diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml index efddde720d..5873e7aee6 100644 --- a/.github/workflows/selfdrive_tests.yaml +++ b/.github/workflows/selfdrive_tests.yaml @@ -204,11 +204,12 @@ jobs: $UNIT_TEST selfdrive/boardd && \ $UNIT_TEST selfdrive/controls && \ $UNIT_TEST selfdrive/monitoring && \ - $UNIT_TEST selfdrive/loggerd && \ + $UNIT_TEST system/loggerd && \ $UNIT_TEST selfdrive/car && \ $UNIT_TEST selfdrive/locationd && \ + $UNIT_TEST system/ubloxd && \ selfdrive/locationd/test/_test_locationd_lib.py && \ - ./selfdrive/locationd/test/test_glonass_runner && \ + ./system/ubloxd/tests/test_glonass_runner && \ $UNIT_TEST selfdrive/athena && \ $UNIT_TEST selfdrive/thermald && \ $UNIT_TEST system/hardware/tici && \ @@ -219,7 +220,7 @@ jobs: ./common/tests/test_util && \ ./common/tests/test_swaglog && \ ./selfdrive/boardd/tests/test_boardd_usbprotocol && \ - ./selfdrive/loggerd/tests/test_logger &&\ + ./system/loggerd/tests/test_logger &&\ ./system/proclogd/tests/test_proclog && \ ./tools/replay/tests/test_replay && \ ./tools/cabana/tests/test_cabana && \ diff --git a/.gitignore b/.gitignore index 2b283d3b11..be6629f212 100644 --- a/.gitignore +++ b/.gitignore @@ -46,9 +46,6 @@ selfdrive/mapd/default_speeds_by_region.json system/proclogd/proclogd selfdrive/ui/_ui selfdrive/test/longitudinal_maneuvers/out -selfdrive/visiond/visiond -selfdrive/sensord/_gpsd -selfdrive/sensord/_sensord system/camerad/camerad system/camerad/test/ae_gray_test selfdrive/modeld/_modeld diff --git a/Jenkinsfile b/Jenkinsfile index 30c045e419..4e80b5fa3c 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -157,10 +157,11 @@ pipeline { phone_steps("tici-common", [ ["build", "cd selfdrive/manager && ./build.py"], ["test power draw", "python system/hardware/tici/test_power_draw.py"], - ["test loggerd", "python selfdrive/loggerd/tests/test_loggerd.py"], - ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python selfdrive/loggerd/tests/test_encoder.py"], - ["test pigeond", "python selfdrive/sensord/tests/test_pigeond.py"], + ["test loggerd", "python system/loggerd/tests/test_loggerd.py"], + ["test encoder", "LD_LIBRARY_PATH=/usr/local/lib python system/loggerd/tests/test_encoder.py"], + ["test pigeond", "python system/sensord/tests/test_pigeond.py"], ["test manager", "python selfdrive/manager/test/test_manager.py"], + ["test pandad", "python selfdrive/boardd/tests/test_pandad.py"], ]) } } @@ -192,11 +193,11 @@ pipeline { steps { phone_steps("tici-lsmc", [ ["build", "cd selfdrive/manager && ./build.py"], - ["test sensord", "cd selfdrive/sensord/tests && python -m unittest test_sensord.py"], + ["test sensord", "cd system/sensord/tests && python -m unittest test_sensord.py"], ]) phone_steps("tici-bmx-lsm", [ ["build", "cd selfdrive/manager && ./build.py"], - ["test sensord", "cd selfdrive/sensord/tests && python -m unittest test_sensord.py"], + ["test sensord", "cd system/sensord/tests && python -m unittest test_sensord.py"], ]) } } diff --git a/README.md b/README.md index 4896d9ff72..a71a9e671e 100755 --- a/README.md +++ b/README.md @@ -108,7 +108,10 @@ Directory Structure ├── clocksd # Broadcasts current time ├── hardware # Hardware abstraction classes ├── logcatd # systemd journal as a service - └── proclogd # Logs information from /proc + ├── loggerd # Logger and uploader of car data + ├── proclogd # Logs information from /proc + ├── sensord # IMU interface code + └── ubloxd # u-blox GNSS module interface code └── selfdrive # Code needed to drive the car ├── assets # Fonts, images, and sounds for UI ├── athena # Allows communication with the app @@ -117,12 +120,10 @@ Directory Structure ├── controls # Planning and controls ├── debug # Tools to help you debug and do car ports ├── locationd # Precise localization and vehicle parameter estimation - ├── loggerd # Logger and uploader of car data ├── manager # Daemon that starts/stops all other daemons as needed ├── modeld # Driving and monitoring model runners ├── monitoring # Daemon to determine driver attention ├── navd # Turn-by-turn navigation - ├── sensord # IMU interface code ├── test # Unit tests, system tests, and a car simulator └── ui # The UI diff --git a/RELEASES.md b/RELEASES.md index f71810784a..9cfcbafea1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,6 +1,7 @@ Version 0.9.2 (2023-03-XX) ======================== * Draw MPC path instead of model predicted path, this is a more accurate representation of what the car will do. +* Škoda Fabia 2022-23 support thanks to jyoung8607! Version 0.9.1 (2023-02-28) ======================== diff --git a/SConstruct b/SConstruct index 007931b7f5..387d2e76f4 100644 --- a/SConstruct +++ b/SConstruct @@ -398,6 +398,7 @@ SConscript([ 'system/camerad/SConscript', 'system/clocksd/SConscript', 'system/proclogd/SConscript', + 'system/ubloxd/SConscript', ]) if arch != "Darwin": SConscript(['system/logcatd/SConscript']) @@ -424,10 +425,10 @@ SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript']) SConscript(['selfdrive/boardd/SConscript']) -SConscript(['selfdrive/loggerd/SConscript']) +SConscript(['system/loggerd/SConscript']) SConscript(['selfdrive/locationd/SConscript']) -SConscript(['selfdrive/sensord/SConscript']) +SConscript(['system/sensord/SConscript']) SConscript(['selfdrive/ui/SConscript']) SConscript(['selfdrive/navd/SConscript']) diff --git a/cereal b/cereal index 42f84fd85d..9888e0476c 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 42f84fd85d06c0fc85371daa2b4820fca49d763e +Subproject commit 9888e0476c05069d46f273569467e4371b2d8690 diff --git a/common/params.cc b/common/params.cc index 2ba4f7e8ab..e74c63bf6a 100644 --- a/common/params.cc +++ b/common/params.cc @@ -99,7 +99,6 @@ std::unordered_map keys = { {"CompletedTrainingVersion", PERSISTENT}, {"ControlsReady", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"CurrentRoute", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, - {"DashcamOverride", PERSISTENT}, {"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"DisablePowerDown", PERSISTENT}, {"ExperimentalMode", PERSISTENT}, diff --git a/docs/CARS.md b/docs/CARS.md index 20155f306b..070d068cab 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 three. All supported cars provide a better experience than any stock system. -# 237 Supported Cars +# 238 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness|Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -161,9 +161,10 @@ A supported vehicle is one that just works when you install a comma three. All s |Subaru|Outback 2020-22|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru B|| |Subaru|XV 2018-19|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A|| |Subaru|XV 2020-21|EyeSight Driver Assistance|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Subaru A|| +|Škoda|Fabia 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533[10](#footnotes)|| |Škoda|Kamiq 2021[7](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533[10](#footnotes)|| |Škoda|Karoq 2019-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| -|Škoda|Kodiaq 2018-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| +|Škoda|Kodiaq 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| |Škoda|Octavia 2015, 2018-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| |Škoda|Octavia RS 2016|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| |Škoda|Scala 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533[10](#footnotes)|| diff --git a/docs/c_docs.rst b/docs/c_docs.rst index 77be7e51d8..5619cc8a51 100644 --- a/docs/c_docs.rst +++ b/docs/c_docs.rst @@ -83,7 +83,7 @@ common sensorsd ^^^^^^^^ .. autodoxygenindex:: - :project: selfdrive_sensord_sensors + :project: system_sensord_sensors boardd ^^^^^^ diff --git a/docs/overview.rst b/docs/overview.rst index cc4c582155..b9a5700528 100644 --- a/docs/overview.rst +++ b/docs/overview.rst @@ -5,7 +5,7 @@ openpilot :maxdepth: 4 Debugging - selfdrive/loggerd/README.md + system/loggerd/README.md Driver Monitoring Process Replay diff --git a/opendbc b/opendbc index 510bfc0695..b7d4a6e271 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 510bfc06954e31257f8d8de17adf92f9a68a1b71 +Subproject commit b7d4a6e2718d9ec3cf436441696528bedb1d44cf diff --git a/panda b/panda index e0e754de2c..b231281c8b 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit e0e754de2c7fdbf943dd02db203b7bb40bf3e9b5 +Subproject commit b231281c8b2c79c46892576dee4c8a56d5e0b2d2 diff --git a/poetry.lock b/poetry.lock index 91e1b5c826..ec4022c81f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -4355,6 +4355,14 @@ python-versions = "*" [package.dependencies] types-urllib3 = "<1.27" +[[package]] +name = "types-tabulate" +version = "0.9.0.1" +description = "Typing stubs for tabulate" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "types-urllib3" version = "1.26.25.1" @@ -4567,7 +4575,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "1.1" python-versions = "~3.8" -content-hash = "9e9495c896e6fd0855803aeaf46513c6c22424b86be820759a8baf27d44e73ee" +content-hash = "669485055bf8d77336509cb7a3878e06aa32431c520825948914d76b57347fde" [metadata.files] adal = [ @@ -6616,7 +6624,6 @@ onnx = [ ] onnx2torch = [ {file = "onnx2torch-1.5.4-py3-none-any.whl", hash = "sha256:fd1a0fe05072bfb9f3d86d9330299b130b41f11bd4ae634db17078974e711725"}, - {file = "onnx2torch-1.5.4.tar.gz", hash = "sha256:df837b557a63540223d85fde4a1d679fde0ca8d8bb89d5379c030b01eddc9c24"}, ] onnxoptimizer = [ {file = "onnxoptimizer-0.3.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:e73a5e2e3ca4db9bff54f7131768749c861677b97ee811a136fcf1a52783cf6e"}, @@ -7002,7 +7009,6 @@ pycryptodome = [ {file = "pycryptodome-3.15.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:7c9ed8aa31c146bef65d89a1b655f5f4eab5e1120f55fc297713c89c9e56ff0b"}, {file = "pycryptodome-3.15.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:5099c9ca345b2f252f0c28e96904643153bae9258647585e5e6f649bb7a1844a"}, {file = "pycryptodome-3.15.0-cp27-cp27m-manylinux2014_aarch64.whl", hash = "sha256:2ec709b0a58b539a4f9d33fb8508264c3678d7edb33a68b8906ba914f71e8c13"}, - {file = "pycryptodome-3.15.0-cp27-cp27m-musllinux_1_1_aarch64.whl", hash = "sha256:2ae53125de5b0d2c95194d957db9bb2681da8c24d0fb0fe3b056de2bcaf5d837"}, {file = "pycryptodome-3.15.0-cp27-cp27m-win32.whl", hash = "sha256:fd2184aae6ee2a944aaa49113e6f5787cdc5e4db1eb8edb1aea914bd75f33a0c"}, {file = "pycryptodome-3.15.0-cp27-cp27m-win_amd64.whl", hash = "sha256:7e3a8f6ee405b3bd1c4da371b93c31f7027944b2bcce0697022801db93120d83"}, {file = "pycryptodome-3.15.0-cp27-cp27mu-manylinux1_i686.whl", hash = "sha256:b9c5b1a1977491533dfd31e01550ee36ae0249d78aae7f632590db833a5012b8"}, @@ -7010,14 +7016,12 @@ pycryptodome = [ {file = "pycryptodome-3.15.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:2aa55aae81f935a08d5a3c2042eb81741a43e044bd8a81ea7239448ad751f763"}, {file = "pycryptodome-3.15.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:c3640deff4197fa064295aaac10ab49a0d55ef3d6a54ae1499c40d646655c89f"}, {file = "pycryptodome-3.15.0-cp27-cp27mu-manylinux2014_aarch64.whl", hash = "sha256:045d75527241d17e6ef13636d845a12e54660aa82e823b3b3341bcf5af03fa79"}, - {file = "pycryptodome-3.15.0-cp27-cp27mu-musllinux_1_1_aarch64.whl", hash = "sha256:eb6fce570869e70cc8ebe68eaa1c26bed56d40ad0f93431ee61d400525433c54"}, {file = "pycryptodome-3.15.0-cp35-abi3-macosx_10_9_x86_64.whl", hash = "sha256:9ee40e2168f1348ae476676a2e938ca80a2f57b14a249d8fe0d3cdf803e5a676"}, {file = "pycryptodome-3.15.0-cp35-abi3-manylinux1_i686.whl", hash = "sha256:4c3ccad74eeb7b001f3538643c4225eac398c77d617ebb3e57571a897943c667"}, {file = "pycryptodome-3.15.0-cp35-abi3-manylinux1_x86_64.whl", hash = "sha256:1b22bcd9ec55e9c74927f6b1f69843cb256fb5a465088ce62837f793d9ffea88"}, {file = "pycryptodome-3.15.0-cp35-abi3-manylinux2010_i686.whl", hash = "sha256:57f565acd2f0cf6fb3e1ba553d0cb1f33405ec1f9c5ded9b9a0a5320f2c0bd3d"}, {file = "pycryptodome-3.15.0-cp35-abi3-manylinux2010_x86_64.whl", hash = "sha256:4b52cb18b0ad46087caeb37a15e08040f3b4c2d444d58371b6f5d786d95534c2"}, {file = "pycryptodome-3.15.0-cp35-abi3-manylinux2014_aarch64.whl", hash = "sha256:092a26e78b73f2530b8bd6b3898e7453ab2f36e42fd85097d705d6aba2ec3e5e"}, - {file = "pycryptodome-3.15.0-cp35-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:50ca7e587b8e541eb6c192acf92449d95377d1f88908c0a32ac5ac2703ebe28b"}, {file = "pycryptodome-3.15.0-cp35-abi3-win32.whl", hash = "sha256:e244ab85c422260de91cda6379e8e986405b4f13dc97d2876497178707f87fc1"}, {file = "pycryptodome-3.15.0-cp35-abi3-win_amd64.whl", hash = "sha256:c77126899c4b9c9827ddf50565e93955cb3996813c18900c16b2ea0474e130e9"}, {file = "pycryptodome-3.15.0-pp27-pypy_73-macosx_10_9_x86_64.whl", hash = "sha256:9eaadc058106344a566dc51d3d3a758ab07f8edde013712bc8d22032a86b264f"}, @@ -7659,18 +7663,6 @@ setproctitle = [ {file = "setproctitle-1.3.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7f2719a398e1a2c01c2a63bf30377a34d0b6ef61946ab9cf4d550733af8f1ef1"}, {file = "setproctitle-1.3.2-cp310-cp310-win32.whl", hash = "sha256:e425be62524dc0c593985da794ee73eb8a17abb10fe692ee43bb39e201d7a099"}, {file = "setproctitle-1.3.2-cp310-cp310-win_amd64.whl", hash = "sha256:e85e50b9c67854f89635a86247412f3ad66b132a4d8534ac017547197c88f27d"}, - {file = "setproctitle-1.3.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:2a97d51c17d438cf5be284775a322d57b7ca9505bb7e118c28b1824ecaf8aeaa"}, - {file = "setproctitle-1.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:587c7d6780109fbd8a627758063d08ab0421377c0853780e5c356873cdf0f077"}, - {file = "setproctitle-1.3.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d17c8bd073cbf8d141993db45145a70b307385b69171d6b54bcf23e5d644de"}, - {file = "setproctitle-1.3.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e932089c35a396dc31a5a1fc49889dd559548d14cb2237adae260382a090382e"}, - {file = "setproctitle-1.3.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e4f8f12258a8739c565292a551c3db62cca4ed4f6b6126664e2381acb4931bf"}, - {file = "setproctitle-1.3.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:570d255fd99c7f14d8f91363c3ea96bd54f8742275796bca67e1414aeca7d8c3"}, - {file = "setproctitle-1.3.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a8e0881568c5e6beff91ef73c0ec8ac2a9d3ecc9edd6bd83c31ca34f770910c4"}, - {file = "setproctitle-1.3.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:4bba3be4c1fabf170595b71f3af46c6d482fbe7d9e0563999b49999a31876f77"}, - {file = "setproctitle-1.3.2-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:37ece938110cab2bb3957e3910af8152ca15f2b6efdf4f2612e3f6b7e5459b80"}, - {file = "setproctitle-1.3.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:db684d6bbb735a80bcbc3737856385b55d53f8a44ce9b46e9a5682c5133a9bf7"}, - {file = "setproctitle-1.3.2-cp311-cp311-win32.whl", hash = "sha256:ca58cd260ea02759238d994cfae844fc8b1e206c684beb8f38877dcab8451dfc"}, - {file = "setproctitle-1.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:88486e6cce2a18a033013d17b30a594f1c5cb42520c49c19e6ade40b864bb7ff"}, {file = "setproctitle-1.3.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:92c626edc66169a1b09e9541b9c0c9f10488447d8a2b1d87c8f0672e771bc927"}, {file = "setproctitle-1.3.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710e16fa3bade3b026907e4a5e841124983620046166f355bbb84be364bf2a02"}, {file = "setproctitle-1.3.2-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1f29b75e86260b0ab59adb12661ef9f113d2f93a59951373eb6d68a852b13e83"}, @@ -8066,6 +8058,10 @@ types-requests = [ {file = "types-requests-2.28.11.2.tar.gz", hash = "sha256:fdcd7bd148139fb8eef72cf4a41ac7273872cad9e6ada14b11ff5dfdeee60ed3"}, {file = "types_requests-2.28.11.2-py3-none-any.whl", hash = "sha256:14941f8023a80b16441b3b46caffcbfce5265fd14555844d6029697824b5a2ef"}, ] +types-tabulate = [ + {file = "types-tabulate-0.9.0.1.tar.gz", hash = "sha256:e486292c279f19247865bdabe802419740a0e74b53444e7f7a8009e08129da5d"}, + {file = "types_tabulate-0.9.0.1-py3-none-any.whl", hash = "sha256:be2ea0de05f615ccfcbadf6206aa720e265955eb1de23e343aec9d8bf3fa9aaa"}, +] types-urllib3 = [ {file = "types-urllib3-1.26.25.1.tar.gz", hash = "sha256:a948584944b2412c9a74b9cf64f6c48caf8652cb88b38361316f6d15d8a184cd"}, {file = "types_urllib3-1.26.25.1-py3-none-any.whl", hash = "sha256:f6422596cc9ee5fdf68f9d547f541096a20c2dcfd587e37c804c9ea720bf5cb2"}, diff --git a/pyproject.toml b/pyproject.toml index 6b4b0bb5fa..b1ad273cd7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -59,6 +59,7 @@ urllib3 = "^1.26.10" utm = "^0.7.0" websocket_client = "^1.3.3" polyline = "^1.4.0" +types-tabulate = "^0.9.0.1" [tool.poetry.group.dev.dependencies] diff --git a/release/files_common b/release/files_common index 5b310d5c80..a20f71018b 100644 --- a/release/files_common +++ b/release/files_common @@ -219,14 +219,15 @@ system/hardware/pc/__init__.py system/hardware/pc/hardware.h system/hardware/pc/hardware.py +system/ubloxd/.gitignore +system/ubloxd/SConscript +system/ubloxd/generated/* +system/ubloxd/*.h +system/ubloxd/*.cc + selfdrive/locationd/__init__.py -selfdrive/locationd/.gitignore selfdrive/locationd/SConscript -selfdrive/locationd/ubloxd.cc -selfdrive/locationd/ublox_msg.cc -selfdrive/locationd/ublox_msg.h -selfdrive/locationd/generated/* - +selfdrive/locationd/.gitignore selfdrive/locationd/laikad.py selfdrive/locationd/locationd.h selfdrive/locationd/locationd.cc @@ -253,35 +254,36 @@ system/proclogd/main.cc system/proclogd/proclog.cc system/proclogd/proclog.h -selfdrive/loggerd/.gitignore -selfdrive/loggerd/SConscript -selfdrive/loggerd/encoder/encoder.cc -selfdrive/loggerd/encoder/encoder.h -selfdrive/loggerd/encoder/v4l_encoder.cc -selfdrive/loggerd/encoder/v4l_encoder.h -selfdrive/loggerd/video_writer.cc -selfdrive/loggerd/video_writer.h -selfdrive/loggerd/logger.cc -selfdrive/loggerd/logger.h -selfdrive/loggerd/loggerd.cc -selfdrive/loggerd/loggerd.h -selfdrive/loggerd/encoderd.cc -selfdrive/loggerd/bootlog.cc -selfdrive/loggerd/encoder/ffmpeg_encoder.cc -selfdrive/loggerd/encoder/ffmpeg_encoder.h - -selfdrive/loggerd/__init__.py -selfdrive/loggerd/config.py -selfdrive/loggerd/uploader.py -selfdrive/loggerd/deleter.py -selfdrive/loggerd/xattr_cache.py - -selfdrive/sensord/SConscript -selfdrive/sensord/sensors_qcom2.cc -selfdrive/sensord/sensors/*.cc -selfdrive/sensord/sensors/*.h -selfdrive/sensord/sensord -selfdrive/sensord/pigeond.py +system/loggerd/.gitignore +system/loggerd/SConscript +system/loggerd/encoder/encoder.cc +system/loggerd/encoder/encoder.h +system/loggerd/encoder/v4l_encoder.cc +system/loggerd/encoder/v4l_encoder.h +system/loggerd/video_writer.cc +system/loggerd/video_writer.h +system/loggerd/logger.cc +system/loggerd/logger.h +system/loggerd/loggerd.cc +system/loggerd/loggerd.h +system/loggerd/encoderd.cc +system/loggerd/bootlog.cc +system/loggerd/encoder/ffmpeg_encoder.cc +system/loggerd/encoder/ffmpeg_encoder.h + +system/loggerd/__init__.py +system/loggerd/config.py +system/loggerd/uploader.py +system/loggerd/deleter.py +system/loggerd/xattr_cache.py + +system/sensord/.gitignore +system/sensord/SConscript +system/sensord/sensors_qcom2.cc +system/sensord/sensors/*.cc +system/sensord/sensors/*.h +system/sensord/sensord +system/sensord/pigeond.py selfdrive/thermald/thermald.py selfdrive/thermald/power_monitoring.py @@ -577,13 +579,14 @@ opendbc/tesla_can.dbc opendbc/tesla_radar.dbc opendbc/tesla_powertrain.dbc -tinygrad_repo/accel/opencl/* -tinygrad_repo/tinygrad/llops/ops_opencl.py tinygrad_repo/openpilot/compile.py tinygrad_repo/extra/onnx.py +tinygrad_repo/extra/onnx_ops.py tinygrad_repo/extra/thneed.py tinygrad_repo/extra/utils.py -tinygrad_repo/tinygrad/llops/ops_gpu.py -tinygrad_repo/tinygrad/shape/* +tinygrad_repo/tinygrad/codegen/ast.py +tinygrad_repo/tinygrad/codegen/gpu.py tinygrad_repo/tinygrad/nn/* +tinygrad_repo/tinygrad/runtime/ops_gpu.py +tinygrad_repo/tinygrad/shape/* tinygrad_repo/tinygrad/*.py diff --git a/release/files_tici b/release/files_tici index c8abd720d5..b4e0c50516 100644 --- a/release/files_tici +++ b/release/files_tici @@ -13,7 +13,7 @@ system/camerad/cameras/camera_util.cc system/camerad/cameras/camera_util.h system/camerad/cameras/real_debayer.cl -selfdrive/sensord/rawgps/* +system/sensord/rawgps/* selfdrive/ui/qt/spinner_larch64 selfdrive/ui/qt/text_larch64 diff --git a/selfdrive/athena/athenad.py b/selfdrive/athena/athenad.py index d1cc4cea83..7cb6d5b845 100755 --- a/selfdrive/athena/athenad.py +++ b/selfdrive/athena/athenad.py @@ -36,8 +36,8 @@ from common.file_helpers import CallbackReader from common.params import Params from common.realtime import sec_since_boot, set_core_affinity from system.hardware import HARDWARE, PC, AGNOS -from selfdrive.loggerd.config import ROOT -from selfdrive.loggerd.xattr_cache import getxattr, setxattr +from system.loggerd.config import ROOT +from system.loggerd.xattr_cache import getxattr, setxattr from selfdrive.statsd import STATS_DIR from system.swaglog import SWAGLOG_DIR, cloudlog from system.version import get_commit, get_origin, get_short_branch, get_version diff --git a/selfdrive/boardd/pandad.py b/selfdrive/boardd/pandad.py index f61d9ee1a6..f292b921cf 100755 --- a/selfdrive/boardd/pandad.py +++ b/selfdrive/boardd/pandad.py @@ -84,9 +84,9 @@ def main() -> NoReturn: params.remove("PandaSignatures") # Flash all Pandas in DFU mode - for p in PandaDFU.list(): - cloudlog.info(f"Panda in DFU mode found, flashing recovery {p}") - PandaDFU(p).recover() + for serial in PandaDFU.list(): + cloudlog.info(f"Panda in DFU mode found, flashing recovery {serial}") + PandaDFU(serial).recover() time.sleep(1) panda_serials = Panda.list() diff --git a/selfdrive/boardd/tests/test_pandad.py b/selfdrive/boardd/tests/test_pandad.py new file mode 100755 index 0000000000..3b2369b39b --- /dev/null +++ b/selfdrive/boardd/tests/test_pandad.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +import time +import unittest + +import cereal.messaging as messaging +from panda import Panda +from selfdrive.test.helpers import phone_only +from selfdrive.manager.process_config import managed_processes +from system.hardware import HARDWARE + + +class TestPandad(unittest.TestCase): + + def tearDown(self): + managed_processes['pandad'].stop() + + def _wait_for_boardd(self): + sm = messaging.SubMaster(['peripheralState']) + for _ in range(30): + sm.update(1000) + if sm.updated['peripheralState']: + break + + if not sm.updated['peripheralState']: + raise Exception("boardd failed to start") + + @phone_only + def test_in_dfu(self): + HARDWARE.recover_internal_panda() + time.sleep(1) + + managed_processes['pandad'].start() + self._wait_for_boardd() + + @phone_only + def test_in_bootstub(self): + with Panda() as p: + p.reset(enter_bootstub=True) + assert p.bootstub + managed_processes['pandad'].start() + self._wait_for_boardd() + + #def test_out_of_date_fw(self): + # pass + + +if __name__ == "__main__": + unittest.main() diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 370772c902..dc82f56197 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -180,7 +180,7 @@ def get_car(logcan, sendcan, experimental_long_allowed, num_pandas=1): candidate, fingerprints, vin, car_fw, source, exact_match = fingerprint(logcan, sendcan, num_pandas) if candidate is None: - cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints) + cloudlog.event("car doesn't match any fingerprints", fingerprints=fingerprints, error=True) candidate = "mock" CarInterface, CarController, CarState = interfaces[candidate] diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 2af5246b88..9f00484f34 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -99,7 +99,7 @@ FINGERPRINTS = { 55: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 8, 926: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8 }, { - 55: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 926: 3, 937: 8, 947: 8, 948: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8 + 55: 8, 58: 6, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 4, 564: 4, 571: 3, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 678: 8, 680: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 779: 8, 784: 8, 792: 8, 799: 8, 800: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 924: 3, 926: 3, 937: 8, 947: 8, 948: 8, 956: 8, 969: 4, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1537: 8, 1538: 8, 1562: 8 }], CAR.PACIFICA_2020: [{ 55: 8, 179: 8, 181: 8, 257: 5, 258: 8, 264: 8, 268: 8, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 294: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 469: 8, 480: 8, 500: 8, 501: 8, 512: 8, 514: 8, 516: 7, 517: 7, 520: 8, 524: 8, 526: 6, 528: 8, 532: 8, 536: 8, 542: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 624: 8, 625: 8, 632: 8, 639: 8, 650: 8, 656: 4, 658: 6, 660: 8, 669: 3, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 711: 8, 719: 8, 720: 6, 729: 5, 736: 8, 746: 5, 752: 2, 754: 8, 760: 8, 764: 8, 766: 8, 770: 8, 773: 8, 776: 8, 779: 8, 782: 8, 784: 8, 792: 8, 793: 8, 794: 8, 795: 8, 799: 8, 800: 8, 801: 8, 802: 8, 803: 8, 804: 8, 808: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 832: 8, 838: 2, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 886: 8, 897: 8, 906: 8, 924: 8, 926: 3, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 962: 8, 969: 4, 973: 8, 974: 5, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 7, 1225: 8, 1227: 8, 1235: 8, 1242: 8, 1246: 8, 1250: 8, 1251: 8, 1252: 8, 1284: 8, 1543: 8, 1568: 8, 1570: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1867: 8, 1875: 8, 1882: 8, 1886: 8, 1890: 8, 1891: 8, 1892: 8, 1898: 8, 2015: 8, 2016: 8, 2017:8, 2024: 8, 2025: 8 diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 3bc56eb9dd..50c7d93987 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -165,6 +165,7 @@ FW_VERSIONS = { b'M1MC-14D003-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.abs, 0x760, None): [ + b'L1MC-2D053-BA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'L1MC-2D053-BB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'L1MC-2D053-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'L1MC-2D053-KB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', @@ -178,6 +179,7 @@ FW_VERSIONS = { b'LC5T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.engine, 0x7E0, None): [ + b'LB5A-14C204-BUJ\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'LB5A-14C204-EAC\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'MB5A-14C204-MD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'MB5A-14C204-RC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index 02e37492d3..4ca7c0a16c 100644 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -206,6 +206,7 @@ routes = [ CarTestRoute("0cd0b7f7e31a3853|2021-12-03--03-12-05", VOLKSWAGEN.AUDI_Q3_MK2), CarTestRoute("8f205bdd11bcbb65|2021-03-26--01-00-17", VOLKSWAGEN.SEAT_ATECA_MK1), CarTestRoute("fc6b6c9a3471c846|2021-05-27--13-39-56", VOLKSWAGEN.SEAT_LEON_MK3), + CarTestRoute("0bbe367c98fa1538|2023-03-04--17-46-11", VOLKSWAGEN.SKODA_FABIA_MK4), CarTestRoute("12d6ae3057c04b0d|2021-09-15--00-04-07", VOLKSWAGEN.SKODA_KAMIQ_MK1), CarTestRoute("12d6ae3057c04b0d|2021-09-04--21-21-21", VOLKSWAGEN.SKODA_KAROQ_MK1), CarTestRoute("90434ff5d7c8d603|2021-03-15--12-07-31", VOLKSWAGEN.SKODA_KODIAQ_MK1), diff --git a/selfdrive/car/torque_data/substitute.yaml b/selfdrive/car/torque_data/substitute.yaml index 61243424f0..696d9829d1 100644 --- a/selfdrive/car/torque_data/substitute.yaml +++ b/selfdrive/car/torque_data/substitute.yaml @@ -56,6 +56,7 @@ CADILLAC ATS Premium Performance 2018: CHEVROLET VOLT PREMIER 2017 CHEVROLET MALIBU PREMIER 2017: CHEVROLET VOLT PREMIER 2017 HOLDEN ASTRA RS-V BK 2017: CHEVROLET VOLT PREMIER 2017 +SKODA FABIA 4TH GEN: VOLKSWAGEN GOLF 7TH GEN SKODA OCTAVIA 3RD GEN: SKODA SUPERB 3RD GEN SKODA SCALA 1ST GEN: SKODA SUPERB 3RD GEN SKODA KODIAQ 1ST GEN: SKODA SUPERB 3RD GEN diff --git a/selfdrive/car/toyota/values.py b/selfdrive/car/toyota/values.py index 35e2db8b1e..a8e143e80a 100644 --- a/selfdrive/car/toyota/values.py +++ b/selfdrive/car/toyota/values.py @@ -1637,6 +1637,7 @@ FW_VERSIONS = { b'\x028966333S8000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', b'\x028966333T0100\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', b'\x028966333V4000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', + b'\x028966333W1000\x00\x00\x00\x00897CF3305001\x00\x00\x00\x00', b'\x02896633T09000\x00\x00\x00\x00897CF3307001\x00\x00\x00\x00', b'\x01896633T38000\x00\x00\x00\x00', b'\x01896633T58000\x00\x00\x00\x00', diff --git a/selfdrive/car/volkswagen/carstate.py b/selfdrive/car/volkswagen/carstate.py index 64d1246880..f3cd2808a8 100644 --- a/selfdrive/car/volkswagen/carstate.py +++ b/selfdrive/car/volkswagen/carstate.py @@ -228,13 +228,13 @@ class CarState(CarStateBase): ret.cruiseState.available = bool(pt_cp.vl["Motor_5"]["GRA_Hauptschalter"]) ret.cruiseState.enabled = pt_cp.vl["Motor_2"]["GRA_Status"] in (1, 2) if self.CP.pcmCruise: - ret.accFaulted = ext_cp.vl["ACC_GRA_Anziege"]["ACA_StaACC"] in (6, 7) + ret.accFaulted = ext_cp.vl["ACC_GRA_Anzeige"]["ACA_StaACC"] in (6, 7) else: ret.accFaulted = pt_cp.vl["Motor_2"]["GRA_Status"] == 3 # Update ACC setpoint. When the setpoint reads as 255, the driver has not # yet established an ACC setpoint, so treat it as zero. - ret.cruiseState.speed = ext_cp.vl["ACC_GRA_Anziege"]["ACA_V_Wunsch"] * CV.KPH_TO_MS + ret.cruiseState.speed = ext_cp.vl["ACC_GRA_Anzeige"]["ACA_V_Wunsch"] * CV.KPH_TO_MS if ret.cruiseState.speed > 70: # 255 kph in m/s == no current setpoint ret.cruiseState.speed = 0 @@ -516,12 +516,12 @@ class PqExtraSignals: # Additional signal and message lists for optional or bus-portable controllers fwd_radar_signals = [ ("ACS_Typ_ACC", "ACC_System"), # Basic vs FtS (no SnG support on PQ) - ("ACA_StaACC", "ACC_GRA_Anziege"), # ACC drivetrain coordinator status - ("ACA_V_Wunsch", "ACC_GRA_Anziege"), # ACC set speed + ("ACA_StaACC", "ACC_GRA_Anzeige"), # ACC drivetrain coordinator status + ("ACA_V_Wunsch", "ACC_GRA_Anzeige"), # ACC set speed ] fwd_radar_checks = [ ("ACC_System", 50), # From J428 ACC radar control module - ("ACC_GRA_Anziege", 25), # From J428 ACC radar control module + ("ACC_GRA_Anzeige", 25), # From J428 ACC radar control module ] bsm_radar_signals = [ ("SWA_Infostufe_SWA_li", "SWA_1"), # Blind spot object info, left diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 521c68184d..2f8bd8661b 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -187,6 +187,10 @@ class CarInterface(CarInterfaceBase): ret.mass = 1227 + STD_CARGO_KG ret.wheelbase = 2.64 + elif candidate == CAR.SKODA_FABIA_MK4: + ret.mass = 1266 + STD_CARGO_KG + ret.wheelbase = 2.56 + elif candidate == CAR.SKODA_KAMIQ_MK1: ret.mass = 1265 + STD_CARGO_KG ret.wheelbase = 2.66 diff --git a/selfdrive/car/volkswagen/pqcan.py b/selfdrive/car/volkswagen/pqcan.py index 130f107950..84200c2921 100644 --- a/selfdrive/car/volkswagen/pqcan.py +++ b/selfdrive/car/volkswagen/pqcan.py @@ -88,4 +88,4 @@ def create_acc_hud_control(packer, bus, acc_hud_status, set_speed, lead_distance # kmh_mph handling probably needed to resolve rounding errors in displayed setpoint } - return packer.make_can_msg("ACC_GRA_Anziege", bus, values) + return packer.make_can_msg("ACC_GRA_Anzeige", bus, values) diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 4eef1307be..694b4006f8 100755 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -36,7 +36,7 @@ class CarControllerParams: if CP.carFingerprint in PQ_CARS: self.LDW_STEP = 5 # LDW_1 message frequency 20Hz - self.ACC_HUD_STEP = 4 # ACC_GRA_Anziege frequency 25Hz + self.ACC_HUD_STEP = 4 # ACC_GRA_Anzeige frequency 25Hz self.STEER_DRIVER_ALLOWANCE = 80 # Driver intervention threshold 0.8 Nm self.STEER_DELTA_UP = 6 # Max HCA reached in 1.00s (STEER_MAX / (50Hz * 1.00)) self.STEER_DELTA_DOWN = 10 # Min HCA reached in 0.60s (STEER_MAX / (50Hz * 0.60)) @@ -129,6 +129,7 @@ class CAR: AUDI_Q3_MK2 = "AUDI Q3 2ND GEN" # Chassis 8U/F3/FS, Mk2 Audi Q3 and variants SEAT_ATECA_MK1 = "SEAT ATECA 1ST GEN" # Chassis 5F, Mk1 SEAT Ateca and CUPRA Ateca SEAT_LEON_MK3 = "SEAT LEON 3RD GEN" # Chassis 5F, Mk3 SEAT Leon and variants + SKODA_FABIA_MK4 = "SKODA FABIA 4TH GEN" # Chassis PJ, Mk4 Skoda Fabia SKODA_KAMIQ_MK1 = "SKODA KAMIQ 1ST GEN" # Chassis NW, Mk1 Skoda Kamiq SKODA_KAROQ_MK1 = "SKODA KAROQ 1ST GEN" # Chassis NU, Mk1 Skoda Karoq SKODA_KODIAQ_MK1 = "SKODA KODIAQ 1ST GEN" # Chassis NS, Mk1 Skoda Kodiaq @@ -239,9 +240,10 @@ CAR_INFO: Dict[str, Union[VWCarInfo, List[VWCarInfo]]] = { CAR.AUDI_Q3_MK2: VWCarInfo("Audi Q3 2019-23"), CAR.SEAT_ATECA_MK1: VWCarInfo("SEAT Ateca 2018"), CAR.SEAT_LEON_MK3: VWCarInfo("SEAT Leon 2014-20"), + CAR.SKODA_FABIA_MK4: VWCarInfo("Škoda Fabia 2022-23", footnotes=[Footnote.VW_MQB_A0]), CAR.SKODA_KAMIQ_MK1: VWCarInfo("Škoda Kamiq 2021", footnotes=[Footnote.VW_MQB_A0, Footnote.KAMIQ]), CAR.SKODA_KAROQ_MK1: VWCarInfo("Škoda Karoq 2019-21"), - CAR.SKODA_KODIAQ_MK1: VWCarInfo("Škoda Kodiaq 2018-19"), + CAR.SKODA_KODIAQ_MK1: VWCarInfo("Škoda Kodiaq 2017-23"), CAR.SKODA_SCALA_MK1: VWCarInfo("Škoda Scala 2020", footnotes=[Footnote.VW_MQB_A0]), CAR.SKODA_SUPERB_MK3: VWCarInfo("Škoda Superb 2015-22"), CAR.SKODA_OCTAVIA_MK3: [ @@ -1009,6 +1011,23 @@ FW_VERSIONS = { b'\xf1\x875Q0907572P \xf1\x890682', ], }, + CAR.SKODA_FABIA_MK4: { + (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8705E906018CF\xf1\x891905', + ], + (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x870CW300051M \xf1\x891936', + ], + (Ecu.srs, 0x715, None): [ + b'\xf1\x875QF959655AT\xf1\x890755\xf1\x82\x1311110011110011111100110200--1111120749', + ], + (Ecu.eps, 0x712, None): [ + b'\xf1\x872Q1909144S \xf1\x896042', + ], + (Ecu.fwdRadar, 0x757, None): [ + b'\xf1\x872Q0907572AA\xf1\x890396', + ], + }, CAR.SKODA_KAMIQ_MK1: { (Ecu.engine, 0x7e0, None): [ b'\xf1\x8705C906032M \xf1\x891333', @@ -1052,17 +1071,20 @@ FW_VERSIONS = { (Ecu.engine, 0x7e0, None): [ b'\xf1\x8704E906027DD\xf1\x893123', b'\xf1\x8704L906026DE\xf1\x895418', + b'\xf1\x8704L906026EJ\xf1\x893661', b'\xf1\x8704L906026HT\xf1\x893617', b'\xf1\x875NA907115E \xf1\x890003', b'\xf1\x875NA907115E \xf1\x890005', ], (Ecu.transmission, 0x7e1, None): [ b'\xf1\x870D9300043 \xf1\x895202', + b'\xf1\x870DL300011N \xf1\x892014', b'\xf1\x870DL300012M \xf1\x892107', b'\xf1\x870DL300012N \xf1\x892110', b'\xf1\x870DL300013G \xf1\x892119', ], (Ecu.srs, 0x715, None): [ + b'\xf1\x873Q0959655AP\xf1\x890306\xf1\x82\r11110011110011421111314211', b'\xf1\x873Q0959655BJ\xf1\x890703\xf1\x82\x0e1213001211001205212111052100', b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1213001211001244212111442100', b'\xf1\x873Q0959655CN\xf1\x890720\xf1\x82\x0e1213001211001205212112052100', @@ -1077,6 +1099,7 @@ FW_VERSIONS = { (Ecu.fwdRadar, 0x757, None): [ b'\xf1\x872Q0907572Q \xf1\x890342', b'\xf1\x872Q0907572R \xf1\x890372', + b'\xf1\x872Q0907572T \xf1\x890383', b'\xf1\x872Q0907572AA\xf1\x890396', ], }, diff --git a/selfdrive/controls/controlsd.py b/selfdrive/controls/controlsd.py index f49b58212a..1391d6570c 100755 --- a/selfdrive/controls/controlsd.py +++ b/selfdrive/controls/controlsd.py @@ -112,9 +112,6 @@ class Controls: if not self.disengage_on_accelerator: self.CP.alternativeExperience |= ALTERNATIVE_EXPERIENCE.DISABLE_DISENGAGE_ON_GAS - if self.CP.dashcamOnly and self.params.get_bool("DashcamOverride"): - self.CP.dashcamOnly = False - # read params self.is_metric = self.params.get_bool("IsMetric") self.is_ldw_enabled = self.params.get_bool("IsLdwEnabled") diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index d8cf9386d1..14934254af 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -19,6 +19,7 @@ def publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner): ui_send = messaging.new_message('uiPlan') ui_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'modelV2']) uiPlan = ui_send.uiPlan + uiPlan.frameId = sm['modelV2'].frameId uiPlan.position.x = np.interp(plan_odo, model_odo, lateral_planner.lat_mpc.x_sol[:,0]).tolist() uiPlan.position.y = np.interp(plan_odo, model_odo, lateral_planner.lat_mpc.x_sol[:,1]).tolist() uiPlan.position.z = np.interp(plan_odo, model_odo, lateral_planner.path_xyz[:,2]).tolist() diff --git a/selfdrive/locationd/.gitignore b/selfdrive/locationd/.gitignore index 86a228a6ff..11b9f127b2 100644 --- a/selfdrive/locationd/.gitignore +++ b/selfdrive/locationd/.gitignore @@ -1,6 +1,3 @@ -ubloxd -ubloxd_test params_learner paramsd locationd -test/test_glonass_runner diff --git a/selfdrive/locationd/SConscript b/selfdrive/locationd/SConscript index 61a0ed7f42..740f827a49 100644 --- a/selfdrive/locationd/SConscript +++ b/selfdrive/locationd/SConscript @@ -1,20 +1,6 @@ Import('env', 'common', 'cereal', 'messaging', 'libkf', 'transformations') -loc_libs = [cereal, messaging, 'zmq', common, 'capnp', 'kj', 'kaitai', 'pthread'] - -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) - - # 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) +loc_libs = [cereal, messaging, 'zmq', common, 'capnp', 'kj', 'pthread'] ekf_sym_cc = env.SharedObject("#rednose/helpers/ekf_sym.cc") locationd_sources = ["locationd.cc", "models/live_kf.cc", ekf_sym_cc] @@ -25,7 +11,4 @@ lenv.Depends(locationd, libkf) if File("liblocationd.cc").exists(): liblocationd = lenv.SharedLibrary("liblocationd", ["liblocationd.cc"] + locationd_sources, LIBS=loc_libs + transformations) - lenv.Depends(liblocationd, libkf) - -if GetOption('test'): - env.Program("test/test_glonass_runner", ['test/test_glonass_runner.cc', 'test/test_glonass_kaitai.cc', glonass_obj], LIBS=[loc_libs]) \ No newline at end of file + lenv.Depends(liblocationd, libkf) \ No newline at end of file diff --git a/selfdrive/locationd/locationd.h b/selfdrive/locationd/locationd.h index a292a3c936..b7e42a9df8 100755 --- a/selfdrive/locationd/locationd.h +++ b/selfdrive/locationd/locationd.h @@ -14,7 +14,7 @@ #include "common/timing.h" #include "common/util.h" -#include "selfdrive/sensord/sensors/constants.h" +#include "system/sensord/sensors/constants.h" #define VISION_DECIMATION 2 #define SENSOR_DECIMATION 10 #include "selfdrive/locationd/models/live_kf.h" diff --git a/selfdrive/manager/manager.py b/selfdrive/manager/manager.py index 963d94066b..1128097251 100755 --- a/selfdrive/manager/manager.py +++ b/selfdrive/manager/manager.py @@ -29,7 +29,7 @@ def manager_init() -> None: set_time(cloudlog) # save boot log - subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd")) + subprocess.call("./bootlog", cwd=os.path.join(BASEDIR, "system/loggerd")) params = Params() params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START) diff --git a/selfdrive/manager/process_config.py b/selfdrive/manager/process_config.py index 8fc4d94e55..57c42aaaaa 100644 --- a/selfdrive/manager/process_config.py +++ b/selfdrive/manager/process_config.py @@ -17,11 +17,17 @@ def logging(started, params, CP: car.CarParams) -> bool: run = (not CP.notCar) or not params.get_bool("DisableLogging") return started and run +def ublox_available() -> bool: + return os.path.exists('/dev/ttyHS0') and not os.path.exists('/persist/comma/use-quectel-gps') + def ublox(started, params, CP: car.CarParams) -> bool: - use_ublox = os.path.exists('/dev/ttyHS0') and not os.path.exists('/persist/comma/use-quectel-gps') + use_ublox = ublox_available() params.put_bool("UbloxAvailable", use_ublox) return started and use_ublox +def qcomgps(started, params, CP: car.CarParams) -> bool: + return started and not ublox_available() + procs = [ # due to qualcomm kernel bugs SIGKILLing camerad sometimes causes page table corruption NativeProcess("camerad", "system/camerad", ["./camerad"], unkillable=True, callback=driverview), @@ -34,12 +40,12 @@ procs = [ DaemonProcess("manage_athenad", "selfdrive.athena.manage_athenad", "AthenadPid"), NativeProcess("dmonitoringmodeld", "selfdrive/modeld", ["./dmonitoringmodeld"], enabled=(not PC or WEBCAM), callback=driverview), - NativeProcess("encoderd", "selfdrive/loggerd", ["./encoderd"]), - NativeProcess("loggerd", "selfdrive/loggerd", ["./loggerd"], onroad=False, callback=logging), + NativeProcess("encoderd", "system/loggerd", ["./encoderd"]), + NativeProcess("loggerd", "system/loggerd", ["./loggerd"], onroad=False, callback=logging), NativeProcess("modeld", "selfdrive/modeld", ["./modeld"]), NativeProcess("mapsd", "selfdrive/navd", ["./map_renderer"], enabled=False), NativeProcess("navmodeld", "selfdrive/modeld", ["./navmodeld"], enabled=False), - NativeProcess("sensord", "selfdrive/sensord", ["./sensord"], enabled=not PC), + NativeProcess("sensord", "system/sensord", ["./sensord"], enabled=not PC), NativeProcess("ui", "selfdrive/ui", ["./ui"], offroad=True, watchdog_max_dt=(5 if not PC else None)), NativeProcess("soundd", "selfdrive/ui/soundd", ["./soundd"], offroad=True), NativeProcess("locationd", "selfdrive/locationd", ["./locationd"]), @@ -47,21 +53,21 @@ procs = [ PythonProcess("calibrationd", "selfdrive.locationd.calibrationd"), PythonProcess("torqued", "selfdrive.locationd.torqued"), PythonProcess("controlsd", "selfdrive.controls.controlsd"), - PythonProcess("deleter", "selfdrive.loggerd.deleter", offroad=True), + PythonProcess("deleter", "system.loggerd.deleter", offroad=True), PythonProcess("dmonitoringd", "selfdrive.monitoring.dmonitoringd", enabled=(not PC or WEBCAM), callback=driverview), PythonProcess("laikad", "selfdrive.locationd.laikad"), - PythonProcess("rawgpsd", "selfdrive.sensord.rawgps.rawgpsd", enabled=TICI), + PythonProcess("rawgpsd", "system.sensord.rawgps.rawgpsd", enabled=TICI, onroad=False, callback=qcomgps), PythonProcess("navd", "selfdrive.navd.navd"), PythonProcess("pandad", "selfdrive.boardd.pandad", offroad=True), PythonProcess("paramsd", "selfdrive.locationd.paramsd"), - NativeProcess("ubloxd", "selfdrive/locationd", ["./ubloxd"], enabled=TICI, onroad=False, callback=ublox), - PythonProcess("pigeond", "selfdrive.sensord.pigeond", enabled=TICI, onroad=False, callback=ublox), + NativeProcess("ubloxd", "system/ubloxd", ["./ubloxd"], enabled=TICI, onroad=False, callback=ublox), + PythonProcess("pigeond", "system.sensord.pigeond", enabled=TICI, onroad=False, callback=ublox), PythonProcess("plannerd", "selfdrive.controls.plannerd"), PythonProcess("radard", "selfdrive.controls.radard"), PythonProcess("thermald", "selfdrive.thermald.thermald", offroad=True), PythonProcess("tombstoned", "selfdrive.tombstoned", enabled=not PC, offroad=True), PythonProcess("updated", "selfdrive.updated", enabled=not PC, onroad=False, offroad=True), - PythonProcess("uploader", "selfdrive.loggerd.uploader", offroad=True), + PythonProcess("uploader", "system.loggerd.uploader", offroad=True), PythonProcess("statsd", "selfdrive.statsd", offroad=True), # debug procs diff --git a/selfdrive/modeld/SConscript b/selfdrive/modeld/SConscript index 7bbc1b3477..c7e0dc5d86 100644 --- a/selfdrive/modeld/SConscript +++ b/selfdrive/modeld/SConscript @@ -70,7 +70,7 @@ lenv.Program('_dmonitoringmodeld', [ if use_thneed and arch == "larch64" or GetOption('pc_thneed'): fn = File("models/supercombo").abspath - tinygrad_opts = ["NATIVE_EXPLOG=1", "VALIDHACKS=1", "OPTWG=1", "IMAGE=2", "GPU=1", "CLCACHE=0"] + tinygrad_opts = ["NATIVE_EXPLOG=1", "VALIDHACKS=1", "OPTLOCAL=1", "IMAGE=2", "GPU=1", "ENABLE_METHOD_CACHE=1"] if not GetOption('pc_thneed'): # use FLOAT16 on device for speed + don't cache the CL kernels for space tinygrad_opts += ["FLOAT16=1", "PYOPENCL_NO_CACHE=1"] diff --git a/selfdrive/modeld/models/README.md b/selfdrive/modeld/models/README.md index 6b704cbfa8..1bfca8e95a 100644 --- a/selfdrive/modeld/models/README.md +++ b/selfdrive/modeld/models/README.md @@ -2,7 +2,7 @@ To view the architecture of the ONNX networks, you can use [netron](https://netron.app/) ## Supercombo -### Supercombo input format (Full size: 393738 x float32) +### Supercombo input format (Full size: 799906 x float32) * **image stream** * Two consecutive images (256 * 512 * 3 in RGB) recorded at 20 Hz : 393216 = 2 * 6 * 128 * 256 * Each 256 * 512 image is represented in YUV420 with 6 channels : 6 * 128 * 256 @@ -16,11 +16,11 @@ To view the architecture of the ONNX networks, you can use [netron](https://netr * Channel 4 represents the half-res U channel * Channel 5 represents the half-res V channel * **desire** - * one-hot encoded vector to command model to execute certain actions, bit only needs to be sent for 1 frame : 8 + * one-hot encoded buffer to command model to execute certain actions, bit needs to be sent for the past 5 seconds (at 20FPS) : 100 * 8 * **traffic convention** * one-hot encoded vector to tell model whether traffic is right-hand or left-hand traffic : 2 -* **recurrent state** - * The recurrent state vector that is fed back into the GRU for temporal context : 512 +* **feature buffer** + * A buffer of intermediate features that gets appended to the current feature to form a 5 seconds temporal context (at 20FPS) : 99 * 128 ### Supercombo output format (Full size: XXX x float32) diff --git a/selfdrive/statsd.py b/selfdrive/statsd.py index 7dc002727e..e64907149c 100755 --- a/selfdrive/statsd.py +++ b/selfdrive/statsd.py @@ -13,7 +13,7 @@ from system.swaglog import cloudlog from system.hardware import HARDWARE from common.file_helpers import atomic_write_in_dir from system.version import get_normalized_origin, get_short_branch, get_short_version, is_dirty -from selfdrive.loggerd.config import STATS_DIR, STATS_DIR_FILE_LIMIT, STATS_SOCKET, STATS_FLUSH_TIME_S +from system.loggerd.config import STATS_DIR, STATS_DIR_FILE_LIMIT, STATS_SOCKET, STATS_FLUSH_TIME_S class METRIC_TYPE: diff --git a/selfdrive/test/process_replay/model_replay_ref_commit b/selfdrive/test/process_replay/model_replay_ref_commit index c64f522352..ad09668a46 100644 --- a/selfdrive/test/process_replay/model_replay_ref_commit +++ b/selfdrive/test/process_replay/model_replay_ref_commit @@ -1 +1 @@ -ba947edbb131a2a36ced7c490dfcf3280ad5b167 +ab64afd1abd1059c14f50c67b51e5ef89029f216 diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 7dc0b139a3..971ddb3fe2 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -449,9 +449,6 @@ def setup_env(simulation=False, CP=None, cfg=None, controlsState=None): if CP.openpilotLongitudinalControl: params.put_bool("ExperimentalLongitudinalEnabled", True) - # controlsd process configuration assume all routes are out of dashcam - params.put_bool("DashcamOverride", True) - def python_replay_process(cfg, lr, fingerprint=None): sub_sockets = [s for _, sub in cfg.pub_sub.items() for s in sub] diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 79769e14b6..a8896884e1 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -f9c7e05b836c4bff364978752e82d64b90f9d6e6 +3c5ebb007f76ba0de710ff7a8cf5910ad2edf22f \ No newline at end of file diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 569090f606..07117c2e7f 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -29,12 +29,12 @@ source_segments = [ ("SUBARU", "341dccd5359e3c97|2022-09-12--10-35-33--3"), # SUBARU.OUTBACK ("GM", "0c58b6a25109da2b|2021-02-23--16-35-50--11"), # GM.VOLT ("GM2", "376bf99325883932|2022-10-27--13-41-22--1"), # GM.BOLT_EUV - ("FORD", "54827bf84c38b14f|2023-01-26--21-59-07--4"), # FORD.BRONCO_SPORT_MK1 ("NISSAN", "35336926920f3571|2021-02-12--18-38-48--46"), # NISSAN.XTRAIL ("VOLKSWAGEN", "de9592456ad7d144|2021-06-29--11-00-15--6"), # VOLKSWAGEN.GOLF ("MAZDA", "bd6a637565e91581|2021-10-30--15-14-53--4"), # MAZDA.CX9_2021 # Enable when port is tested and dashcamOnly is no longer set + #("FORD", "54827bf84c38b14f|2023-01-26--21-59-07--4"), # FORD.BRONCO_SPORT_MK1 #("TESLA", "bb50caf5f0945ab1|2021-06-19--17-20-18--3"), # TESLA.AP2_MODELS #("VOLKSWAGEN2", "3cfdec54aa035f3f|2022-07-19--23-45-10--2"), # VOLKSWAGEN.PASSAT_NMS ] @@ -53,7 +53,6 @@ segments = [ ("SUBARU", "regen1E72BBDCED5|2022-09-27--15-55-31--0"), ("GM", "regen45B05A80EF6|2022-09-27--15-57-22--0"), ("GM2", "376bf99325883932|2022-10-27--13-41-22--1"), - ("FORD", "54827bf84c38b14f|2023-01-26--21-59-07--4"), ("NISSAN", "regenC19D899B46D|2022-09-27--15-59-13--0"), ("VOLKSWAGEN", "regenD8F7AC4BD0D|2022-09-27--16-41-45--0"), ("MAZDA", "regenFC3F9ECBB64|2022-09-27--16-03-09--0"), diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 84511771f7..07a3c61bc5 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -15,7 +15,7 @@ from common.basedir import BASEDIR from common.timeout import Timeout from common.params import Params from selfdrive.controls.lib.events import EVENTS, ET -from selfdrive.loggerd.config import ROOT +from system.loggerd.config import ROOT from selfdrive.test.helpers import set_params_enabled, release_only from tools.lib.logreader import LogReader diff --git a/selfdrive/test/test_valgrind_replay.py b/selfdrive/test/test_valgrind_replay.py index 238b822ec9..46dd4901e5 100755 --- a/selfdrive/test/test_valgrind_replay.py +++ b/selfdrive/test/test_valgrind_replay.py @@ -28,7 +28,7 @@ CONFIGS = [ }, ignore=[], command="./ubloxd", - path="selfdrive/locationd/", + path="system/ubloxd", segment="0375fdf7b1ce594d|2019-06-13--08-32-25--3", wait_for_response=True ), diff --git a/selfdrive/thermald/thermald.py b/selfdrive/thermald/thermald.py index eedeff31f1..531e0b04d1 100755 --- a/selfdrive/thermald/thermald.py +++ b/selfdrive/thermald/thermald.py @@ -18,7 +18,7 @@ from common.params import Params from common.realtime import DT_TRML, sec_since_boot from selfdrive.controls.lib.alertmanager import set_offroad_alert from system.hardware import HARDWARE, TICI, AGNOS -from selfdrive.loggerd.config import get_available_percent +from system.loggerd.config import get_available_percent from selfdrive.statsd import statlog from system.swaglog import cloudlog from selfdrive.thermald.power_monitoring import PowerMonitoring diff --git a/selfdrive/tombstoned.py b/selfdrive/tombstoned.py index 61a575f141..65fb45b678 100755 --- a/selfdrive/tombstoned.py +++ b/selfdrive/tombstoned.py @@ -10,7 +10,7 @@ import glob from typing import NoReturn from common.file_helpers import mkdirs_exists_ok -from selfdrive.loggerd.config import ROOT +from system.loggerd.config import ROOT import selfdrive.sentry as sentry from system.swaglog import cloudlog from system.version import get_commit diff --git a/selfdrive/ui/qt/maps/map.cc b/selfdrive/ui/qt/maps/map.cc index dd30b5feff..abbf434d69 100644 --- a/selfdrive/ui/qt/maps/map.cc +++ b/selfdrive/ui/qt/maps/map.cc @@ -24,8 +24,6 @@ const float MAX_PITCH = 50; const float MIN_PITCH = 0; const float MAP_SCALE = 2; -const float VALID_POS_STD = 50.0; // m - const QString ICON_SUFFIX = ".png"; MapWindow::MapWindow(const QMapboxGLSettings &settings) : m_settings(settings), velocity_filter(0, 10, 0.05) { @@ -125,42 +123,6 @@ void MapWindow::updateState(const UIState &s) { } } - // TODO should check a valid/status flag - if (sm.updated("gnssMeasurements") && sm["gnssMeasurements"].getGnssMeasurements().getGpsWeek() > 0){ - auto laikad_location = sm["gnssMeasurements"].getGnssMeasurements(); - auto laikad_pos = laikad_location.getPositionECEF(); - auto laikad_pos_ecef = laikad_pos.getValue(); - auto laikad_pos_std = laikad_pos.getStd(); - auto laikad_velocity_ecef = laikad_location.getVelocityECEF().getValue(); - - laikad_valid = laikad_pos.getValid() && Eigen::Vector3d(laikad_pos_std[0], laikad_pos_std[1], laikad_pos_std[2]).norm() < VALID_POS_STD; - - if (laikad_valid && !locationd_valid) { - ECEF ecef = {.x = laikad_pos_ecef[0], .y = laikad_pos_ecef[1], .z = laikad_pos_ecef[2]}; - Geodetic laikad_pos_geodetic = ecef2geodetic(ecef); - last_position = QMapbox::Coordinate(laikad_pos_geodetic.lat, laikad_pos_geodetic.lon); - - // Compute NED velocity - LocalCoord converter(ecef); - ECEF next_ecef = {.x = ecef.x + laikad_velocity_ecef[0], .y = ecef.y + laikad_velocity_ecef[1], .z = ecef.z + laikad_velocity_ecef[2]}; - Eigen::VectorXd ned_vel = converter.ecef2ned(next_ecef).to_vector() - converter.ecef2ned(ecef).to_vector(); - - float velocity = ned_vel.norm(); - velocity_filter.update(velocity); - - // Convert NED velocity to angle - if (velocity > 1.0) { - float new_bearing = fmod(RAD2DEG(atan2(ned_vel[1], ned_vel[0])) + 360.0, 360.0); - if (last_bearing) { - float delta = 0.1 * angle_difference(*last_bearing, new_bearing); // Smooth heading - last_bearing = fmod(*last_bearing + delta + 360.0, 360.0); - } else { - last_bearing = new_bearing; - } - } - } - } - if (sm.updated("navRoute") && sm["navRoute"].getNavRoute().getCoordinates().size()) { qWarning() << "Got new navRoute from navd. Opening map:" << allow_open; diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 19fe665d17..a29e9edef3 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -669,16 +669,18 @@ void AnnotatedCameraWidget::paintGL() { } // Wide or narrow cam dependent on speed - float v_ego = sm["carState"].getCarState().getVEgo(); - if ((v_ego < 10) || s->wide_cam_only) { - wide_cam_requested = true; - } else if (v_ego > 15) { - wide_cam_requested = false; + bool has_wide_cam = available_streams.count(VISION_STREAM_WIDE_ROAD); + if (has_wide_cam) { + float v_ego = sm["carState"].getCarState().getVEgo(); + if ((v_ego < 10) || available_streams.size() == 1) { + wide_cam_requested = true; + } else if (v_ego > 15) { + wide_cam_requested = false; + } + wide_cam_requested = wide_cam_requested && sm["controlsState"].getControlsState().getExperimentalMode(); + // for replay of old routes, never go to widecam + wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; } - wide_cam_requested = wide_cam_requested && sm["controlsState"].getControlsState().getExperimentalMode() && false; - // TODO: also detect when ecam vision stream isn't available - // for replay of old routes, never go to widecam - wide_cam_requested = wide_cam_requested && s->scene.calibration_wide_valid; CameraWidget::setStreamType(wide_cam_requested ? VISION_STREAM_WIDE_ROAD : VISION_STREAM_ROAD); s->scene.wide_cam = CameraWidget::getStreamType() == VISION_STREAM_WIDE_ROAD; diff --git a/selfdrive/ui/qt/widgets/cameraview.cc b/selfdrive/ui/qt/widgets/cameraview.cc index 8c7a7072e2..10300da55c 100644 --- a/selfdrive/ui/qt/widgets/cameraview.cc +++ b/selfdrive/ui/qt/widgets/cameraview.cc @@ -96,8 +96,10 @@ mat4 get_fit_view_transform(float widget_aspect_ratio, float frame_aspect_ratio) CameraWidget::CameraWidget(std::string stream_name, VisionStreamType type, bool zoom, QWidget* parent) : stream_name(stream_name), requested_stream_type(type), zoomed_view(zoom), QOpenGLWidget(parent) { setAttribute(Qt::WA_OpaquePaintEvent); + qRegisterMetaType>("availableStreams"); QObject::connect(this, &CameraWidget::vipcThreadConnected, this, &CameraWidget::vipcConnected, Qt::BlockingQueuedConnection); QObject::connect(this, &CameraWidget::vipcThreadFrameReceived, this, &CameraWidget::vipcFrameReceived, Qt::QueuedConnection); + QObject::connect(this, &CameraWidget::vipcAvailableStreamsUpdated, this, &CameraWidget::availableStreamsUpdated, Qt::QueuedConnection); } CameraWidget::~CameraWidget() { @@ -181,6 +183,10 @@ void CameraWidget::stopVipcThread() { } } +void CameraWidget::availableStreamsUpdated(std::set streams) { + available_streams = streams; +} + void CameraWidget::updateFrameMat() { int w = width(), h = height(); @@ -366,6 +372,14 @@ void CameraWidget::vipcThread() { if (!vipc_client->connected) { clearFrames(); + auto streams = VisionIpcClient::getAvailableStreams(stream_name, false); + if (streams.empty()) { + qWarning() << "VisionIPC connected, but no streams available"; + QThread::msleep(100); + continue; + } + emit vipcAvailableStreamsUpdated(streams); + if (!vipc_client->connect(false)) { QThread::msleep(100); continue; @@ -400,4 +414,5 @@ void CameraWidget::vipcThread() { void CameraWidget::clearFrames() { std::lock_guard lk(frame_lock); frames.clear(); + available_streams.clear(); } diff --git a/selfdrive/ui/qt/widgets/cameraview.h b/selfdrive/ui/qt/widgets/cameraview.h index f8b97be03e..9135620d35 100644 --- a/selfdrive/ui/qt/widgets/cameraview.h +++ b/selfdrive/ui/qt/widgets/cameraview.h @@ -41,6 +41,7 @@ signals: void clicked(); void vipcThreadConnected(VisionIpcClient *); void vipcThreadFrameReceived(); + void vipcAvailableStreamsUpdated(std::set); protected: void paintGL() override; @@ -71,6 +72,7 @@ protected: int stream_stride = 0; std::atomic active_stream_type; std::atomic requested_stream_type; + std::set available_streams; QThread *vipc_thread = nullptr; // Calibration @@ -88,4 +90,7 @@ protected: protected slots: void vipcConnected(VisionIpcClient *vipc_client); void vipcFrameReceived(); + void availableStreamsUpdated(std::set streams); }; + +Q_DECLARE_METATYPE(std::set); diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index 5c4eab3327..8dc3a9830d 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -596,16 +596,17 @@ trabalho definido Unable to mount data partition. Partition may be corrupted. Press confirm to erase and reset your device. - + Não é possível montar a partição de dados. Partição corrompida. Confirme para apagar e redefinir o dispositivo. Press confirm to erase all content and settings. Press cancel to resume boot. - + Pressione confirmar para apagar todo o conteúdo e configurações. Pressione cancelar para voltar. Resetting device... This may take up to a minute. - + Redefinindo o dispositivo +Isso pode levar até um minuto. @@ -707,11 +708,11 @@ This may take up to a minute. No custom software found at this URL. - + Não há software personalizado nesta URL. Something went wrong. Reboot the device. - + Algo deu errado. Reinicie o dispositivo. diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index e4058ee0db..83db0b7301 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -200,7 +200,7 @@ openpilot requires the device to be mounted within 4° left or right and within 5° up or 8° down. openpilot is continuously calibrating, resetting is rarely required. - openpilot 需要將裝置固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。 + openpilot 需要將設備固定在左右偏差 4° 以內,朝上偏差 5° 以内或朝下偏差 8° 以内。鏡頭在後台會持續自動校準,很少有需要重置的情况。 Your device is pointed %1° %2 and %3° %4. @@ -592,16 +592,16 @@ location set Unable to mount data partition. Partition may be corrupted. Press confirm to erase and reset your device. - + 無法掛載資料分割區 分割區可能已經毀損 請確認是否要刪除並重新設定 Press confirm to erase all content and settings. Press cancel to resume boot. - + 按下確認以刪除所有內容及設定 按下取消來繼續開機 Resetting device... This may take up to a minute. - + 設備重置中 此過程可能需要幾分鐘 @@ -703,11 +703,11 @@ This may take up to a minute. No custom software found at this URL. - + 無法在此URL找到定制的軟體 Something went wrong. Reboot the device. - + 發生了一些錯誤 請重新啟動您的設備 @@ -1028,11 +1028,11 @@ This may take up to a minute. openpilot longitudinal control may come in a future update. - + 未來可能會推出openpilot縱向控制 An experimental version of openpilot longitudinal control can be tested, along with Experimental mode, on non-release branches. - + 在非發行分支中 可找到包含實驗模式的openpilot縱向控制測試版本 Enable experimental longitudinal control to allow Experimental mode. diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 50843de68e..50ffc84f4f 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -234,7 +234,6 @@ void UIState::updateStatus() { if (scene.started) { status = STATUS_DISENGAGED; scene.started_frame = sm->frame; - wide_cam_only = Params().getBool("WideCameraOnly"); } started_prev = scene.started; emit offroadTransition(!scene.started); @@ -252,12 +251,10 @@ UIState::UIState(QObject *parent) : QObject(parent) { sm = std::make_unique>({ "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "roadCameraState", "pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2", - "wideRoadCameraState", "managerState", "navInstruction", "navRoute", "gnssMeasurements", - "uiPlan", + "wideRoadCameraState", "managerState", "navInstruction", "navRoute", "uiPlan", }); Params params; - wide_cam_only = params.getBool("WideCameraOnly"); prime_type = std::atoi(params.get("PrimeType").c_str()); language = QString::fromStdString(params.get("LanguageSetting")); diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index ad2a1fe1f4..4c4bd462e7 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -150,7 +150,6 @@ public: QString language; QTransform car_space_transform; - bool wide_cam_only; signals: void uiUpdate(const UIState &s); diff --git a/system/hardware/tici/amplifier.py b/system/hardware/tici/amplifier.py index 8233834d11..840d575fdf 100644 --- a/system/hardware/tici/amplifier.py +++ b/system/hardware/tici/amplifier.py @@ -24,13 +24,10 @@ BASE_CONFIG = [ AmpConfig("MCLK prescaler", 0b01, 0x10, 4, 0b00110000), AmpConfig("PM: enable speakers", 0b11, 0x4D, 4, 0b00110000), AmpConfig("PM: enable DACs", 0b11, 0x4D, 0, 0b00000011), - AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), - AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), AmpConfig("Enable PLL1", 0b1, 0x12, 7, 0b10000000), AmpConfig("Enable PLL2", 0b1, 0x1A, 7, 0b10000000), AmpConfig("DAI1: I2S mode", 0b00100, 0x14, 2, 0b01111100), AmpConfig("DAI2: I2S mode", 0b00100, 0x1C, 2, 0b01111100), - AmpConfig("Right speaker output volume", 0x1c, 0x3E, 0, 0b00011111), AmpConfig("DAI1 Passband filtering: music mode", 0b1, 0x18, 7, 0b10000000), AmpConfig("DAI1 voice mode gain (DV1G)", 0b00, 0x2F, 4, 0b00110000), AmpConfig("DAI1 attenuation (DV1)", 0x0, 0x2F, 0, 0b00001111), @@ -41,7 +38,6 @@ BASE_CONFIG = [ AmpConfig("ALC/excursion limiter release time", 0b101, 0x43, 4, 0b01110000), AmpConfig("ALC multiband enable", 0b1, 0x43, 3, 0b00001000), AmpConfig("DAI1 EQ enable", 0b0, 0x49, 0, 0b00000001), - AmpConfig("DAI2 EQ enable", 0b1, 0x49, 1, 0b00000010), AmpConfig("DAI2 EQ clip detection disabled", 0b1, 0x32, 4, 0b00010000), AmpConfig("DAI2 EQ attenuation", 0x5, 0x32, 0, 0b00001111), AmpConfig("Excursion limiter upper corner freq", 0b100, 0x41, 4, 0b01110000), @@ -64,6 +60,11 @@ 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)), @@ -72,11 +73,13 @@ CONFIGS = { ], "tizi": [ AmpConfig("Left speaker output from left DAC", 0b1, 0x2B, 0, 0b11111111), + AmpConfig("Right speaker output from right DAC", 0b1, 0x2C, 0, 0b11111111), AmpConfig("Left Speaker Mixer Gain", 0b00, 0x2D, 0, 0b00000011), - AmpConfig("Left speaker output volume", 0x1F, 0x3D, 0, 0b00011111), - AmpConfig("Right speaker output volume", 0x1F, 0x3E, 0, 0b00011111), - AmpConfig("DAI1 attenuation (DV1)", 0x4, 0x2F, 0, 0b00001111), - AmpConfig("DAI2 attenuation (DV2)", 0x4, 0x31, 0, 0b00001111), + AmpConfig("Right Speaker Mixer Gain", 0b00, 0x2D, 2, 0b00001100), + AmpConfig("Left speaker output volume", 0x17, 0x3D, 0, 0b00011111), + AmpConfig("Right speaker output volume", 0x17, 0x3E, 0, 0b00011111), + + AmpConfig("DAI2 EQ enable", 0b0, 0x49, 1, 0b00000010), AmpConfig("DAI2: DC blocking", 0b0, 0x20, 0, 0b00000001), AmpConfig("ALC enable", 0b0, 0x43, 7, 0b10000000), AmpConfig("DAI2 EQ attenuation", 0x2, 0x32, 0, 0b00001111), @@ -91,12 +94,6 @@ CONFIGS = { AmpConfig("Right DAC input mixer: DAI2 left", 0b0, 0x22, 1, 0b00000010), AmpConfig("Right DAC input mixer: DAI2 right", 0b1, 0x22, 0, 0b00000001), AmpConfig("Volume adjustment smoothing disabled", 0b1, 0x49, 6, 0b01000000), - - *configs_from_eq_params(0x84, EQParams(0x3084, 0xC023, 0x3D60, 0x042B, 0x1222)), - *configs_from_eq_params(0x8E, EQParams(0x2FB2, 0xC05C, 0x3BD3, 0x06C5, 0x16BB)), - *configs_from_eq_params(0x98, EQParams(0x21F5, 0xDF73, 0x2DFE, 0x371A, 0x2C80)), - *configs_from_eq_params(0xA2, EQParams(0x2A5A, 0x0AD0, 0x14FA, 0x3F14, 0x3C76)), - *configs_from_eq_params(0xAC, EQParams(0x1577, 0x3FAE, 0xEE60, 0x0664, 0x3D86)), ], } diff --git a/system/hardware/tici/test_power_draw.py b/system/hardware/tici/test_power_draw.py index 2460152998..f563933285 100755 --- a/system/hardware/tici/test_power_draw.py +++ b/system/hardware/tici/test_power_draw.py @@ -3,6 +3,7 @@ import unittest import time import math from dataclasses import dataclass +from tabulate import tabulate from system.hardware import HARDWARE, TICI from system.hardware.tici.power_monitor import get_power @@ -20,7 +21,7 @@ class Proc: PROCS = [ Proc('camerad', 2.15), - Proc('modeld', 1.15, atol=0.2), + Proc('modeld', 0.93, atol=0.2), Proc('dmonitoringmodeld', 0.4), Proc('encoderd', 0.23), ] @@ -58,15 +59,16 @@ class TestPowerDraw(unittest.TestCase): manager_cleanup() - print("-"*35) - print(f"Baseline {baseline:.2f}W\n") + tab = [] + tab.append(['process', 'expected (W)', 'current (W)']) for proc in PROCS: cur = used[proc.name] expected = proc.power - print(f"{proc.name.ljust(20)} {expected:.2f}W {cur:.2f}W") + tab.append([proc.name, round(expected, 2), round(cur, 2)]) with self.subTest(proc=proc.name): self.assertTrue(math.isclose(cur, expected, rel_tol=proc.rtol, abs_tol=proc.atol)) - print("-"*35) + print(tabulate(tab)) + print(f"Baseline {baseline:.2f}W\n") if __name__ == "__main__": diff --git a/selfdrive/loggerd/.gitignore b/system/loggerd/.gitignore similarity index 100% rename from selfdrive/loggerd/.gitignore rename to system/loggerd/.gitignore diff --git a/selfdrive/loggerd/README.md b/system/loggerd/README.md similarity index 100% rename from selfdrive/loggerd/README.md rename to system/loggerd/README.md diff --git a/selfdrive/loggerd/SConscript b/system/loggerd/SConscript similarity index 100% rename from selfdrive/loggerd/SConscript rename to system/loggerd/SConscript diff --git a/selfdrive/loggerd/__init__.py b/system/loggerd/__init__.py similarity index 100% rename from selfdrive/loggerd/__init__.py rename to system/loggerd/__init__.py diff --git a/selfdrive/loggerd/bootlog.cc b/system/loggerd/bootlog.cc similarity index 97% rename from selfdrive/loggerd/bootlog.cc rename to system/loggerd/bootlog.cc index e882e4cf8d..4deb5b41f3 100644 --- a/selfdrive/loggerd/bootlog.cc +++ b/system/loggerd/bootlog.cc @@ -3,7 +3,7 @@ #include "cereal/messaging/messaging.h" #include "common/swaglog.h" -#include "selfdrive/loggerd/logger.h" +#include "system/loggerd/logger.h" static kj::Array build_boot_log() { diff --git a/selfdrive/loggerd/config.py b/system/loggerd/config.py similarity index 100% rename from selfdrive/loggerd/config.py rename to system/loggerd/config.py diff --git a/selfdrive/loggerd/deleter.py b/system/loggerd/deleter.py similarity index 89% rename from selfdrive/loggerd/deleter.py rename to system/loggerd/deleter.py index 5606288024..5fb2b9eb41 100644 --- a/selfdrive/loggerd/deleter.py +++ b/system/loggerd/deleter.py @@ -3,8 +3,8 @@ import os import shutil import threading from system.swaglog import cloudlog -from selfdrive.loggerd.config import ROOT, get_available_bytes, get_available_percent -from selfdrive.loggerd.uploader import listdir_by_creation +from system.loggerd.config import ROOT, get_available_bytes, get_available_percent +from system.loggerd.uploader import listdir_by_creation MIN_BYTES = 5 * 1024 * 1024 * 1024 MIN_PERCENT = 10 diff --git a/selfdrive/loggerd/encoder/encoder.cc b/system/loggerd/encoder/encoder.cc similarity index 98% rename from selfdrive/loggerd/encoder/encoder.cc rename to system/loggerd/encoder/encoder.cc index 943f37803d..08eaf0ff01 100644 --- a/selfdrive/loggerd/encoder/encoder.cc +++ b/system/loggerd/encoder/encoder.cc @@ -1,5 +1,5 @@ #include -#include "selfdrive/loggerd/encoder/encoder.h" +#include "system/loggerd/encoder/encoder.h" VideoEncoder::~VideoEncoder() {} diff --git a/selfdrive/loggerd/encoder/encoder.h b/system/loggerd/encoder/encoder.h similarity index 97% rename from selfdrive/loggerd/encoder/encoder.h rename to system/loggerd/encoder/encoder.h index 21ef65cf12..88dd5cee23 100644 --- a/selfdrive/loggerd/encoder/encoder.h +++ b/system/loggerd/encoder/encoder.h @@ -7,7 +7,7 @@ #include "cereal/messaging/messaging.h" #include "cereal/visionipc/visionipc.h" #include "common/queue.h" -#include "selfdrive/loggerd/video_writer.h" +#include "system/loggerd/video_writer.h" #include "system/camerad/cameras/camera_common.h" #define V4L2_BUF_FLAG_KEYFRAME 8 diff --git a/selfdrive/loggerd/encoder/ffmpeg_encoder.cc b/system/loggerd/encoder/ffmpeg_encoder.cc similarity index 98% rename from selfdrive/loggerd/encoder/ffmpeg_encoder.cc rename to system/loggerd/encoder/ffmpeg_encoder.cc index 5f8d140e8b..275da34f18 100644 --- a/selfdrive/loggerd/encoder/ffmpeg_encoder.cc +++ b/system/loggerd/encoder/ffmpeg_encoder.cc @@ -1,6 +1,6 @@ #pragma clang diagnostic ignored "-Wdeprecated-declarations" -#include "selfdrive/loggerd/encoder/ffmpeg_encoder.h" +#include "system/loggerd/encoder/ffmpeg_encoder.h" #include #include diff --git a/selfdrive/loggerd/encoder/ffmpeg_encoder.h b/system/loggerd/encoder/ffmpeg_encoder.h similarity index 92% rename from selfdrive/loggerd/encoder/ffmpeg_encoder.h rename to system/loggerd/encoder/ffmpeg_encoder.h index 497a28b651..9095a6e815 100644 --- a/selfdrive/loggerd/encoder/ffmpeg_encoder.h +++ b/system/loggerd/encoder/ffmpeg_encoder.h @@ -11,8 +11,8 @@ extern "C" { #include } -#include "selfdrive/loggerd/encoder/encoder.h" -#include "selfdrive/loggerd/loggerd.h" +#include "system/loggerd/encoder/encoder.h" +#include "system/loggerd/loggerd.h" class FfmpegEncoder : public VideoEncoder { public: diff --git a/selfdrive/loggerd/encoder/v4l_encoder.cc b/system/loggerd/encoder/v4l_encoder.cc similarity index 99% rename from selfdrive/loggerd/encoder/v4l_encoder.cc rename to system/loggerd/encoder/v4l_encoder.cc index 88aeb21256..16e7246ff4 100644 --- a/selfdrive/loggerd/encoder/v4l_encoder.cc +++ b/system/loggerd/encoder/v4l_encoder.cc @@ -2,7 +2,7 @@ #include #include -#include "selfdrive/loggerd/encoder/v4l_encoder.h" +#include "system/loggerd/encoder/v4l_encoder.h" #include "common/util.h" #include "common/timing.h" diff --git a/selfdrive/loggerd/encoder/v4l_encoder.h b/system/loggerd/encoder/v4l_encoder.h similarity index 95% rename from selfdrive/loggerd/encoder/v4l_encoder.h rename to system/loggerd/encoder/v4l_encoder.h index c2a53dd6ef..d4b0a1211d 100644 --- a/selfdrive/loggerd/encoder/v4l_encoder.h +++ b/system/loggerd/encoder/v4l_encoder.h @@ -1,7 +1,7 @@ #pragma once #include "common/queue.h" -#include "selfdrive/loggerd/encoder/encoder.h" +#include "system/loggerd/encoder/encoder.h" #define BUF_IN_COUNT 7 #define BUF_OUT_COUNT 6 diff --git a/selfdrive/loggerd/encoderd.cc b/system/loggerd/encoderd.cc similarity index 99% rename from selfdrive/loggerd/encoderd.cc rename to system/loggerd/encoderd.cc index db5f4b61ab..12b58b6591 100644 --- a/selfdrive/loggerd/encoderd.cc +++ b/system/loggerd/encoderd.cc @@ -1,4 +1,4 @@ -#include "selfdrive/loggerd/loggerd.h" +#include "system/loggerd/loggerd.h" ExitHandler do_exit; diff --git a/selfdrive/loggerd/logger.cc b/system/loggerd/logger.cc similarity index 99% rename from selfdrive/loggerd/logger.cc rename to system/loggerd/logger.cc index aaf267e523..0599aa1e54 100644 --- a/selfdrive/loggerd/logger.cc +++ b/system/loggerd/logger.cc @@ -1,4 +1,4 @@ -#include "selfdrive/loggerd/logger.h" +#include "system/loggerd/logger.h" #include #include diff --git a/selfdrive/loggerd/logger.h b/system/loggerd/logger.h similarity index 100% rename from selfdrive/loggerd/logger.h rename to system/loggerd/logger.h diff --git a/selfdrive/loggerd/loggerd.cc b/system/loggerd/loggerd.cc similarity index 99% rename from selfdrive/loggerd/loggerd.cc rename to system/loggerd/loggerd.cc index e09cdfaa9e..a7f7db4801 100644 --- a/selfdrive/loggerd/loggerd.cc +++ b/system/loggerd/loggerd.cc @@ -1,5 +1,5 @@ -#include "selfdrive/loggerd/loggerd.h" -#include "selfdrive/loggerd/video_writer.h" +#include "system/loggerd/loggerd.h" +#include "system/loggerd/video_writer.h" ExitHandler do_exit; diff --git a/selfdrive/loggerd/loggerd.h b/system/loggerd/loggerd.h similarity index 92% rename from selfdrive/loggerd/loggerd.h rename to system/loggerd/loggerd.h index 1fa6349828..1b8f9e0d2a 100644 --- a/selfdrive/loggerd/loggerd.h +++ b/system/loggerd/loggerd.h @@ -23,13 +23,13 @@ #include "common/util.h" #include "system/hardware/hw.h" -#include "selfdrive/loggerd/encoder/encoder.h" -#include "selfdrive/loggerd/logger.h" +#include "system/loggerd/encoder/encoder.h" +#include "system/loggerd/logger.h" #ifdef QCOM2 -#include "selfdrive/loggerd/encoder/v4l_encoder.h" +#include "system/loggerd/encoder/v4l_encoder.h" #define Encoder V4LEncoder #else -#include "selfdrive/loggerd/encoder/ffmpeg_encoder.h" +#include "system/loggerd/encoder/ffmpeg_encoder.h" #define Encoder FfmpegEncoder #endif diff --git a/selfdrive/loggerd/tests/__init__.py b/system/loggerd/tests/__init__.py similarity index 100% rename from selfdrive/loggerd/tests/__init__.py rename to system/loggerd/tests/__init__.py diff --git a/selfdrive/loggerd/tests/fill_eon.py b/system/loggerd/tests/fill_eon.py similarity index 79% rename from selfdrive/loggerd/tests/fill_eon.py rename to system/loggerd/tests/fill_eon.py index b40982fa9f..e0c52ea0d7 100755 --- a/selfdrive/loggerd/tests/fill_eon.py +++ b/system/loggerd/tests/fill_eon.py @@ -3,8 +3,8 @@ import os -from selfdrive.loggerd.config import ROOT, get_available_percent -from selfdrive.loggerd.tests.loggerd_tests_common import create_random_file +from system.loggerd.config import ROOT, get_available_percent +from system.loggerd.tests.loggerd_tests_common import create_random_file if __name__ == "__main__": diff --git a/selfdrive/loggerd/tests/loggerd_tests_common.py b/system/loggerd/tests/loggerd_tests_common.py similarity index 98% rename from selfdrive/loggerd/tests/loggerd_tests_common.py rename to system/loggerd/tests/loggerd_tests_common.py index 80cfb162f1..6aca83858b 100644 --- a/selfdrive/loggerd/tests/loggerd_tests_common.py +++ b/system/loggerd/tests/loggerd_tests_common.py @@ -5,7 +5,7 @@ import random import tempfile import unittest -import selfdrive.loggerd.uploader as uploader +import system.loggerd.uploader as uploader def create_random_file(file_path, size_mb, lock=False): try: diff --git a/selfdrive/loggerd/tests/test_deleter.py b/system/loggerd/tests/test_deleter.py similarity index 96% rename from selfdrive/loggerd/tests/test_deleter.py rename to system/loggerd/tests/test_deleter.py index 80fb5c997f..5b54a43f3b 100755 --- a/selfdrive/loggerd/tests/test_deleter.py +++ b/system/loggerd/tests/test_deleter.py @@ -6,8 +6,8 @@ import unittest from collections import namedtuple from common.timeout import Timeout, TimeoutException -import selfdrive.loggerd.deleter as deleter -from selfdrive.loggerd.tests.loggerd_tests_common import UploaderTestCase +import system.loggerd.deleter as deleter +from system.loggerd.tests.loggerd_tests_common import UploaderTestCase Stats = namedtuple("Stats", ['f_bavail', 'f_blocks', 'f_frsize']) diff --git a/selfdrive/loggerd/tests/test_encoder.py b/system/loggerd/tests/test_encoder.py similarity index 99% rename from selfdrive/loggerd/tests/test_encoder.py rename to system/loggerd/tests/test_encoder.py index 1b9bcef2d7..81f4e9fb9d 100755 --- a/selfdrive/loggerd/tests/test_encoder.py +++ b/system/loggerd/tests/test_encoder.py @@ -14,7 +14,7 @@ from tqdm import trange from common.params import Params from common.timeout import Timeout from system.hardware import TICI -from selfdrive.loggerd.config import ROOT +from system.loggerd.config import ROOT from selfdrive.manager.process_config import managed_processes from tools.lib.logreader import LogReader diff --git a/selfdrive/loggerd/tests/test_logger.cc b/system/loggerd/tests/test_logger.cc similarity index 99% rename from selfdrive/loggerd/tests/test_logger.cc rename to system/loggerd/tests/test_logger.cc index ba7835d632..9c82299091 100644 --- a/selfdrive/loggerd/tests/test_logger.cc +++ b/system/loggerd/tests/test_logger.cc @@ -9,7 +9,7 @@ #include "catch2/catch.hpp" #include "cereal/messaging/messaging.h" #include "common/util.h" -#include "selfdrive/loggerd/logger.h" +#include "system/loggerd/logger.h" #include "tools/replay/util.h" typedef cereal::Sentinel::SentinelType SentinelType; diff --git a/selfdrive/loggerd/tests/test_loggerd.py b/system/loggerd/tests/test_loggerd.py similarity index 99% rename from selfdrive/loggerd/tests/test_loggerd.py rename to system/loggerd/tests/test_loggerd.py index 857dc5c4e9..54098d13d0 100755 --- a/selfdrive/loggerd/tests/test_loggerd.py +++ b/system/loggerd/tests/test_loggerd.py @@ -15,7 +15,7 @@ from cereal.services import service_list from common.basedir import BASEDIR from common.params import Params from common.timeout import Timeout -from selfdrive.loggerd.config import ROOT +from system.loggerd.config import ROOT from selfdrive.manager.process_config import managed_processes from system.version import get_version from tools.lib.logreader import LogReader @@ -51,7 +51,7 @@ class TestLoggerd(unittest.TestCase): def _gen_bootlog(self): with Timeout(5): - out = subprocess.check_output("./bootlog", cwd=os.path.join(BASEDIR, "selfdrive/loggerd"), encoding='utf-8') + out = subprocess.check_output("./bootlog", cwd=os.path.join(BASEDIR, "system/loggerd"), encoding='utf-8') log_fn = self._get_log_fn(out) diff --git a/selfdrive/loggerd/tests/test_runner.cc b/system/loggerd/tests/test_runner.cc similarity index 100% rename from selfdrive/loggerd/tests/test_runner.cc rename to system/loggerd/tests/test_runner.cc diff --git a/selfdrive/loggerd/tests/test_uploader.py b/system/loggerd/tests/test_uploader.py similarity index 97% rename from selfdrive/loggerd/tests/test_uploader.py rename to system/loggerd/tests/test_uploader.py index 6090bbe2aa..11b273cec8 100755 --- a/selfdrive/loggerd/tests/test_uploader.py +++ b/system/loggerd/tests/test_uploader.py @@ -7,9 +7,9 @@ import logging import json from system.swaglog import cloudlog -import selfdrive.loggerd.uploader as uploader +import system.loggerd.uploader as uploader -from selfdrive.loggerd.tests.loggerd_tests_common import UploaderTestCase +from system.loggerd.tests.loggerd_tests_common import UploaderTestCase class TestLogHandler(logging.Handler): diff --git a/selfdrive/loggerd/tools/mark_all_uploaded.py b/system/loggerd/tools/mark_all_uploaded.py similarity index 60% rename from selfdrive/loggerd/tools/mark_all_uploaded.py rename to system/loggerd/tools/mark_all_uploaded.py index e60e6cfa2c..c963014748 100644 --- a/selfdrive/loggerd/tools/mark_all_uploaded.py +++ b/system/loggerd/tools/mark_all_uploaded.py @@ -1,7 +1,7 @@ import os -from selfdrive.loggerd.uploader import UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE +from system.loggerd.uploader import UPLOAD_ATTR_NAME, UPLOAD_ATTR_VALUE -from selfdrive.loggerd.config import ROOT +from system.loggerd.config import ROOT for folder in os.walk(ROOT): for file1 in folder[2]: full_path = os.path.join(folder[0], file1) diff --git a/selfdrive/loggerd/tools/mark_unuploaded.py b/system/loggerd/tools/mark_unuploaded.py similarity index 70% rename from selfdrive/loggerd/tools/mark_unuploaded.py rename to system/loggerd/tools/mark_unuploaded.py index 343805d5fc..3d1d4472b0 100755 --- a/selfdrive/loggerd/tools/mark_unuploaded.py +++ b/system/loggerd/tools/mark_unuploaded.py @@ -1,7 +1,7 @@ #!/usr/bin/env python3 import os import sys -from selfdrive.loggerd.uploader import UPLOAD_ATTR_NAME +from system.loggerd.uploader import UPLOAD_ATTR_NAME for fn in sys.argv[1:]: print(f"unmarking {fn}") diff --git a/selfdrive/loggerd/uploader.py b/system/loggerd/uploader.py similarity index 98% rename from selfdrive/loggerd/uploader.py rename to system/loggerd/uploader.py index f97bafecb9..d4ed6dca28 100644 --- a/selfdrive/loggerd/uploader.py +++ b/system/loggerd/uploader.py @@ -16,8 +16,8 @@ from common.api import Api from common.params import Params from common.realtime import set_core_affinity from system.hardware import TICI -from selfdrive.loggerd.xattr_cache import getxattr, setxattr -from selfdrive.loggerd.config import ROOT +from system.loggerd.xattr_cache import getxattr, setxattr +from system.loggerd.config import ROOT from system.swaglog import cloudlog NetworkType = log.DeviceState.NetworkType diff --git a/selfdrive/loggerd/video_writer.cc b/system/loggerd/video_writer.cc similarity index 98% rename from selfdrive/loggerd/video_writer.cc rename to system/loggerd/video_writer.cc index 4f79ccafc8..91bf09355f 100644 --- a/selfdrive/loggerd/video_writer.cc +++ b/system/loggerd/video_writer.cc @@ -2,7 +2,7 @@ #include #include -#include "selfdrive/loggerd/video_writer.h" +#include "system/loggerd/video_writer.h" #include "common/swaglog.h" #include "common/util.h" diff --git a/selfdrive/loggerd/video_writer.h b/system/loggerd/video_writer.h similarity index 100% rename from selfdrive/loggerd/video_writer.h rename to system/loggerd/video_writer.h diff --git a/selfdrive/loggerd/xattr_cache.py b/system/loggerd/xattr_cache.py similarity index 100% rename from selfdrive/loggerd/xattr_cache.py rename to system/loggerd/xattr_cache.py diff --git a/system/sensord/.gitignore b/system/sensord/.gitignore new file mode 100644 index 0000000000..e9b8071b4b --- /dev/null +++ b/system/sensord/.gitignore @@ -0,0 +1 @@ +_sensord diff --git a/selfdrive/sensord/SConscript b/system/sensord/SConscript similarity index 100% rename from selfdrive/sensord/SConscript rename to system/sensord/SConscript diff --git a/selfdrive/sensord/__init__.py b/system/sensord/__init__.py similarity index 100% rename from selfdrive/sensord/__init__.py rename to system/sensord/__init__.py diff --git a/selfdrive/sensord/pigeond.py b/system/sensord/pigeond.py similarity index 99% rename from selfdrive/sensord/pigeond.py rename to system/sensord/pigeond.py index 9d0a62bd3b..c9ad7ff22a 100755 --- a/selfdrive/sensord/pigeond.py +++ b/system/sensord/pigeond.py @@ -183,6 +183,7 @@ def initialize_pigeon(pigeon: TTYPigeon) -> bool: pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x02\x13\x01\x20\x6C") pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x0A\x09\x01\x1E\x70") pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x0A\x0B\x01\x20\x74") + pigeon.send_with_ack(b"\xB5\x62\x06\x01\x03\x00\x01\x35\x01\x41\xAD") cloudlog.debug("pigeon configured") # try restoring almanac backup diff --git a/selfdrive/sensord/rawgps/compare.py b/system/sensord/rawgps/compare.py similarity index 100% rename from selfdrive/sensord/rawgps/compare.py rename to system/sensord/rawgps/compare.py diff --git a/selfdrive/sensord/rawgps/modemdiag.py b/system/sensord/rawgps/modemdiag.py similarity index 100% rename from selfdrive/sensord/rawgps/modemdiag.py rename to system/sensord/rawgps/modemdiag.py diff --git a/selfdrive/sensord/rawgps/rawgpsd.py b/system/sensord/rawgps/rawgpsd.py similarity index 98% rename from selfdrive/sensord/rawgps/rawgpsd.py rename to system/sensord/rawgps/rawgpsd.py index 3fa5e927a2..f75ceee7ed 100755 --- a/selfdrive/sensord/rawgps/rawgpsd.py +++ b/system/sensord/rawgps/rawgpsd.py @@ -15,8 +15,8 @@ from common.gpio import gpio_init, gpio_set from laika.gps_time import GPSTime from system.hardware.tici.pins import GPIO from system.swaglog import cloudlog -from selfdrive.sensord.rawgps.modemdiag import ModemDiag, DIAG_LOG_F, setup_logs, send_recv -from selfdrive.sensord.rawgps.structs import (dict_unpacker, position_report, relist, +from system.sensord.rawgps.modemdiag import ModemDiag, DIAG_LOG_F, setup_logs, send_recv +from system.sensord.rawgps.structs import (dict_unpacker, position_report, relist, gps_measurement_report, gps_measurement_report_sv, glonass_measurement_report, glonass_measurement_report_sv, oemdre_measurement_report, oemdre_measurement_report_sv, oemdre_svpoly_report, diff --git a/selfdrive/sensord/rawgps/structs.py b/system/sensord/rawgps/structs.py similarity index 100% rename from selfdrive/sensord/rawgps/structs.py rename to system/sensord/rawgps/structs.py diff --git a/selfdrive/sensord/rawgps/test_rawgps.py b/system/sensord/rawgps/test_rawgps.py similarity index 100% rename from selfdrive/sensord/rawgps/test_rawgps.py rename to system/sensord/rawgps/test_rawgps.py diff --git a/selfdrive/sensord/sensord b/system/sensord/sensord similarity index 100% rename from selfdrive/sensord/sensord rename to system/sensord/sensord diff --git a/selfdrive/sensord/sensors/bmx055_accel.cc b/system/sensord/sensors/bmx055_accel.cc similarity index 100% rename from selfdrive/sensord/sensors/bmx055_accel.cc rename to system/sensord/sensors/bmx055_accel.cc diff --git a/selfdrive/sensord/sensors/bmx055_accel.h b/system/sensord/sensors/bmx055_accel.h similarity index 96% rename from selfdrive/sensord/sensors/bmx055_accel.h rename to system/sensord/sensors/bmx055_accel.h index 8ef660a99f..2cc316e992 100644 --- a/selfdrive/sensord/sensors/bmx055_accel.h +++ b/system/sensord/sensors/bmx055_accel.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define BMX055_ACCEL_I2C_ADDR 0x18 diff --git a/selfdrive/sensord/sensors/bmx055_gyro.cc b/system/sensord/sensors/bmx055_gyro.cc similarity index 100% rename from selfdrive/sensord/sensors/bmx055_gyro.cc rename to system/sensord/sensors/bmx055_gyro.cc diff --git a/selfdrive/sensord/sensors/bmx055_gyro.h b/system/sensord/sensors/bmx055_gyro.h similarity index 95% rename from selfdrive/sensord/sensors/bmx055_gyro.h rename to system/sensord/sensors/bmx055_gyro.h index 80b93f128c..7be3e56563 100644 --- a/selfdrive/sensord/sensors/bmx055_gyro.h +++ b/system/sensord/sensors/bmx055_gyro.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define BMX055_GYRO_I2C_ADDR 0x68 diff --git a/selfdrive/sensord/sensors/bmx055_magn.cc b/system/sensord/sensors/bmx055_magn.cc similarity index 100% rename from selfdrive/sensord/sensors/bmx055_magn.cc rename to system/sensord/sensors/bmx055_magn.cc diff --git a/selfdrive/sensord/sensors/bmx055_magn.h b/system/sensord/sensors/bmx055_magn.h similarity index 97% rename from selfdrive/sensord/sensors/bmx055_magn.h rename to system/sensord/sensors/bmx055_magn.h index e4a79bc7e0..15c4e734b9 100644 --- a/selfdrive/sensord/sensors/bmx055_magn.h +++ b/system/sensord/sensors/bmx055_magn.h @@ -1,7 +1,7 @@ #pragma once #include -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define BMX055_MAGN_I2C_ADDR 0x10 diff --git a/selfdrive/sensord/sensors/bmx055_temp.cc b/system/sensord/sensors/bmx055_temp.cc similarity index 94% rename from selfdrive/sensord/sensors/bmx055_temp.cc rename to system/sensord/sensors/bmx055_temp.cc index 95b8068ac1..68ee0da1d6 100644 --- a/selfdrive/sensord/sensors/bmx055_temp.cc +++ b/system/sensord/sensors/bmx055_temp.cc @@ -2,7 +2,7 @@ #include -#include "selfdrive/sensord/sensors/bmx055_accel.h" +#include "system/sensord/sensors/bmx055_accel.h" #include "common/swaglog.h" #include "common/timing.h" diff --git a/selfdrive/sensord/sensors/bmx055_temp.h b/system/sensord/sensors/bmx055_temp.h similarity index 71% rename from selfdrive/sensord/sensors/bmx055_temp.h rename to system/sensord/sensors/bmx055_temp.h index 0b6802deaa..a2eabae395 100644 --- a/selfdrive/sensord/sensors/bmx055_temp.h +++ b/system/sensord/sensors/bmx055_temp.h @@ -1,7 +1,7 @@ #pragma once -#include "selfdrive/sensord/sensors/bmx055_accel.h" -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/bmx055_accel.h" +#include "system/sensord/sensors/i2c_sensor.h" class BMX055_Temp : public I2CSensor { uint8_t get_device_address() {return BMX055_ACCEL_I2C_ADDR;} diff --git a/selfdrive/sensord/sensors/constants.h b/system/sensord/sensors/constants.h similarity index 100% rename from selfdrive/sensord/sensors/constants.h rename to system/sensord/sensors/constants.h diff --git a/selfdrive/sensord/sensors/file_sensor.cc b/system/sensord/sensors/file_sensor.cc similarity index 100% rename from selfdrive/sensord/sensors/file_sensor.cc rename to system/sensord/sensors/file_sensor.cc diff --git a/selfdrive/sensord/sensors/file_sensor.h b/system/sensord/sensors/file_sensor.h similarity index 88% rename from selfdrive/sensord/sensors/file_sensor.h rename to system/sensord/sensors/file_sensor.h index 39d695167d..07d7e8f946 100644 --- a/selfdrive/sensord/sensors/file_sensor.h +++ b/system/sensord/sensors/file_sensor.h @@ -4,7 +4,7 @@ #include #include "cereal/gen/cpp/log.capnp.h" -#include "selfdrive/sensord/sensors/sensor.h" +#include "system/sensord/sensors/sensor.h" class FileSensor : public Sensor { protected: diff --git a/selfdrive/sensord/sensors/i2c_sensor.cc b/system/sensord/sensors/i2c_sensor.cc similarity index 100% rename from selfdrive/sensord/sensors/i2c_sensor.cc rename to system/sensord/sensors/i2c_sensor.cc diff --git a/selfdrive/sensord/sensors/i2c_sensor.h b/system/sensord/sensors/i2c_sensor.h similarity index 93% rename from selfdrive/sensord/sensors/i2c_sensor.h rename to system/sensord/sensors/i2c_sensor.h index 08ca6f09cd..ccac526c12 100644 --- a/selfdrive/sensord/sensors/i2c_sensor.h +++ b/system/sensord/sensors/i2c_sensor.h @@ -8,8 +8,8 @@ #include "common/gpio.h" #include "common/swaglog.h" -#include "selfdrive/sensord/sensors/constants.h" -#include "selfdrive/sensord/sensors/sensor.h" +#include "system/sensord/sensors/constants.h" +#include "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); diff --git a/selfdrive/sensord/sensors/light_sensor.cc b/system/sensord/sensors/light_sensor.cc similarity index 92% rename from selfdrive/sensord/sensors/light_sensor.cc rename to system/sensord/sensors/light_sensor.cc index 58c602ea39..99e321b47d 100644 --- a/selfdrive/sensord/sensors/light_sensor.cc +++ b/system/sensord/sensors/light_sensor.cc @@ -3,7 +3,7 @@ #include #include "common/timing.h" -#include "selfdrive/sensord/sensors/constants.h" +#include "system/sensord/sensors/constants.h" LightSensor::LightSensor(std::string filename) : FileSensor(filename) {} diff --git a/selfdrive/sensord/sensors/light_sensor.h b/system/sensord/sensors/light_sensor.h similarity index 100% rename from selfdrive/sensord/sensors/light_sensor.h rename to system/sensord/sensors/light_sensor.h diff --git a/selfdrive/sensord/sensors/lsm6ds3_accel.cc b/system/sensord/sensors/lsm6ds3_accel.cc similarity index 100% rename from selfdrive/sensord/sensors/lsm6ds3_accel.cc rename to system/sensord/sensors/lsm6ds3_accel.cc diff --git a/selfdrive/sensord/sensors/lsm6ds3_accel.h b/system/sensord/sensors/lsm6ds3_accel.h similarity index 97% rename from selfdrive/sensord/sensors/lsm6ds3_accel.h rename to system/sensord/sensors/lsm6ds3_accel.h index c3f66f5803..69667cb759 100644 --- a/selfdrive/sensord/sensors/lsm6ds3_accel.h +++ b/system/sensord/sensors/lsm6ds3_accel.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define LSM6DS3_ACCEL_I2C_ADDR 0x6A diff --git a/selfdrive/sensord/sensors/lsm6ds3_gyro.cc b/system/sensord/sensors/lsm6ds3_gyro.cc similarity index 100% rename from selfdrive/sensord/sensors/lsm6ds3_gyro.cc rename to system/sensord/sensors/lsm6ds3_gyro.cc diff --git a/selfdrive/sensord/sensors/lsm6ds3_gyro.h b/system/sensord/sensors/lsm6ds3_gyro.h similarity index 96% rename from selfdrive/sensord/sensors/lsm6ds3_gyro.h rename to system/sensord/sensors/lsm6ds3_gyro.h index 220e6b0cec..adaae62dd2 100644 --- a/selfdrive/sensord/sensors/lsm6ds3_gyro.h +++ b/system/sensord/sensors/lsm6ds3_gyro.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define LSM6DS3_GYRO_I2C_ADDR 0x6A diff --git a/selfdrive/sensord/sensors/lsm6ds3_temp.cc b/system/sensord/sensors/lsm6ds3_temp.cc similarity index 100% rename from selfdrive/sensord/sensors/lsm6ds3_temp.cc rename to system/sensord/sensors/lsm6ds3_temp.cc diff --git a/selfdrive/sensord/sensors/lsm6ds3_temp.h b/system/sensord/sensors/lsm6ds3_temp.h similarity index 92% rename from selfdrive/sensord/sensors/lsm6ds3_temp.h rename to system/sensord/sensors/lsm6ds3_temp.h index 1d6bcc228a..1b5b621814 100644 --- a/selfdrive/sensord/sensors/lsm6ds3_temp.h +++ b/system/sensord/sensors/lsm6ds3_temp.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define LSM6DS3_TEMP_I2C_ADDR 0x6A diff --git a/selfdrive/sensord/sensors/mmc5603nj_magn.cc b/system/sensord/sensors/mmc5603nj_magn.cc similarity index 100% rename from selfdrive/sensord/sensors/mmc5603nj_magn.cc rename to system/sensord/sensors/mmc5603nj_magn.cc diff --git a/selfdrive/sensord/sensors/mmc5603nj_magn.h b/system/sensord/sensors/mmc5603nj_magn.h similarity index 94% rename from selfdrive/sensord/sensors/mmc5603nj_magn.h rename to system/sensord/sensors/mmc5603nj_magn.h index a364c7c37a..fce3f3fecb 100644 --- a/selfdrive/sensord/sensors/mmc5603nj_magn.h +++ b/system/sensord/sensors/mmc5603nj_magn.h @@ -1,6 +1,6 @@ #pragma once -#include "selfdrive/sensord/sensors/i2c_sensor.h" +#include "system/sensord/sensors/i2c_sensor.h" // Address of the chip on the bus #define MMC5603NJ_I2C_ADDR 0x30 diff --git a/selfdrive/sensord/sensors/sensor.h b/system/sensord/sensors/sensor.h similarity index 100% rename from selfdrive/sensord/sensors/sensor.h rename to system/sensord/sensors/sensor.h diff --git a/selfdrive/sensord/sensors_qcom2.cc b/system/sensord/sensors_qcom2.cc similarity index 90% rename from selfdrive/sensord/sensors_qcom2.cc rename to system/sensord/sensors_qcom2.cc index fc8dc8620b..349c67f498 100644 --- a/selfdrive/sensord/sensors_qcom2.cc +++ b/system/sensord/sensors_qcom2.cc @@ -12,17 +12,17 @@ #include "common/swaglog.h" #include "common/timing.h" #include "common/util.h" -#include "selfdrive/sensord/sensors/bmx055_accel.h" -#include "selfdrive/sensord/sensors/bmx055_gyro.h" -#include "selfdrive/sensord/sensors/bmx055_magn.h" -#include "selfdrive/sensord/sensors/bmx055_temp.h" -#include "selfdrive/sensord/sensors/constants.h" -#include "selfdrive/sensord/sensors/light_sensor.h" -#include "selfdrive/sensord/sensors/lsm6ds3_accel.h" -#include "selfdrive/sensord/sensors/lsm6ds3_gyro.h" -#include "selfdrive/sensord/sensors/lsm6ds3_temp.h" -#include "selfdrive/sensord/sensors/mmc5603nj_magn.h" -#include "selfdrive/sensord/sensors/sensor.h" +#include "system/sensord/sensors/bmx055_accel.h" +#include "system/sensord/sensors/bmx055_gyro.h" +#include "system/sensord/sensors/bmx055_magn.h" +#include "system/sensord/sensors/bmx055_temp.h" +#include "system/sensord/sensors/constants.h" +#include "system/sensord/sensors/light_sensor.h" +#include "system/sensord/sensors/lsm6ds3_accel.h" +#include "system/sensord/sensors/lsm6ds3_gyro.h" +#include "system/sensord/sensors/lsm6ds3_temp.h" +#include "system/sensord/sensors/mmc5603nj_magn.h" +#include "system/sensord/sensors/sensor.h" #define I2C_BUS_IMU 1 diff --git a/selfdrive/sensord/tests/__init__.py b/system/sensord/tests/__init__.py similarity index 100% rename from selfdrive/sensord/tests/__init__.py rename to system/sensord/tests/__init__.py diff --git a/selfdrive/sensord/tests/test_pigeond.py b/system/sensord/tests/test_pigeond.py similarity index 100% rename from selfdrive/sensord/tests/test_pigeond.py rename to system/sensord/tests/test_pigeond.py diff --git a/selfdrive/sensord/tests/test_sensord.py b/system/sensord/tests/test_sensord.py similarity index 100% rename from selfdrive/sensord/tests/test_sensord.py rename to system/sensord/tests/test_sensord.py diff --git a/selfdrive/sensord/tests/ttff_test.py b/system/sensord/tests/ttff_test.py similarity index 100% rename from selfdrive/sensord/tests/ttff_test.py rename to system/sensord/tests/ttff_test.py diff --git a/system/ubloxd/.gitignore b/system/ubloxd/.gitignore new file mode 100644 index 0000000000..05263ff67c --- /dev/null +++ b/system/ubloxd/.gitignore @@ -0,0 +1,2 @@ +ubloxd +tests/test_glonass_runner diff --git a/system/ubloxd/SConscript b/system/ubloxd/SConscript new file mode 100644 index 0000000000..fff0986efd --- /dev/null +++ b/system/ubloxd/SConscript @@ -0,0 +1,20 @@ +Import('env', 'common', 'cereal', 'messaging') + +loc_libs = [cereal, messaging, 'zmq', common, 'capnp', 'kj', 'kaitai', 'pthread'] + +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) + + # 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('test'): + 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 diff --git a/selfdrive/locationd/generated/glonass.cpp b/system/ubloxd/generated/glonass.cpp similarity index 100% rename from selfdrive/locationd/generated/glonass.cpp rename to system/ubloxd/generated/glonass.cpp diff --git a/selfdrive/locationd/generated/glonass.h b/system/ubloxd/generated/glonass.h similarity index 100% rename from selfdrive/locationd/generated/glonass.h rename to system/ubloxd/generated/glonass.h diff --git a/selfdrive/locationd/generated/gps.cpp b/system/ubloxd/generated/gps.cpp similarity index 100% rename from selfdrive/locationd/generated/gps.cpp rename to system/ubloxd/generated/gps.cpp diff --git a/selfdrive/locationd/generated/gps.h b/system/ubloxd/generated/gps.h similarity index 100% rename from selfdrive/locationd/generated/gps.h rename to system/ubloxd/generated/gps.h diff --git a/selfdrive/locationd/generated/ubx.cpp b/system/ubloxd/generated/ubx.cpp similarity index 100% rename from selfdrive/locationd/generated/ubx.cpp rename to system/ubloxd/generated/ubx.cpp diff --git a/selfdrive/locationd/generated/ubx.h b/system/ubloxd/generated/ubx.h similarity index 100% rename from selfdrive/locationd/generated/ubx.h rename to system/ubloxd/generated/ubx.h diff --git a/selfdrive/locationd/glonass.ksy b/system/ubloxd/glonass.ksy similarity index 100% rename from selfdrive/locationd/glonass.ksy rename to system/ubloxd/glonass.ksy diff --git a/selfdrive/locationd/glonass_fix.patch b/system/ubloxd/glonass_fix.patch similarity index 68% rename from selfdrive/locationd/glonass_fix.patch rename to system/ubloxd/glonass_fix.patch index fa34a8ef15..7eb973a348 100644 --- a/selfdrive/locationd/glonass_fix.patch +++ b/system/ubloxd/glonass_fix.patch @@ -1,7 +1,7 @@ -diff --git a/selfdrive/locationd/generated/glonass.cpp b/selfdrive/locationd/generated/glonass.cpp +diff --git a/system/ubloxd/generated/glonass.cpp b/system/ubloxd/generated/glonass.cpp index 5b17bc327..b5c6aa610 100644 ---- a/selfdrive/locationd/generated/glonass.cpp -+++ b/selfdrive/locationd/generated/glonass.cpp +--- 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); diff --git a/selfdrive/locationd/gps.ksy b/system/ubloxd/gps.ksy similarity index 100% rename from selfdrive/locationd/gps.ksy rename to system/ubloxd/gps.ksy diff --git a/selfdrive/locationd/test/print_gps_stats.py b/system/ubloxd/tests/print_gps_stats.py similarity index 100% rename from selfdrive/locationd/test/print_gps_stats.py rename to system/ubloxd/tests/print_gps_stats.py diff --git a/selfdrive/locationd/test/test_glonass_kaitai.cc b/system/ubloxd/tests/test_glonass_kaitai.cc similarity index 99% rename from selfdrive/locationd/test/test_glonass_kaitai.cc rename to system/ubloxd/tests/test_glonass_kaitai.cc index 22f5202a3d..5ad274142a 100644 --- a/selfdrive/locationd/test/test_glonass_kaitai.cc +++ b/system/ubloxd/tests/test_glonass_kaitai.cc @@ -6,7 +6,7 @@ #include #include "catch2/catch.hpp" -#include "selfdrive/locationd/generated/glonass.h" +#include "system/ubloxd/generated/glonass.h" typedef std::vector> string_data; diff --git a/selfdrive/locationd/test/test_glonass_runner.cc b/system/ubloxd/tests/test_glonass_runner.cc similarity index 100% rename from selfdrive/locationd/test/test_glonass_runner.cc rename to system/ubloxd/tests/test_glonass_runner.cc diff --git a/selfdrive/locationd/test/test_ublox_processing.py b/system/ubloxd/tests/test_ublox_processing.py similarity index 100% rename from selfdrive/locationd/test/test_ublox_processing.py rename to system/ubloxd/tests/test_ublox_processing.py diff --git a/selfdrive/locationd/test/ublox.py b/system/ubloxd/tests/ublox.py similarity index 99% rename from selfdrive/locationd/test/ublox.py rename to system/ubloxd/tests/ublox.py index 9cffbeac40..80abc64e2c 100644 --- a/selfdrive/locationd/test/ublox.py +++ b/system/ubloxd/tests/ublox.py @@ -54,6 +54,7 @@ MSG_NAV_DOP = 0x04 MSG_NAV_EKFSTATUS = 0x40 MSG_NAV_SBAS = 0x32 MSG_NAV_SOL = 0x06 +MSG_NAV_SAT = 0x35 # RXM messages MSG_RXM_RAW = 0x15 diff --git a/selfdrive/locationd/test/ubloxd.py b/system/ubloxd/tests/ubloxd.py similarity index 98% rename from selfdrive/locationd/test/ubloxd.py rename to system/ubloxd/tests/ubloxd.py index 82aa502ceb..7c7e68b23b 100755 --- a/selfdrive/locationd/test/ubloxd.py +++ b/system/ubloxd/tests/ubloxd.py @@ -60,6 +60,7 @@ def configure_ublox(dev): dev.configure_message_rate(ublox.CLASS_RXM, ublox.MSG_RXM_SFRBX, 1) dev.configure_message_rate(ublox.CLASS_MON, ublox.MSG_MON_HW, 1) dev.configure_message_rate(ublox.CLASS_MON, ublox.MSG_MON_HW2, 1) + dev.configure_message_rate(ublox.CLASS_NAV, ublox.MSG_NAV_SAT, 1) # Query the backup restore status print("backup restore polling message (implement custom response handler!):") diff --git a/selfdrive/locationd/ublox_msg.cc b/system/ubloxd/ublox_msg.cc similarity index 87% rename from selfdrive/locationd/ublox_msg.cc rename to system/ubloxd/ublox_msg.cc index b746989466..83e64b7ddc 100644 --- a/selfdrive/locationd/ublox_msg.cc +++ b/system/ubloxd/ublox_msg.cc @@ -81,7 +81,8 @@ inline uint16_t UbloxMsgParser::get_glonass_year(uint8_t N4, uint16_t Nt) { return year; } -bool UbloxMsgParser::add_data(const uint8_t *incoming_data, uint32_t incoming_data_len, size_t &bytes_consumed) { +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 ); @@ -126,6 +127,9 @@ std::pair> UbloxMsgParser::gen_msg() { return {"ubloxGnss", gen_mon_hw(static_cast(body))}; case 0x0a0b: return {"ubloxGnss", gen_mon_hw2(static_cast(body))}; + case 0x0135: + // TODO return {"ubloxGnss", gen_nav_sat(static_cast(body))}; + return {"ubloxGnss", kj::Array()}; default: LOGE("Unknown message type %x", ubx_message.msg_type()); return {"ubloxGnss", kj::Array()}; @@ -183,7 +187,7 @@ kj::Array UbloxMsgParser::parse_gps_ephemeris(ubx_t::rxm_sfrbx_t *m gps_t subframe(&stream); int subframe_id = subframe.how()->subframe_id(); - if (subframe_id > 3) { + if (subframe_id > 3 || subframe_id < 1) { // dont parse almanac subframes return kj::Array(); } @@ -263,12 +267,8 @@ kj::Array UbloxMsgParser::parse_gps_ephemeris(ubx_t::rxm_sfrbx_t *m } kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_t *msg) { - 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(); - } - + // 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); { @@ -281,23 +281,48 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ kaitai::kstream stream(string_data); glonass_t gl_string(&stream); - int string_number = gl_string.string_number(); - if (string_number > 5 || gl_string.idle_chip()) { + if (string_number < 1 || string_number > 5 || gl_string.idle_chip()) { // dont parse non immediate data, idle_chip == 0 return kj::Array(); } - // immediate data is the same within one superframe - if (glonass_superframes[msg->sv_id()] != gl_string.superframe_number()) { - glonass_strings[msg->sv_id()].clear(); - glonass_superframes[msg->sv_id()] = gl_string.superframe_number(); + // 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->sv_id()][string_number] = string_data; + 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->sv_id()].size() != 5) { + if (glonass_strings[msg->freq_id()].size() != 5) { return kj::Array(); } @@ -308,7 +333,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ // string number 1 { - kaitai::kstream stream(glonass_strings[msg->sv_id()][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()); @@ -321,7 +346,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ // string number 2 { - kaitai::kstream stream(glonass_strings[msg->sv_id()][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()); @@ -335,7 +360,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ // string number 3 { - kaitai::kstream stream(glonass_strings[msg->sv_id()][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()); @@ -349,7 +374,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ // string number 4 { - kaitai::kstream stream(glonass_strings[msg->sv_id()][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()); @@ -367,7 +392,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ // string number 5 { - kaitai::kstream stream(glonass_strings[msg->sv_id()][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()); @@ -396,7 +421,7 @@ kj::Array UbloxMsgParser::parse_glonass_ephemeris(ubx_t::rxm_sfrbx_ eph.setSecond((eph.getTk() & 0x1) * 30); } - glonass_strings[msg->sv_id()].clear(); + glonass_strings[msg->freq_id()].clear(); return capnp::messageToFlatArray(msg_builder); } diff --git a/selfdrive/locationd/ublox_msg.h b/system/ubloxd/ublox_msg.h similarity index 88% rename from selfdrive/locationd/ublox_msg.h rename to system/ubloxd/ublox_msg.h index 6988f20b74..06877cc50d 100644 --- a/selfdrive/locationd/ublox_msg.h +++ b/system/ubloxd/ublox_msg.h @@ -9,9 +9,9 @@ #include "cereal/messaging/messaging.h" #include "common/util.h" -#include "selfdrive/locationd/generated/gps.h" -#include "selfdrive/locationd/generated/glonass.h" -#include "selfdrive/locationd/generated/ubx.h" +#include "system/ubloxd/generated/gps.h" +#include "system/ubloxd/generated/glonass.h" +#include "system/ubloxd/generated/ubx.h" using namespace std::string_literals; @@ -86,7 +86,7 @@ namespace ublox { class UbloxMsgParser { public: - bool add_data(const uint8_t *incoming_data, uint32_t incoming_data_len, size_t &bytes_consumed); + 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);} @@ -109,6 +109,7 @@ class UbloxMsgParser { 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]; @@ -119,5 +120,6 @@ class UbloxMsgParser { {11, 64}, {12, 128}, {13, 256}, {14, 512}, {15, 1024}}; std::unordered_map> glonass_strings; - std::unordered_map glonass_superframes; + std::unordered_map> glonass_string_times; + std::unordered_map> glonass_string_superframes; }; diff --git a/selfdrive/locationd/ubloxd.cc b/system/ubloxd/ubloxd.cc similarity index 88% rename from selfdrive/locationd/ubloxd.cc rename to system/ubloxd/ubloxd.cc index d9b3e7647d..1dae6dc866 100644 --- a/selfdrive/locationd/ubloxd.cc +++ b/system/ubloxd/ubloxd.cc @@ -5,7 +5,7 @@ #include "cereal/messaging/messaging.h" #include "common/swaglog.h" #include "common/util.h" -#include "selfdrive/locationd/ublox_msg.h" +#include "system/ubloxd/ublox_msg.h" ExitHandler do_exit; using namespace ublox; @@ -35,6 +35,7 @@ int main() { 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(); @@ -42,7 +43,7 @@ int main() { while(bytes_consumed < len && !do_exit) { size_t bytes_consumed_this_time = 0U; - if(parser.add_data(data + bytes_consumed, (uint32_t)(len - bytes_consumed), bytes_consumed_this_time)) { + 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(); diff --git a/selfdrive/locationd/ubx.ksy b/system/ubloxd/ubx.ksy similarity index 100% rename from selfdrive/locationd/ubx.ksy rename to system/ubloxd/ubx.ksy diff --git a/tinygrad_repo b/tinygrad_repo index 2e1d47b166..d8dda2af3a 160000 --- a/tinygrad_repo +++ b/tinygrad_repo @@ -1 +1 @@ -Subproject commit 2e1d47b16625ff343516287cdd9e4bcb26f5c4ef +Subproject commit d8dda2af3afcef0bb772fff580cfa8b3eabf7f69 diff --git a/tools/cabana/SConscript b/tools/cabana/SConscript index ddd6208c07..3cb5913c01 100644 --- a/tools/cabana/SConscript +++ b/tools/cabana/SConscript @@ -28,7 +28,7 @@ cabana_env.Depends(assets, Glob('/assets/*', exclude=[assets, assets_src, "asset prev_moc_path = cabana_env['QT_MOCHPREFIX'] cabana_env['QT_MOCHPREFIX'] = os.path.dirname(prev_moc_path) + '/cabana/moc_' -cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'streams/livestream.cc', 'streams/abstractstream.cc', 'streams/replaystream.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbcmanager.cc', +cabana_lib = cabana_env.Library("cabana_lib", ['mainwin.cc', 'streams/livestream.cc', 'streams/abstractstream.cc', 'streams/replaystream.cc', 'binaryview.cc', 'chartswidget.cc', 'historylog.cc', 'videowidget.cc', 'signaledit.cc', 'dbc.cc', 'dbcmanager.cc', 'commands.cc', 'messageswidget.cc', 'route.cc', 'settings.cc', 'util.cc', 'detailwidget.cc', 'tools/findsimilarbits.cc'], LIBS=cabana_libs, FRAMEWORKS=base_frameworks) cabana_env.Program('_cabana', ['cabana.cc', cabana_lib, assets], LIBS=cabana_libs, FRAMEWORKS=base_frameworks) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 120a85a330..b81f7d5e79 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -75,8 +75,8 @@ void BinaryView::addShortcuts() { QShortcut *shortcut_endian = new QShortcut(QKeySequence(Qt::Key_E), this); QObject::connect(shortcut_endian, &QShortcut::activated, [=]{ if (hovered_sig != nullptr) { - const Signal *hovered_sig_prev = hovered_sig; - Signal s = *hovered_sig; + const cabana::Signal *hovered_sig_prev = hovered_sig; + cabana::Signal s = *hovered_sig; s.is_little_endian = !s.is_little_endian; emit editSignal(hovered_sig, s); @@ -89,8 +89,8 @@ void BinaryView::addShortcuts() { QShortcut *shortcut_sign = new QShortcut(QKeySequence(Qt::Key_S), this); QObject::connect(shortcut_sign, &QShortcut::activated, [=]{ if (hovered_sig != nullptr) { - const Signal *hovered_sig_prev = hovered_sig; - Signal s = *hovered_sig; + const cabana::Signal *hovered_sig_prev = hovered_sig; + cabana::Signal s = *hovered_sig; s.is_signed = !s.is_signed; emit editSignal(hovered_sig, s); @@ -117,7 +117,7 @@ QSize BinaryView::minimumSizeHint() const { CELL_HEIGHT * std::min(model->rowCount(), 10) + 2}; } -void BinaryView::highlight(const Signal *sig) { +void BinaryView::highlight(const cabana::Signal *sig) { if (sig != hovered_sig) { for (int i = 0; i < model->items.size(); ++i) { auto &item_sigs = model->items[i].sigs; @@ -176,7 +176,7 @@ void BinaryView::mousePressEvent(QMouseEvent *event) { void BinaryView::highlightPosition(const QPoint &pos) { if (auto index = indexAt(viewport()->mapFromGlobal(pos)); index.isValid()) { auto item = (BinaryViewModel::Item *)index.internalPointer(); - const Signal *sig = item->sigs.isEmpty() ? nullptr : item->sigs.back(); + const cabana::Signal *sig = item->sigs.isEmpty() ? nullptr : item->sigs.back(); highlight(sig); } } @@ -226,8 +226,8 @@ void BinaryView::refresh() { highlightPosition(QCursor::pos()); } -QSet BinaryView::getOverlappingSignals() const { - QSet overlapping; +QSet BinaryView::getOverlappingSignals() const { + QSet overlapping; for (auto &item : model->items) { if (item.sigs.size() > 1) for (auto s : item.sigs) overlapping += s; diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 681ac1fbf3..f677d11941 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -8,7 +8,6 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; class BinaryItemDelegate : public QStyledItemDelegate { public: @@ -44,7 +43,7 @@ public: bool is_msb = false; bool is_lsb = false; QString val = "-"; - QList sigs; + QList sigs; }; std::vector items; @@ -59,19 +58,19 @@ class BinaryView : public QTableView { public: BinaryView(QWidget *parent = nullptr); void setMessage(const MessageId &message_id); - void highlight(const Signal *sig); - QSet getOverlappingSignals() const; + void highlight(const cabana::Signal *sig); + QSet getOverlappingSignals() const; inline void updateState() { model->updateState(); } QSize minimumSizeHint() const override; signals: - void signalClicked(const Signal *sig); - void signalHovered(const Signal *sig); + void signalClicked(const cabana::Signal *sig); + void signalHovered(const cabana::Signal *sig); void addSignal(int start_bit, int size, bool little_endian); - void resizeSignal(const Signal *sig, int from, int size); - void removeSignal(const Signal *sig); - void editSignal(const Signal *origin_s, Signal &s); - void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); + void resizeSignal(const cabana::Signal *sig, int from, int size); + void removeSignal(const cabana::Signal *sig); + void editSignal(const cabana::Signal *origin_s, cabana::Signal &s); + void showChart(const MessageId &id, const cabana::Signal *sig, bool show, bool merge); private: void addShortcuts(); @@ -87,7 +86,7 @@ private: QModelIndex anchor_index; BinaryViewModel *model; BinaryItemDelegate *delegate; - const Signal *resize_sig = nullptr; - const Signal *hovered_sig = nullptr; + const cabana::Signal *resize_sig = nullptr; + const cabana::Signal *hovered_sig = nullptr; friend class BinaryItemDelegate; }; diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 54966be578..184d41ca0b 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -45,7 +45,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QFrame(parent) { toolbar->addWidget(stretch_label); range_lb_action = toolbar->addWidget(range_lb = new QLabel(this)); - range_slider = new QSlider(Qt::Horizontal, this); + range_slider = new LogSlider(1000, Qt::Horizontal, this); range_slider->setMaximumWidth(200); range_slider->setToolTip(tr("Set the chart range")); range_slider->setRange(1, settings.max_cached_minutes * 60); @@ -163,7 +163,7 @@ void ChartsWidget::updateState() { } void ChartsWidget::setMaxChartRange(int value) { - max_chart_range = settings.chart_range = value; + max_chart_range = settings.chart_range = range_slider->value(); updateToolBar(); updateState(); } @@ -189,7 +189,7 @@ void ChartsWidget::settingChanged() { } } -ChartView *ChartsWidget::findChart(const MessageId &id, const Signal *sig) { +ChartView *ChartsWidget::findChart(const MessageId &id, const cabana::Signal *sig) { for (auto c : charts) if (c->hasSeries(id, sig)) return c; return nullptr; @@ -212,7 +212,7 @@ ChartView *ChartsWidget::createChart() { return chart; } -void ChartsWidget::showChart(const MessageId &id, const Signal *sig, bool show, bool merge) { +void ChartsWidget::showChart(const MessageId &id, const cabana::Signal *sig, bool show, bool merge) { ChartView *chart = findChart(id, sig); if (show && !chart) { chart = merge && charts.size() > 0 ? charts.back() : createChart(); @@ -377,7 +377,7 @@ void ChartView::createToolButtons() { }); } -void ChartView::addSeries(const MessageId &msg_id, const Signal *sig) { +void ChartView::addSeries(const MessageId &msg_id, const cabana::Signal *sig) { if (hasSeries(msg_id, sig)) return; QXYSeries *series = createSeries(series_type, getColor(sig)); @@ -388,7 +388,7 @@ void ChartView::addSeries(const MessageId &msg_id, const Signal *sig) { emit seriesAdded(msg_id, sig); } -bool ChartView::hasSeries(const MessageId &msg_id, const Signal *sig) const { +bool ChartView::hasSeries(const MessageId &msg_id, const cabana::Signal *sig) const { return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); } @@ -413,7 +413,7 @@ void ChartView::removeIf(std::function predicate) { } } -void ChartView::signalUpdated(const Signal *sig) { +void ChartView::signalUpdated(const cabana::Signal *sig) { if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.sig == sig; })) { updateTitle(); // TODO: don't update series if only name changed. @@ -421,8 +421,8 @@ void ChartView::signalUpdated(const Signal *sig) { } } -void ChartView::msgUpdated(uint32_t address) { - if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; })) +void ChartView::msgUpdated(MessageId id) { + if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id == id; })) updateTitle(); } @@ -502,7 +502,7 @@ void ChartView::updateSeriesPoints() { } } -void ChartView::updateSeries(const Signal *sig, const std::vector *events, bool clear) { +void ChartView::updateSeries(const cabana::Signal *sig, const std::vector *events, bool clear) { events = events ? events : can->events(); for (auto &s : sigs) { if (!sig || s.sig == sig) { @@ -668,6 +668,16 @@ void ChartView::mousePressEvent(QMouseEvent *event) { if (dropAction == Qt::MoveAction) { return; } + } else if (event->button() == Qt::LeftButton && QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier)) { + if (!can->liveStreaming()) { + // Save current playback state when scrubbing + resume_after_scrub = !can->isPaused(); + if (resume_after_scrub) { + can->pause(true); + } + + is_scrubbing = true; + } } else { QChartView::mousePressEvent(event); } @@ -701,9 +711,27 @@ void ChartView::mouseReleaseEvent(QMouseEvent *event) { } else { QGraphicsView::mouseReleaseEvent(event); } + + // Resume playback if we were scrubbing + is_scrubbing = false; + if (resume_after_scrub) { + can->pause(false); + resume_after_scrub = false; + } } void ChartView::mouseMoveEvent(QMouseEvent *ev) { + // Scrubbing + if (is_scrubbing && QApplication::keyboardModifiers().testFlag(Qt::ShiftModifier)) { + if (chart()->plotArea().contains(ev->pos())) { + double t = chart()->mapToValue(ev->pos()).x(); + // Prevent seeking past the end of the route + t = std::clamp(t, 0., can->totalSeconds()); + can->seekTo(t); + } + return; + } + auto rubber = findChild(); bool is_zooming = rubber && rubber->isVisible(); const auto plot_area = chart()->plotArea(); @@ -954,7 +982,7 @@ void SeriesSelector::updateAvailableList(int index) { } } -void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name) { +void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const cabana::Signal *sig, bool show_msg_name) { QString text = QString(" %1").arg(getColor(sig).name(), sig->name); if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id.toString()); diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index c86c19a04e..bdc924ff83 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -15,7 +15,6 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; using namespace QtCharts; const int CHART_MIN_WIDTH = 300; @@ -31,16 +30,16 @@ class ChartView : public QChartView { public: ChartView(QWidget *parent = nullptr); - void addSeries(const MessageId &msg_id, const Signal *sig); - bool hasSeries(const MessageId &msg_id, const Signal *sig) const; - void updateSeries(const Signal *sig = nullptr, const std::vector *events = nullptr, bool clear = true); + void addSeries(const MessageId &msg_id, const cabana::Signal *sig); + bool hasSeries(const MessageId &msg_id, const cabana::Signal *sig) const; + void updateSeries(const cabana::Signal *sig = nullptr, const std::vector *events = nullptr, bool clear = true); void updatePlot(double cur, double min, double max); void setSeriesType(SeriesType type); void updatePlotArea(int left); struct SigItem { MessageId msg_id; - const Signal *sig = nullptr; + const cabana::Signal *sig = nullptr; QXYSeries *series = nullptr; QVector vals; QVector step_vals; @@ -50,20 +49,20 @@ public: }; signals: - void seriesRemoved(const MessageId &id, const Signal *sig); - void seriesAdded(const MessageId &id, const Signal *sig); + void seriesRemoved(const MessageId &id, const cabana::Signal *sig); + void seriesAdded(const MessageId &id, const cabana::Signal *sig); void zoomIn(double min, double max); void zoomReset(); void remove(); void axisYLabelWidthChanged(int w); private slots: - void msgUpdated(uint32_t address); - void signalUpdated(const Signal *sig); + void signalUpdated(const cabana::Signal *sig); void manageSeries(); void handleMarkerClicked(); - void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); } - void signalRemoved(const Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } + void msgUpdated(MessageId id); + void msgRemoved(MessageId id) { removeIf([=](auto &s) { return s.msg_id == id; }); } + void signalRemoved(const cabana::Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: void createToolButtons(); @@ -97,6 +96,8 @@ private: double cur_sec = 0; const QString mime_type = "application/x-cabanachartview"; SeriesType series_type = SeriesType::Line; + bool is_scrubbing = false; + bool resume_after_scrub = false; friend class ChartsWidget; }; @@ -105,8 +106,8 @@ class ChartsWidget : public QFrame { public: ChartsWidget(QWidget *parent = nullptr); - void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); - inline bool hasSignal(const MessageId &id, const Signal *sig) { return findChart(id, sig) != nullptr; } + void showChart(const MessageId &id, const cabana::Signal *sig, bool show, bool merge); + inline bool hasSignal(const MessageId &id, const cabana::Signal *sig) { return findChart(id, sig) != nullptr; } public slots: void setColumnCount(int n); @@ -132,11 +133,11 @@ private: void updateLayout(); void settingChanged(); bool eventFilter(QObject *obj, QEvent *event) override; - ChartView *findChart(const MessageId &id, const Signal *sig); + ChartView *findChart(const MessageId &id, const cabana::Signal *sig); QLabel *title_label; QLabel *range_lb; - QSlider *range_slider; + LogSlider *range_slider; QAction *range_lb_action; QAction *range_slider_action; bool docking = true; @@ -158,18 +159,18 @@ private: class SeriesSelector : public QDialog { public: struct ListItem : public QListWidgetItem { - ListItem(const MessageId &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} + ListItem(const MessageId &msg_id, const cabana::Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} MessageId msg_id; - const Signal *sig; + const cabana::Signal *sig; }; SeriesSelector(QString title, QWidget *parent); QList seletedItems(); - inline void addSelected(const MessageId &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); } + inline void addSelected(const MessageId &id, const cabana::Signal *sig) { addItemToList(selected_list, id, sig, true); } private: void updateAvailableList(int index); - void addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name = false); + void addItemToList(QListWidget *parent, const MessageId id, const cabana::Signal *sig, bool show_msg_name = false); void add(QListWidgetItem *item); void remove(QListWidgetItem *item); diff --git a/tools/cabana/commands.cc b/tools/cabana/commands.cc index 9b9724aada..337de1c702 100644 --- a/tools/cabana/commands.cc +++ b/tools/cabana/commands.cc @@ -50,7 +50,7 @@ void RemoveMsgCommand::redo() { // AddSigCommand -AddSigCommand::AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent) +AddSigCommand::AddSigCommand(const MessageId &id, const cabana::Signal &sig, QUndoCommand *parent) : id(id), signal(sig), QUndoCommand(parent) { setText(QObject::tr("add signal %1 to %2:%3").arg(sig.name).arg(msgName(id)).arg(id.address)); } @@ -60,7 +60,7 @@ void AddSigCommand::redo() { dbc()->addSignal(id, signal); } // RemoveSigCommand -RemoveSigCommand::RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent) +RemoveSigCommand::RemoveSigCommand(const MessageId &id, const cabana::Signal *sig, QUndoCommand *parent) : id(id), signal(*sig), QUndoCommand(parent) { setText(QObject::tr("remove signal %1 from %2:%3").arg(signal.name).arg(msgName(id)).arg(id.address)); } @@ -70,7 +70,7 @@ void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name); } // EditSignalCommand -EditSignalCommand::EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) +EditSignalCommand::EditSignalCommand(const MessageId &id, const cabana::Signal *sig, const cabana::Signal &new_sig, QUndoCommand *parent) : id(id), old_signal(*sig), new_signal(new_sig), QUndoCommand(parent) { setText(QObject::tr("edit signal %1 in %2:%3").arg(old_signal.name).arg(msgName(id)).arg(id.address)); } diff --git a/tools/cabana/commands.h b/tools/cabana/commands.h index 3565211eb9..2a5f40d584 100644 --- a/tools/cabana/commands.h +++ b/tools/cabana/commands.h @@ -5,7 +5,6 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; class EditMsgCommand : public QUndoCommand { public: @@ -27,41 +26,41 @@ public: private: const MessageId id; - Msg message; + cabana::Msg message; }; class AddSigCommand : public QUndoCommand { public: - AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent = nullptr); + AddSigCommand(const MessageId &id, const cabana::Signal &sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: const MessageId id; - Signal signal = {}; + cabana::Signal signal = {}; }; class RemoveSigCommand : public QUndoCommand { public: - RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent = nullptr); + RemoveSigCommand(const MessageId &id, const cabana::Signal *sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: const MessageId id; - Signal signal = {}; + cabana::Signal signal = {}; }; class EditSignalCommand : public QUndoCommand { public: - EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr); + EditSignalCommand(const MessageId &id, const cabana::Signal *sig, const cabana::Signal &new_sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: const MessageId id; - Signal old_signal = {}; - Signal new_signal = {}; + cabana::Signal old_signal = {}; + cabana::Signal new_signal = {}; }; namespace UndoStack { diff --git a/tools/cabana/dbc.cc b/tools/cabana/dbc.cc new file mode 100644 index 0000000000..ff100e01f7 --- /dev/null +++ b/tools/cabana/dbc.cc @@ -0,0 +1,82 @@ +#include "tools/cabana/dbc.h" +#include "tools/cabana/util.h" + +uint qHash(const MessageId &item) { + return qHash(item.source) ^ qHash(item.address); +} + +std::vector cabana::Msg::getSignals() const { + std::vector ret; + ret.reserve(sigs.size()); + for (auto &sig : sigs) ret.push_back(&sig); + std::sort(ret.begin(), ret.end(), [](auto l, auto r) { return l->start_bit < r->start_bit; }); + return ret; +} + +void cabana::Signal::updatePrecision() { + precision = std::max(num_decimals(factor), num_decimals(offset)); +} + +// helper functions + +static QVector BIG_ENDIAN_START_BITS = []() { + QVector ret; + for (int i = 0; i < 64; i++) + for (int j = 7; j >= 0; j--) + ret.push_back(j + i * 8); + return ret; +}(); + +double get_raw_value(uint8_t *data, size_t data_size, const cabana::Signal &sig) { + int64_t val = 0; + + int i = sig.msb / 8; + int bits = sig.size; + while (i >= 0 && i < data_size && bits > 0) { + int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8; + int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1; + int size = msb - lsb + 1; + + uint64_t d = (data[i] >> (lsb - (i * 8))) & ((1ULL << size) - 1); + val |= d << (bits - size); + + bits -= size; + i = sig.is_little_endian ? i - 1 : i + 1; + } + if (sig.is_signed) { + val -= ((val >> (sig.size - 1)) & 0x1) ? (1ULL << sig.size) : 0; + } + return val * sig.factor + sig.offset; +} + +bool cabana::operator==(const cabana::Signal &l, const cabana::Signal &r) { + return l.name == r.name && l.size == r.size && + l.start_bit == r.start_bit && + l.msb == r.msb && l.lsb == r.lsb && + l.is_signed == r.is_signed && l.is_little_endian == r.is_little_endian && + l.factor == r.factor && l.offset == r.offset && + l.min == r.min && l.max == r.max && l.comment == r.comment && l.unit == r.unit && l.val_desc == r.val_desc; +} + +int bigEndianStartBitsIndex(int start_bit) { return BIG_ENDIAN_START_BITS[start_bit]; } +int bigEndianBitIndex(int index) { return BIG_ENDIAN_START_BITS.indexOf(index); } + +void updateSigSizeParamsFromRange(cabana::Signal &s, int start_bit, int size) { + s.start_bit = s.is_little_endian ? start_bit : bigEndianBitIndex(start_bit); + s.size = size; + if (s.is_little_endian) { + s.lsb = s.start_bit; + s.msb = s.start_bit + s.size - 1; + } else { + s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1); + s.msb = s.start_bit; + } +} + +std::pair getSignalRange(const cabana::Signal *s) { + int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit); + int to = from + s->size - 1; + return {from, to}; +} + +std::vector allDBCNames() { return get_dbc_names(); } diff --git a/tools/cabana/dbc.h b/tools/cabana/dbc.h new file mode 100644 index 0000000000..a2ebbc16cc --- /dev/null +++ b/tools/cabana/dbc.h @@ -0,0 +1,80 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "opendbc/can/common_dbc.h" + +const QString UNTITLED = "untitled"; + +struct MessageId { + uint8_t source; + uint32_t address; + + QString toString() const { + return QString("%1:%2").arg(source).arg(address, 1, 16); + } + + bool operator==(const MessageId &other) const { + return source == other.source && address == other.address; + } + + bool operator!=(const MessageId &other) const { + return !(*this == other); + } + + bool operator<(const MessageId &other) const { + return std::pair{source, address} < std::pair{other.source, other.address}; + } + + bool operator>(const MessageId &other) const { + return std::pair{source, address} > std::pair{other.source, other.address}; + } +}; + +uint qHash(const MessageId &item); +Q_DECLARE_METATYPE(MessageId); + + +typedef QList> ValueDescription; + +namespace cabana { + struct Signal { + QString name; + int start_bit, msb, lsb, size; + bool is_signed; + double factor, offset; + bool is_little_endian; + QString min, max, unit; + QString comment; + ValueDescription val_desc; + int precision = 0; + void updatePrecision(); + }; + + struct Msg { + QString name; + uint32_t size; + QList sigs; + + std::vector getSignals() const; + const cabana::Signal *sig(const QString &sig_name) const { + auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; }); + return it != sigs.end() ? &(*it) : nullptr; + } + }; + + bool operator==(const cabana::Signal &l, const cabana::Signal &r); + inline bool operator!=(const cabana::Signal &l, const cabana::Signal &r) { return !(l == r); } +} + +// Helper functions +double get_raw_value(uint8_t *data, size_t data_size, const cabana::Signal &sig); +int bigEndianStartBitsIndex(int start_bit); +int bigEndianBitIndex(int index); +void updateSigSizeParamsFromRange(cabana::Signal &s, int start_bit, int size); +std::pair getSignalRange(const cabana::Signal *s); +std::vector allDBCNames(); diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 32113c2f22..651367ba57 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -8,8 +8,6 @@ #include #include -namespace dbcmanager { - bool DBCManager::open(const QString &dbc_file_name, QString *error) { QString opendbc_file_path = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, dbc_file_name); QFile file(opendbc_file_path); @@ -19,15 +17,50 @@ bool DBCManager::open(const QString &dbc_file_name, QString *error) { return false; } +bool DBCManager::open(const QString &name, const QString &content, QString *error) { + try { + std::istringstream stream(content.toStdString()); + auto dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); + msgs.clear(); + for (auto &msg : dbc->msgs) { + auto &m = msgs[msg.address]; + m.name = msg.name.c_str(); + m.size = msg.size; + for (auto &s : msg.sigs) { + m.sigs.push_back({}); + auto &sig = m.sigs.last(); + sig.name = s.name.c_str(); + sig.start_bit = s.start_bit; + sig.msb = s.msb; + sig.lsb = s.lsb; + sig.size = s.size; + sig.is_signed = s.is_signed; + sig.factor = s.factor; + sig.offset = s.offset; + sig.is_little_endian = s.is_little_endian; + sig.updatePrecision(); + } + } + parseExtraInfo(content); + name_ = name; + emit DBCFileChanged(); + delete dbc; + } catch (std::exception &e) { + if (error) *error = e.what(); + return false; + } + return true; +} + void DBCManager::parseExtraInfo(const QString &content) { static QRegularExpression bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); static QRegularExpression sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); static QRegularExpression sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"(.*)\";)"); static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (.*);)"); - auto get_sig = [this](uint32_t address, const QString &name) -> Signal * { - auto m = (Msg *)msg(address); - return m ? (Signal *)m->sig(name) : nullptr; + auto get_sig = [this](uint32_t address, const QString &name) -> cabana::Signal * { + auto m = (cabana::Msg *)msg(address); + return m ? (cabana::Signal *)m->sig(name) : nullptr; }; QTextStream stream((QString *)&content); @@ -111,25 +144,37 @@ void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t si auto &m = msgs[id.address]; m.name = name; m.size = size; - emit msgUpdated(id.address); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit msgUpdated({.source = source, .address = id.address}); + } } void DBCManager::removeMsg(const MessageId &id) { msgs.erase(id.address); - emit msgRemoved(id.address); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit msgRemoved({.source = source, .address = id.address}); + } } -void DBCManager::addSignal(const MessageId &id, const Signal &sig) { - if (auto m = const_cast(msg(id.address))) { +void DBCManager::addSignal(const MessageId &id, const cabana::Signal &sig) { + if (auto m = const_cast(msg(id.address))) { m->sigs.push_back(sig); auto s = &m->sigs.last(); - emit signalAdded(id.address, s); + + // This DBC applies to all active sources, emit for every source + for (uint8_t source : sources) { + emit signalAdded({.source = source, .address = id.address}, s); + } } } -void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig) { - if (auto m = const_cast(msg(id))) { - if (auto s = (Signal *)m->sig(sig_name)) { +void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig) { + if (auto m = const_cast(msg(id))) { + if (auto s = (cabana::Signal *)m->sig(sig_name)) { *s = sig; emit signalUpdated(s); } @@ -137,7 +182,7 @@ void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, cons } void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { - if (auto m = const_cast(msg(id))) { + if (auto m = const_cast(msg(id))) { auto it = std::find_if(m->sigs.begin(), m->sigs.end(), [&](auto &s) { return s.name == sig_name; }); if (it != m->sigs.end()) { emit signalRemoved(&(*it)); @@ -146,122 +191,25 @@ void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { } } -DBCManager *dbc() { - static DBCManager dbc_manager(nullptr); - return &dbc_manager; -} - -// Msg - -std::vector Msg::getSignals() const { - std::vector ret; - ret.reserve(sigs.size()); - for (auto &sig : sigs) ret.push_back(&sig); - std::sort(ret.begin(), ret.end(), [](auto l, auto r) { return l->start_bit < r->start_bit; }); - return ret; -} - -// helper functions - -static QVector BIG_ENDIAN_START_BITS = []() { - QVector ret; - for (int i = 0; i < 64; i++) - for (int j = 7; j >= 0; j--) - ret.push_back(j + i * 8); - return ret; -}(); - -int bigEndianStartBitsIndex(int start_bit) { return BIG_ENDIAN_START_BITS[start_bit]; } -int bigEndianBitIndex(int index) { return BIG_ENDIAN_START_BITS.indexOf(index); } - -double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) { - int64_t val = 0; - - int i = sig.msb / 8; - int bits = sig.size; - while (i >= 0 && i < data_size && bits > 0) { - int lsb = (int)(sig.lsb / 8) == i ? sig.lsb : i * 8; - int msb = (int)(sig.msb / 8) == i ? sig.msb : (i + 1) * 8 - 1; - int size = msb - lsb + 1; - - uint64_t d = (data[i] >> (lsb - (i * 8))) & ((1ULL << size) - 1); - val |= d << (bits - size); - - bits -= size; - i = sig.is_little_endian ? i - 1 : i + 1; - } - if (sig.is_signed) { - val -= ((val >> (sig.size - 1)) & 0x1) ? (1ULL << sig.size) : 0; - } - return val * sig.factor + sig.offset; -} - -void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size) { - s.start_bit = s.is_little_endian ? start_bit : bigEndianBitIndex(start_bit); - s.size = size; - if (s.is_little_endian) { - s.lsb = s.start_bit; - s.msb = s.start_bit + s.size - 1; - } else { - s.lsb = bigEndianStartBitsIndex(bigEndianBitIndex(s.start_bit) + s.size - 1); - s.msb = s.start_bit; +QStringList DBCManager::signalNames() { + // Used for autocompletion + QStringList ret; + for (auto const& [_, msg] : msgs) { + for (auto sig: msg.getSignals()) { + ret << sig->name; + } } + ret.sort(); + ret.removeDuplicates(); + return ret; } -std::pair getSignalRange(const Signal *s) { - int from = s->is_little_endian ? s->start_bit : bigEndianBitIndex(s->start_bit); - int to = from + s->size - 1; - return {from, to}; -} - -bool operator==(const Signal &l, const Signal &r) { - return l.name == r.name && l.size == r.size && - l.start_bit == r.start_bit && - l.msb == r.msb && l.lsb == r.lsb && - l.is_signed == r.is_signed && l.is_little_endian == r.is_little_endian && - l.factor == r.factor && l.offset == r.offset && - l.min == r.min && l.max == r.max && l.comment == r.comment && l.unit == r.unit && l.val_desc == r.val_desc; +void DBCManager::updateSources(const QSet &s) { + sources = s; } -} // namespace dbcmanager - -#include "opendbc/can/common_dbc.h" -std::vector dbcmanager::DBCManager::allDBCNames() { return get_dbc_names(); } - -bool dbcmanager::DBCManager::open(const QString &name, const QString &content, QString *error) { - try { - std::istringstream stream(content.toStdString()); - auto dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); - msgs.clear(); - for (auto &msg : dbc->msgs) { - auto &m = msgs[msg.address]; - m.name = msg.name.c_str(); - m.size = msg.size; - for (auto &s : msg.sigs) { - m.sigs.push_back({}); - auto &sig = m.sigs.last(); - sig.name = s.name.c_str(); - sig.start_bit = s.start_bit; - sig.msb = s.msb; - sig.lsb = s.lsb; - sig.size = s.size; - sig.is_signed = s.is_signed; - sig.factor = s.factor; - sig.offset = s.offset; - sig.is_little_endian = s.is_little_endian; - } - } - parseExtraInfo(content); - name_ = name; - emit DBCFileChanged(); - delete dbc; - } catch (std::exception &e) { - if (error) *error = e.what(); - return false; - } - return true; +DBCManager *dbc() { + static DBCManager dbc_manager(nullptr); + return &dbc_manager; } -uint qHash(const MessageId &item) { - return qHash(item.source) ^ qHash(item.address); -} diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index d877347796..dd3d9811c7 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -5,64 +5,10 @@ #include #include #include +#include +#include -struct MessageId { - uint8_t source; - uint32_t address; - - QString toString() const { - return QString("%1:%2").arg(source).arg(address, 1, 16); - } - - bool operator==(const MessageId &other) const { - return source == other.source && address == other.address; - } - - bool operator!=(const MessageId &other) const { - return !(*this == other); - } - - bool operator<(const MessageId &other) const { - return std::pair{source, address} < std::pair{other.source, other.address}; - } - - bool operator>(const MessageId &other) const { - return std::pair{source, address} > std::pair{other.source, other.address}; - } -}; - -uint qHash(const MessageId &item); -Q_DECLARE_METATYPE(MessageId); - -namespace dbcmanager { - -typedef QList> ValueDescription; - -struct Signal { - QString name; - int start_bit, msb, lsb, size; - bool is_signed; - double factor, offset; - bool is_little_endian; - QString min, max, unit; - QString comment; - ValueDescription val_desc; -}; - -struct Msg { - QString name; - uint32_t size; - - std::vector getSignals() const; - const Signal *sig(const QString &sig_name) const { - auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; }); - return it != sigs.end() ? &(*it) : nullptr; - } - -private: - QList sigs; - friend class DBCManager; -}; +#include "tools/cabana/dbc.h" class DBCManager : public QObject { Q_OBJECT @@ -73,49 +19,60 @@ public: bool open(const QString &dbc_file_name, QString *error = nullptr); bool open(const QString &name, const QString &content, QString *error = nullptr); QString generateDBC(); - void addSignal(const MessageId &id, const Signal &sig); - void updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig); + void addSignal(const MessageId &id, const cabana::Signal &sig); + void updateSignal(const MessageId &id, const QString &sig_name, const cabana::Signal &sig); void removeSignal(const MessageId &id, const QString &sig_name); + inline int msgCount() const { return msgs.size(); } - static std::vector allDBCNames(); inline QString name() const { return name_; } void updateMsg(const MessageId &id, const QString &name, uint32_t size); void removeMsg(const MessageId &id); - inline const std::map &messages() const { return msgs; } - inline const Msg *msg(const MessageId &id) const { return msg(id.address); } - inline const Msg *msg(uint32_t address) const { - auto it = msgs.find(address); - return it != msgs.end() ? &it->second : nullptr; + inline std::map getMessages(uint8_t source) { + std::map ret; + for (auto &[address, msg] : msgs) { + MessageId id = {.source = source, .address = address}; + ret[id] = msg; + } + return ret; + } + inline const cabana::Msg *msg(const MessageId &id) const { return msg(id.address); } + inline const cabana::Msg* msg(uint8_t source, const QString &name) { + for (auto &[_, msg] : msgs) { + if (msg.name == name) { + return &msg; + } + } + + return nullptr; } + QStringList signalNames(); + +public slots: + void updateSources(const QSet &s); signals: - void signalAdded(uint32_t address, const Signal *sig); - void signalRemoved(const Signal *sig); - void signalUpdated(const Signal *sig); - void msgUpdated(uint32_t address); - void msgRemoved(uint32_t address); + void signalAdded(MessageId id, const cabana::Signal *sig); + void signalRemoved(const cabana::Signal *sig); + void signalUpdated(const cabana::Signal *sig); + void msgUpdated(MessageId id); + void msgRemoved(MessageId id); void DBCFileChanged(); private: void parseExtraInfo(const QString &content); - std::map msgs; + std::map msgs; QString name_; -}; + QSet sources; -const QString UNTITLED = "untitled"; + inline const cabana::Msg *msg(uint32_t address) const { + auto it = msgs.find(address); + return it != msgs.end() ? &it->second : nullptr; + } +}; -// TODO: Add helper function in dbc.h -double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig); -bool operator==(const Signal &l, const Signal &r); -inline bool operator!=(const Signal &l, const Signal &r) { return !(l == r); } -int bigEndianStartBitsIndex(int start_bit); -int bigEndianBitIndex(int index); -void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size); -std::pair getSignalRange(const Signal *s); DBCManager *dbc(); + inline QString msgName(const MessageId &id) { auto msg = dbc()->msg(id); return msg ? msg->name : UNTITLED; } - -} // namespace dbcmanager diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 01fbccf7db..ab723fa0e2 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -68,7 +68,7 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(binary_view, &BinaryView::resizeSignal, signal_view->model, &SignalModel::resizeSignal); QObject::connect(binary_view, &BinaryView::addSignal, signal_view->model, &SignalModel::addSignal); QObject::connect(binary_view, &BinaryView::signalHovered, signal_view, &SignalView::signalHovered); - QObject::connect(binary_view, &BinaryView::signalClicked, [this](const Signal *s) { signal_view->selectSignal(s, true); }); + QObject::connect(binary_view, &BinaryView::signalClicked, [this](const cabana::Signal *s) { signal_view->selectSignal(s, true); }); QObject::connect(binary_view, &BinaryView::editSignal, signal_view->model, &SignalModel::saveSignal); QObject::connect(binary_view, &BinaryView::removeSignal, signal_view->model, &SignalModel::removeSignal); QObject::connect(binary_view, &BinaryView::showChart, charts, &ChartsWidget::showChart); @@ -177,7 +177,7 @@ void DetailWidget::removeMsg() { // EditMessageDialog EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent) - : original_name(title), QDialog(parent) { + : original_name(title), msg_id(msg_id), QDialog(parent) { setWindowTitle(tr("Edit message: %1").arg(msg_id.toString())); QFormLayout *form_layout = new QFormLayout(this); @@ -194,7 +194,7 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit form_layout->addRow(tr("Size"), size_spin); btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - btn_box->button(QDialogButtonBox::Ok)->setEnabled(false); + validateName(name_edit->text()); form_layout->addRow(btn_box); setFixedWidth(parent->width() * 0.9); @@ -204,11 +204,10 @@ EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &tit } void EditMessageDialog::validateName(const QString &text) { - bool valid = false; + bool valid = text.compare(UNTITLED, Qt::CaseInsensitive) != 0; error_label->setVisible(false); - if (!text.isEmpty() && text != original_name && text.compare(UNTITLED, Qt::CaseInsensitive) != 0) { - valid = std::none_of(dbc()->messages().begin(), dbc()->messages().end(), - [&text](auto &m) { return m.second.name == text; }); + if (!text.isEmpty() && valid && text != original_name) { + valid = dbc()->msg(msg_id.source, text) == nullptr; if (!valid) { error_label->setText(tr("Name already exists")); error_label->setVisible(true); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 0bfd8a74af..cc5bffd534 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -15,6 +15,7 @@ public: EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent); void validateName(const QString &text); + MessageId msg_id; QString original_name; QDialogButtonBox *btn_box; QLineEdit *name_edit; diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 57f65b97d8..830fd30d49 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -14,11 +14,14 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const { if (index.column() == 0) { return QString::number((m.mono_time / (double)1e9) - can->routeStartTime(), 'f', 2); } - return show_signals ? QString::number(m.sig_values[index.column() - 1]) : toHex(m.data); + int i = index.column() - 1; + return show_signals ? QString::number(m.sig_values[i], 'f', sigs[i]->precision) : toHex(m.data); } else if (role == ColorsRole) { return QVariant::fromValue(m.colors); } else if (role == BytesRole) { return m.data; + } else if (role == Qt::TextAlignmentRole) { + return Qt::AlignRight; } return {}; } @@ -235,7 +238,7 @@ LogsWidget::LogsWidget(QWidget *parent) : QFrame(parent) { delegate = new MessageBytesDelegate(this); logs->setItemDelegateForColumn(1, new MessageBytesDelegate(this)); logs->setHorizontalHeader(new HeaderView(Qt::Horizontal, this)); - logs->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | (Qt::Alignment)Qt::TextWordWrap); + logs->horizontalHeader()->setDefaultAlignment(Qt::AlignRight | (Qt::Alignment)Qt::TextWordWrap); logs->horizontalHeader()->setSectionResizeMode(QHeaderView::ResizeToContents); logs->verticalHeader()->setVisible(false); logs->setFrameShape(QFrame::NoFrame); diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index 206d53bc8d..119b61a0e8 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -11,8 +11,6 @@ #include "tools/cabana/streams/abstractstream.h" #include "tools/cabana/util.h" -using namespace dbcmanager; - class HeaderView : public QHeaderView { public: HeaderView(Qt::Orientation orientation, QWidget *parent = nullptr) : QHeaderView(orientation, parent) {} @@ -64,7 +62,7 @@ public: uint64_t last_fetch_time = 0; std::function filter_cmp = nullptr; std::deque messages; - std::vector sigs; + std::vector sigs; bool dynamic_mode = true; bool display_signals_mode = true; }; diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index abcb4948a9..56ffe872d6 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -42,6 +42,7 @@ MainWindow::MainWindow() : QMainWindow() { messages_widget->restoreHeaderState(settings.message_header_state); qRegisterMetaType("uint64_t"); + qRegisterMetaType>("QSet"); qRegisterMetaType("ReplyMsgType"); installMessageHandler([this](ReplyMsgType type, const std::string msg) { // use queued connection to recv the log messages from replay. @@ -70,6 +71,7 @@ MainWindow::MainWindow() : QMainWindow() { QObject::connect(can, &AbstractStream::streamStarted, this, &MainWindow::loadDBCFromFingerprint); QObject::connect(can, &AbstractStream::eventsMerged, this, &MainWindow::updateStatus); QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &MainWindow::DBCFileChanged); + QObject::connect(can, &AbstractStream::sourcesUpdated, dbc(), &DBCManager::updateSources); QObject::connect(UndoStack::instance(), &QUndoStack::cleanChanged, this, &MainWindow::undoStackCleanChanged); QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &MainWindow::undoStackIndexChanged); QObject::connect(&settings, &Settings::changed, this, &MainWindow::updateStatus); @@ -97,7 +99,7 @@ void MainWindow::createActions() { file_menu->addSeparator(); QMenu *load_opendbc_menu = file_menu->addMenu(tr("Load DBC from commaai/opendbc")); // load_opendbc_menu->setStyleSheet("QMenu { menu-scrollable: true; }"); - auto dbc_names = dbc()->allDBCNames(); + auto dbc_names = allDBCNames(); std::sort(dbc_names.begin(), dbc_names.end()); for (const auto &name : dbc_names) { load_opendbc_menu->addAction(QString::fromStdString(name), this, &MainWindow::openOpendbcFile); @@ -214,6 +216,7 @@ void MainWindow::undoStackIndexChanged(int index) { } prev_undostack_index = index; prev_undostack_count = count; + autoSave(); } void MainWindow::undoStackCleanChanged(bool clean) { @@ -255,7 +258,18 @@ void MainWindow::openFile() { void MainWindow::loadFile(const QString &fn) { if (!fn.isEmpty()) { - QFile file(fn); + QString dbc_fn = fn; + + // Prompt user to load auto saved file if it exists. + if (QFile::exists(fn + AUTO_SAVE_EXTENSION)) { + auto ret = QMessageBox::question(this, tr("Auto saved DBC found"), tr("Auto saved DBC file from previous session found. Do you want to load it instead?")); + if (ret == QMessageBox::Yes) { + dbc_fn += AUTO_SAVE_EXTENSION; + UndoStack::instance()->resetClean(); // Force user to save on close so the auto saved file is not lost + } + } + + QFile file(dbc_fn); if (file.open(QIODevice::ReadOnly)) { auto dbc_name = QFileInfo(fn).baseName(); QString error; @@ -298,7 +312,7 @@ void MainWindow::loadDBCFromClipboard() { QString dbc_str = QGuiApplication::clipboard()->text(); QString error; bool ret = dbc()->open("clipboard", dbc_str, &error); - if (ret && dbc()->messages().size() > 0) { + if (ret && dbc()->msgCount() > 0) { QMessageBox::information(this, tr("Load From Clipboard"), tr("DBC Successfully Loaded!")); } else { QMessageBox msg_box(QMessageBox::Warning, tr("Failed to load DBC from clipboard"), tr("Make sure that you paste the text with correct format.")); @@ -340,7 +354,23 @@ void MainWindow::save() { } } +void MainWindow::autoSave() { + if (!current_file.isEmpty() && !UndoStack::instance()->isClean()) { + QFile file(current_file + AUTO_SAVE_EXTENSION); + if (file.open(QIODevice::WriteOnly)) { + file.write(dbc()->generateDBC().toUtf8()); + } + } +} + +void MainWindow::cleanupAutoSaveFile() { + if (!current_file.isEmpty()) { + QFile::remove(current_file + AUTO_SAVE_EXTENSION); + } +} + void MainWindow::saveFile(const QString &fn) { + cleanupAutoSaveFile(); QFile file(fn); if (file.open(QIODevice::WriteOnly)) { file.write(dbc()->generateDBC().toUtf8()); @@ -445,6 +475,7 @@ void MainWindow::dockCharts(bool dock) { } void MainWindow::closeEvent(QCloseEvent *event) { + cleanupAutoSaveFile(); remindSaveChanges(); main_win = nullptr; diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index 1c21d69370..3258b95cde 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -13,6 +13,8 @@ #include "tools/cabana/videowidget.h" #include "tools/cabana/tools/findsimilarbits.h" +const QString AUTO_SAVE_EXTENSION = ".tmp"; + class MainWindow : public QMainWindow { Q_OBJECT @@ -42,6 +44,8 @@ signals: protected: void remindSaveChanges(); void saveFile(const QString &fn); + void autoSave(); + void cleanupAutoSaveFile(); void setCurrentFile(const QString &fn); void updateRecentFileActions(); void createActions(); diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index ed9e241b0c..08dac0d69a 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -8,7 +8,6 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; class MessageListModel : public QAbstractTableModel { Q_OBJECT diff --git a/tools/cabana/settings.cc b/tools/cabana/settings.cc index 23f001efff..00bbb94de5 100644 --- a/tools/cabana/settings.cc +++ b/tools/cabana/settings.cc @@ -32,7 +32,7 @@ void Settings::save() { void Settings::load() { QSettings s("settings", QSettings::IniFormat); fps = s.value("fps", 10).toInt(); - max_cached_minutes = s.value("max_cached_minutes", 5).toInt(); + max_cached_minutes = s.value("max_cached_minutes", 30).toInt(); chart_height = s.value("chart_height", 200).toInt(); chart_range = s.value("chart_range", 3 * 60).toInt(); chart_column_count = s.value("chart_column_count", 1).toInt(); diff --git a/tools/cabana/settings.h b/tools/cabana/settings.h index a302d20077..c3ba906576 100644 --- a/tools/cabana/settings.h +++ b/tools/cabana/settings.h @@ -14,7 +14,7 @@ public: void load(); int fps = 10; - int max_cached_minutes = 5; + int max_cached_minutes = 30; int chart_height = 200; int chart_column_count = 1; int chart_range = 3 * 60; // e minutes diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index e425a13f82..673a68a50b 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -1,7 +1,8 @@ #include "tools/cabana/signaledit.h" +#include +#include #include -#include #include #include #include @@ -22,7 +23,7 @@ SignalModel::SignalModel(QObject *parent) : root(new Item), QAbstractItemModel(p QObject::connect(can, &AbstractStream::msgsReceived, this, &SignalModel::updateState); } -void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Signal *sig) { +void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const cabana::Signal *sig) { Item *item = new Item{.sig = sig, .parent = parent_item, .title = sig->name, .type = Item::Sig}; parent_item->children.insert(pos, item); QString titles[]{"Name", "Size", "Little Endian", "Signed", "Offset", "Factor", "Extra Info", "Unit", "Comment", "Minimum Value", "Maximum Value", "Value Descriptions"}; @@ -61,7 +62,7 @@ void SignalModel::updateState(const QHash *msgs) { auto &dat = can->lastMessage(msg_id).dat; int row = 0; for (auto item : root->children) { - QString value = QString::number(get_raw_value((uint8_t *)dat.begin(), dat.size(), *item->sig)); + QString value = QString::number(get_raw_value((uint8_t *)dat.begin(), dat.size(), *item->sig), 'f', item->sig->precision); if (!item->sig->unit.isEmpty()){ value += " " + item->sig->unit; } @@ -104,7 +105,7 @@ Qt::ItemFlags SignalModel::flags(const QModelIndex &index) const { return flags; } -int SignalModel::signalRow(const Signal *sig) const { +int SignalModel::signalRow(const cabana::Signal *sig) const { for (int i = 0; i < root->children.size(); ++i) { if (root->children[i]->sig == sig) return i; } @@ -168,7 +169,7 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r if (role != Qt::EditRole && role != Qt::CheckStateRole) return false; Item *item = getItem(index); - Signal s = *item->sig; + cabana::Signal s = *item->sig; switch (item->type) { case Item::Name: s.name = value.toString(); break; case Item::Size: s.size = value.toInt(); break; @@ -183,6 +184,7 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r case Item::Desc: s.val_desc = value.value(); break; default: return false; } + s.updatePrecision(); bool ret = saveSignal(item->sig, s); emit dataChanged(index, index, {Qt::DisplayRole, Qt::EditRole, Qt::CheckStateRole}); return ret; @@ -203,7 +205,7 @@ void SignalModel::showExtraInfo(const QModelIndex &index) { } } -bool SignalModel::saveSignal(const Signal *origin_s, Signal &s) { +bool SignalModel::saveSignal(const cabana::Signal *origin_s, cabana::Signal &s) { auto msg = dbc()->msg(msg_id); if (s.name != origin_s->name && msg->sig(s.name) != nullptr) { QString text = tr("There is already a signal with the same name '%1'").arg(s.name); @@ -235,15 +237,15 @@ bool SignalModel::saveSignal(const Signal *origin_s, Signal &s) { void SignalModel::addSignal(int start_bit, int size, bool little_endian) { auto msg = dbc()->msg(msg_id); - for (int i = 1; !msg; ++i) { - QString name = QString("NEW_MSG_%1").arg(i); - if (std::none_of(dbc()->messages().begin(), dbc()->messages().end(), [&](auto &m) { return m.second.name == name; })) { + for (int i = 0; !msg; ++i) { + QString name = QString("NEW_MSG_") + QString::number(msg_id.address, 16).toUpper(); + if (!dbc()->msg(msg_id.source, name)) { UndoStack::push(new EditMsgCommand(msg_id, name, can->lastMessage(msg_id).dat.size())); msg = dbc()->msg(msg_id); } } - Signal sig = {.is_little_endian = little_endian, .factor = 1}; + cabana::Signal sig = {.is_little_endian = little_endian, .factor = 1}; for (int i = 1; /**/; ++i) { sig.name = QString("NEW_SIGNAL_%1").arg(i); if (msg->sig(sig.name) == nullptr) break; @@ -252,24 +254,24 @@ void SignalModel::addSignal(int start_bit, int size, bool little_endian) { UndoStack::push(new AddSigCommand(msg_id, sig)); } -void SignalModel::resizeSignal(const Signal *sig, int start_bit, int size) { - Signal s = *sig; +void SignalModel::resizeSignal(const cabana::Signal *sig, int start_bit, int size) { + cabana::Signal s = *sig; updateSigSizeParamsFromRange(s, start_bit, size); saveSignal(sig, s); } -void SignalModel::removeSignal(const Signal *sig) { +void SignalModel::removeSignal(const cabana::Signal *sig) { UndoStack::push(new RemoveSigCommand(msg_id, sig)); } -void SignalModel::handleMsgChanged(uint32_t address) { - if (address == msg_id.address) { +void SignalModel::handleMsgChanged(MessageId id) { + if (id == msg_id) { refresh(); } } -void SignalModel::handleSignalAdded(uint32_t address, const Signal *sig) { - if (address == msg_id.address) { +void SignalModel::handleSignalAdded(MessageId id, const cabana::Signal *sig) { + if (id == msg_id) { int i = 0; for (; i < root->children.size(); ++i) { if (sig->start_bit < root->children[i]->sig->start_bit) break; @@ -280,13 +282,13 @@ void SignalModel::handleSignalAdded(uint32_t address, const Signal *sig) { } } -void SignalModel::handleSignalUpdated(const Signal *sig) { +void SignalModel::handleSignalUpdated(const cabana::Signal *sig) { if (int row = signalRow(sig); row != -1) { emit dataChanged(index(row, 0), index(row, 1), {Qt::DisplayRole, Qt::EditRole, Qt::CheckStateRole}); } } -void SignalModel::handleSignalRemoved(const Signal *sig) { +void SignalModel::handleSignalRemoved(const cabana::Signal *sig) { if (int row = signalRow(sig); row != -1) { beginRemoveRows({}, row, row); delete root->children.takeAt(row); @@ -304,11 +306,17 @@ SignalItemDelegate::SignalItemDelegate(QObject *parent) : QStyledItemDelegate(pa } QSize SignalItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const { - QSize size = QStyledItemDelegate::sizeHint(option, index); - if (index.column() == 0 && !index.parent().isValid()) { - size.rwidth() = std::min(option.widget->size().width() / 2, size.width() + color_label_width + 8); + int width = option.widget->size().width() / 2; + if (index.column() == 0) { + auto text = index.data(Qt::DisplayRole).toString(); + auto it = width_cache.find(text); + if (it == width_cache.end()) { + int spacing = option.widget->style()->pixelMetric(QStyle::PM_TreeViewIndentation) + color_label_width + 8; + it = width_cache.insert(text, option.fontMetrics.width(text) + spacing); + } + width = std::min(width, it.value()); } - return size; + return {width, QApplication::fontMetrics().height()}; } void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { @@ -362,6 +370,14 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie QLineEdit *e = new QLineEdit(parent); e->setFrame(false); e->setValidator(index.row() == 0 ? name_validator : double_validator); + + if (item->type == SignalModel::Item::Name) { + QCompleter *completer = new QCompleter(dbc()->signalNames()); + completer->setCaseSensitivity(Qt::CaseInsensitive); + completer->setFilterMode(Qt::MatchContains); + e->setCompleter(completer); + } + return e; } else if (item->type == SignalModel::Item::Size) { QSpinBox *spin = new QSpinBox(parent); @@ -425,7 +441,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(model, &QAbstractItemModel::modelReset, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &SignalView::rowsChanged); - QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { selectSignal(sig); }); + QObject::connect(dbc(), &DBCManager::signalAdded, [this](MessageId id, const cabana::Signal *sig) { selectSignal(sig); }); setWhatsThis(tr(R"( Signal view
@@ -479,7 +495,7 @@ void SignalView::rowClicked(const QModelIndex &index) { } } -void SignalView::selectSignal(const Signal *sig, bool expand) { +void SignalView::selectSignal(const cabana::Signal *sig, bool expand) { if (int row = model->signalRow(sig); row != -1) { auto idx = model->index(row, 0); if (expand) { @@ -503,12 +519,12 @@ void SignalView::updateChartState() { } } -void SignalView::signalHovered(const Signal *sig) { +void SignalView::signalHovered(const cabana::Signal *sig) { auto &children = model->root->children; for (int i = 0; i < children.size(); ++i) { bool highlight = children[i]->sig == sig; if (std::exchange(children[i]->highlight, highlight) != highlight) { - emit model->dataChanged(model->index(i, 0), model->index(i, 0)); + emit model->dataChanged(model->index(i, 0), model->index(i, 0), {Qt::DecorationRole}); } } } diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index 73a107f5c9..ae73a7b3bc 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -21,7 +21,7 @@ public: Item *parent = nullptr; QList children; - const Signal *sig = nullptr; + const cabana::Signal *sig = nullptr; QString title; bool highlight = false; bool extra_expanded = false; @@ -39,19 +39,19 @@ public: void setMessage(const MessageId &id); void setFilter(const QString &txt); void addSignal(int start_bit, int size, bool little_endian); - bool saveSignal(const Signal *origin_s, Signal &s); - void resizeSignal(const Signal *sig, int start_bit, int size); - void removeSignal(const Signal *sig); + bool saveSignal(const cabana::Signal *origin_s, cabana::Signal &s); + void resizeSignal(const cabana::Signal *sig, int start_bit, int size); + void removeSignal(const cabana::Signal *sig); Item *getItem(const QModelIndex &index) const; - int signalRow(const Signal *sig) const; + int signalRow(const cabana::Signal *sig) const; void showExtraInfo(const QModelIndex &index); private: - void insertItem(SignalModel::Item *parent_item, int pos, const Signal *sig); - void handleSignalAdded(uint32_t address, const Signal *sig); - void handleSignalUpdated(const Signal *sig); - void handleSignalRemoved(const Signal *sig); - void handleMsgChanged(uint32_t address); + void insertItem(SignalModel::Item *parent_item, int pos, const cabana::Signal *sig); + void handleSignalAdded(MessageId id, const cabana::Signal *sig); + void handleSignalUpdated(const cabana::Signal *sig); + void handleSignalRemoved(const cabana::Signal *sig); + void handleMsgChanged(MessageId id); void refresh(); void updateState(const QHash *msgs); @@ -85,6 +85,7 @@ public: QValidator *name_validator, *double_validator; QFont small_font; const int color_label_width = 18; + mutable QHash width_cache; }; class SignalView : public QFrame { @@ -93,15 +94,15 @@ class SignalView : public QFrame { public: SignalView(ChartsWidget *charts, QWidget *parent); void setMessage(const MessageId &id); - void signalHovered(const Signal *sig); + void signalHovered(const cabana::Signal *sig); void updateChartState(); - void selectSignal(const Signal *sig, bool expand = false); + void selectSignal(const cabana::Signal *sig, bool expand = false); void rowClicked(const QModelIndex &index); SignalModel *model = nullptr; signals: - void highlight(const Signal *sig); - void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); + void highlight(const cabana::Signal *sig); + void showChart(const MessageId &id, const cabana::Signal *sig, bool show, bool merge); private: void rowsChanged(); diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 3e631d3709..c8ff449098 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -1,4 +1,6 @@ #include "tools/cabana/streams/abstractstream.h" +#include +#include AbstractStream *can = nullptr; @@ -37,6 +39,11 @@ bool AbstractStream::updateEvent(const Event *event) { data.colors = tracker.colors; data.last_change_t = tracker.last_change_t; data.bit_change_counts = tracker.bit_change_counts; + + if (!sources.contains(id.source)) { + sources.insert(id.source); + emit sourcesUpdated(sources); + } } double ts = millis_since_boot(); @@ -59,40 +66,62 @@ const CanData &AbstractStream::lastMessage(const MessageId &id) { return it != can_msgs.end() ? it.value() : empty_data; } -void AbstractStream::updateLastMsgsTo(double sec) { - QHash last_msgs; - last_msgs.reserve(can_msgs.size()); - double route_start_time = routeStartTime(); - uint64_t last_ts = (sec + route_start_time) * 1e9; - auto evs = events(); - auto last = std::upper_bound(evs->rbegin(), evs->rend(), last_ts, [](uint64_t ts, auto &e) { return e->mono_time < ts; }); - for (auto it = last; it != evs->rend(); ++it) { +static QHash parseEvents(std::vector::const_reverse_iterator first, + std::vector::const_reverse_iterator last, double route_start_time) { + QHash msgs; + msgs.reserve(500); + for (auto it = first; it != last; ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - auto &m = last_msgs[{.source = c.getSrc(), .address = c.getAddress()}]; + auto &m = msgs[{.source = c.getSrc(), .address = c.getAddress()}]; if (++m.count == 1) { m.ts = ((*it)->mono_time / 1e9) - route_start_time; m.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); m.colors = QVector(m.dat.size(), QColor(0, 0, 0, 0)); m.last_change_t = QVector(m.dat.size(), m.ts); m.bit_change_counts.resize(m.dat.size()); - } else { - m.freq = m.count / std::max(1.0, m.ts); } } } } + return msgs; +}; + +// it is thread safe to update data in updateLastMsgsTo. +// updateEvent will not be called before replayStream::seekedTo return. +void AbstractStream::updateLastMsgsTo(double sec) { + uint64_t ts = (sec + routeStartTime()) * 1e9; + const uint64_t delta = std::max(std::ceil(sec / std::thread::hardware_concurrency()), 30.0) * 1e9; + const auto evs = events(); + auto first = std::upper_bound(evs->crbegin(), evs->crend(), ts, [](uint64_t ts, auto &e) { return ts > e->mono_time; }); + QFutureSynchronizer> synchronizer; + while(first != evs->crend()) { + ts = (*first)->mono_time > delta ? (*first)->mono_time - delta : 0; + auto last = std::lower_bound(first, evs->crend(), ts, [](auto &e, uint64_t ts) { return e->mono_time > ts; }); + synchronizer.addFuture(QtConcurrent::run(parseEvents, first, last, routeStartTime())); + first = last; + } + synchronizer.waitForFinished(); - // it is thread safe to update data here. - // updateEvent will not be called before replayStream::seekedTo return. new_msgs->clear(); change_trackers.clear(); - counters.clear(); can_msgs.clear(); - for (auto it = last_msgs.cbegin(); it != last_msgs.cend(); ++it) { - can_msgs[it.key()] = it.value(); - counters[it.key()] = it.value().count; + counters.clear(); + for (const auto &f : synchronizer.futures()) { + auto msgs = f.result(); + for (auto it = msgs.cbegin(); it != msgs.cend(); ++it) { + counters[it.key()] += it.value().count; + auto m = can_msgs.find(it.key()); + if (m == can_msgs.end()) { + m = can_msgs.insert(it.key(), it.value()); + } else { + m.value().count += it.value().count; + } + m.value().freq = m.value().count / std::max(1.0, m.value().ts); + } } - emit updated(); - emit msgsReceived(&can_msgs); + QTimer::singleShot(0, [this]() { + emit updated(); + emit msgsReceived(&can_msgs); + }); } diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index e582682971..de7c394303 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -52,9 +52,11 @@ signals: void updated(); void msgsReceived(const QHash *); void received(QHash *); + void sourcesUpdated(const QSet &s); public: QHash can_msgs; + QSet sources; protected: void process(QHash *); diff --git a/tools/cabana/streams/livestream.cc b/tools/cabana/streams/livestream.cc index 8f63d3baec..592d883c4c 100644 --- a/tools/cabana/streams/livestream.cc +++ b/tools/cabana/streams/livestream.cc @@ -45,12 +45,11 @@ void LiveStream::streamThread() { } void LiveStream::handleEvent(Event *evt) { - current_ts = evt->mono_time; - if (start_ts == 0 || current_ts < start_ts) { - if (current_ts < start_ts) { + if (start_ts == 0 || evt->mono_time < start_ts) { + if (evt->mono_time < start_ts) { qDebug() << "stream is looping back to old time stamp"; } - start_ts = current_ts.load(); + start_ts = current_ts = evt->mono_time; emit streamStarted(); } @@ -58,19 +57,19 @@ void LiveStream::handleEvent(Event *evt) { can_events.push_back(evt); if (!pause_) { if (speed_ < 1 && last_update_ts > 0) { - auto it = std::upper_bound(can_events.begin(), can_events.end(), last_update_event_ts, [](uint64_t ts, auto &e) { + auto it = std::upper_bound(can_events.cbegin(), can_events.cend(), current_ts, [](uint64_t ts, auto &e) { return ts < e->mono_time; }); + if (it != can_events.cend()) { + bool skip = (nanos_since_boot() - last_update_ts) < ((*it)->mono_time - current_ts) / speed_; + if (skip) return; - if (it != can_events.end() && - (nanos_since_boot() - last_update_ts) < ((*it)->mono_time - last_update_event_ts) / speed_) { - return; + evt = *it; } - evt = (*it); } - updateEvent(evt); - last_update_event_ts = evt->mono_time; + current_ts = evt->mono_time; last_update_ts = nanos_since_boot(); + updateEvent(evt); } } diff --git a/tools/cabana/streams/livestream.h b/tools/cabana/streams/livestream.h index ba20032b67..43f67ae95f 100644 --- a/tools/cabana/streams/livestream.h +++ b/tools/cabana/streams/livestream.h @@ -32,7 +32,6 @@ protected: std::atomic current_ts = 0; std::atomic speed_ = 1; std::atomic pause_ = false; - uint64_t last_update_event_ts = 0; uint64_t last_update_ts = 0; const QString zmq_address; diff --git a/tools/cabana/tests/test_cabana.cc b/tools/cabana/tests/test_cabana.cc index 6f9f2d016b..8445867acb 100644 --- a/tools/cabana/tests/test_cabana.cc +++ b/tools/cabana/tests/test_cabana.cc @@ -5,7 +5,6 @@ #include "tools/replay/logreader.h" #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; // demo route, first segment const std::string TEST_RLOG_URL = "https://commadata2.blob.core.windows.net/commadata2/4cf7a6ad03080c90/2021-09-29--13-46-36/0/rlog.bz2"; @@ -16,11 +15,11 @@ TEST_CASE("DBCManager::generateDBC") { DBCManager dbc_from_generated(nullptr); dbc_from_generated.open("", dbc_origin.generateDBC()); - auto &msgs = dbc_origin.messages(); - auto &new_msgs = dbc_from_generated.messages(); - REQUIRE(msgs.size() == new_msgs.size()); - for (auto &[address, m] : msgs) { - auto &new_m = new_msgs.at(address); + REQUIRE(dbc_origin.msgCount() == dbc_from_generated.msgCount()); + auto msgs = dbc_origin.getMessages(0); + auto new_msgs = dbc_from_generated.getMessages(0); + for (auto &[id, m] : msgs) { + auto &new_m = new_msgs.at(id); REQUIRE(m.name == new_m.name); REQUIRE(m.size == new_m.size); REQUIRE(m.getSignals().size() == new_m.getSignals().size()); @@ -44,7 +43,7 @@ TEST_CASE("Parse can messages") { if (e->which == cereal::Event::Which::CAN) { std::map, std::vector> values_1; for (const auto &c : e->event.getCan()) { - const auto msg = dbc.msg(c.getAddress()); + const auto msg = dbc.msg({.source = c.getSrc(), .address = c.getAddress()}); if (c.getSrc() == 0 && msg) { for (auto sig : msg->getSignals()) { double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), *sig); diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index 27cb7bced8..7768359df4 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -9,7 +9,6 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::WindowFlags() | Qt::Window) { setWindowTitle(tr("Find similar bits")); @@ -30,8 +29,9 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi bus_combo->setCurrentIndex(0); msg_cb = new QComboBox(this); - for (auto &[address, msg] : dbc()->messages()) { - msg_cb->addItem(msg.name, address); + // TODO: update when bus_combo changes + for (auto &[id, msg] : dbc()->getMessages(0)) { + msg_cb->addItem(msg.name, id.address); } msg_cb->model()->sort(0); msg_cb->setCurrentIndex(0); diff --git a/tools/cabana/tools/findsimilarbits.h b/tools/cabana/tools/findsimilarbits.h index ba9b063baf..53d7806a8f 100644 --- a/tools/cabana/tools/findsimilarbits.h +++ b/tools/cabana/tools/findsimilarbits.h @@ -7,7 +7,6 @@ #include #include "tools/cabana/dbcmanager.h" -using namespace dbcmanager; class FindSimilarBitsDlg : public QDialog { Q_OBJECT diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index 1a0b9d93ef..b37b7911ed 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -128,7 +128,7 @@ void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem & } } -QColor getColor(const Signal *sig) { +QColor getColor(const cabana::Signal *sig) { float h = 19 * (float)sig->lsb / 64.0; h = fmod(h, 1.0); @@ -170,6 +170,8 @@ QToolButton *toolButton(const QString &icon, const QString &tooltip) { btn->setIcon(utils::icon(icon)); btn->setToolTip(tooltip); btn->setAutoRaise(true); + const int metric = qApp->style()->pixelMetric(QStyle::PM_SmallIconSize); + btn->setIconSize({metric, metric}); return btn; }; @@ -182,3 +184,13 @@ QString toHex(uint8_t byte) { }(); return hex[byte]; } + +int num_decimals(double num) { + const QString string = QString::number(num); + const QStringList split = string.split('.'); + if (split.size() == 1) { + return 0; + } else { + return split[1].size(); + } + } diff --git a/tools/cabana/util.h b/tools/cabana/util.h index cf1b5d4b20..3cf14982a9 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include @@ -11,8 +12,7 @@ #include #include -#include "tools/cabana/dbcmanager.h" -using namespace dbcmanager; +#include "tools/cabana/dbc.h" class ChangeTracker { public: @@ -30,6 +30,23 @@ private: QByteArray prev_dat; }; +class LogSlider : public QSlider { + Q_OBJECT + +public: + LogSlider(double factor, Qt::Orientation orientation, QWidget *parent = nullptr) : factor(factor), QSlider(orientation, parent) {}; + + void setRange(double min, double max) { QSlider::setRange(logScale(min), logScale(max)); } + int value() const { return invLogScale(QSlider::value()); } + void setValue(int value) { QSlider::setValue(logScale(value)); } + +private: + double factor; + int logScale(int value) const { return factor * std::log10(value); } + int invLogScale(int value) const { return std::pow(10, value / factor); } +}; + + enum { ColorsRole = Qt::UserRole + 1, BytesRole = Qt::UserRole + 2 @@ -59,7 +76,7 @@ public: inline QString toHex(const QByteArray &dat) { return dat.toHex(' ').toUpper(); } QString toHex(uint8_t byte); -QColor getColor(const dbcmanager::Signal *sig); +QColor getColor(const cabana::Signal *sig); class NameValidator : public QRegExpValidator { Q_OBJECT @@ -74,3 +91,4 @@ QPixmap icon(const QString &id); } QToolButton *toolButton(const QString &icon, const QString &tooltip); +int num_decimals(double num); diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index 1a7e27f1b3..d10b09fec5 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -13,7 +13,6 @@ #include "selfdrive/ui/qt/widgets/controls.h" #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" -using namespace dbcmanager; class Slider : public QSlider { Q_OBJECT diff --git a/tools/gpstest/test_gps.py b/tools/gpstest/test_gps.py index 8bc5dc89a8..2c08c105a1 100644 --- a/tools/gpstest/test_gps.py +++ b/tools/gpstest/test_gps.py @@ -5,7 +5,7 @@ import struct from common.params import Params import cereal.messaging as messaging -import selfdrive.sensord.pigeond as pd +import system.sensord.pigeond as pd from system.hardware import TICI from selfdrive.test.helpers import with_processes diff --git a/tools/gpstest/test_laikad.py b/tools/gpstest/test_laikad.py index 410a9c70d3..24ffa6c424 100644 --- a/tools/gpstest/test_laikad.py +++ b/tools/gpstest/test_laikad.py @@ -4,7 +4,7 @@ import time import unittest import cereal.messaging as messaging -import selfdrive.sensord.pigeond as pd +import system.sensord.pigeond as pd from common.params import Params from system.hardware import TICI diff --git a/tools/lib/README.md b/tools/lib/README.md index 3cf239d2df..d77eef5ac5 100644 --- a/tools/lib/README.md +++ b/tools/lib/README.md @@ -1,6 +1,6 @@ ## LogReader -Route is a class for conveniently accessing all the [logs](/selfdrive/loggerd/) from your routes. The LogReader class reads the non-video logs, i.e. rlog.bz2 and qlog.bz2. There's also a matching FrameReader class for reading the videos. +Route is a class for conveniently accessing all the [logs](/system/loggerd/) from your routes. The LogReader class reads the non-video logs, i.e. rlog.bz2 and qlog.bz2. There's also a matching FrameReader class for reading the videos. ```python from tools.lib.route import Route diff --git a/tools/replay/replay.cc b/tools/replay/replay.cc index 178b116a87..b68330f688 100644 --- a/tools/replay/replay.cc +++ b/tools/replay/replay.cc @@ -193,7 +193,7 @@ std::optional Replay::find(FindFlag flag) { void Replay::pause(bool pause) { updateEvents([=]() { - rWarning("%s at %d s", pause ? "paused..." : "resuming", currentSeconds()); + rWarning("%s at %.2f s", pause ? "paused..." : "resuming", currentSeconds()); paused_ = pause; return true; });