Merge remote-tracking branch 'upstream/master' into civic22_long

pull/25364/head
royjr 3 years ago
commit 9b6b1a0b7d
  1. 2
      .github/workflows/selfdrive_tests.yaml
  2. 2
      .github/workflows/tools_tests.yaml
  3. 2
      Jenkinsfile
  4. 18
      RELEASES.md
  5. 2
      cereal
  6. 1
      common/params.cc
  7. 2
      common/version.h
  8. 15
      docs/CARS.md
  9. BIN
      selfdrive/assets/fonts/JetBrainsMono-Medium.ttf
  10. 3
      selfdrive/assets/img_couch.svg
  11. 10
      selfdrive/assets/img_experimental.svg
  12. 4
      selfdrive/assets/img_experimental_grey.svg
  13. 4
      selfdrive/assets/img_experimental_white.svg
  14. 2
      selfdrive/car/gm/values.py
  15. 14
      selfdrive/car/honda/carcontroller.py
  16. 7
      selfdrive/car/hyundai/carcontroller.py
  17. 3
      selfdrive/car/hyundai/hyundaican.py
  18. 6
      selfdrive/car/hyundai/interface.py
  19. 22
      selfdrive/car/hyundai/values.py
  20. 1
      selfdrive/car/tests/routes.py
  21. 9
      selfdrive/car/torque_data/override.yaml
  22. 1
      selfdrive/car/torque_data/params.yaml
  23. 1
      selfdrive/car/torque_data/substitute.yaml
  24. 1
      selfdrive/controls/controlsd.py
  25. 1
      selfdrive/locationd/laikad.py
  26. 12
      selfdrive/locationd/liblocationd.cc
  27. 75
      selfdrive/locationd/locationd.cc
  28. 9
      selfdrive/locationd/locationd.h
  29. 4
      selfdrive/locationd/torqued.py
  30. 1
      selfdrive/loggerd/loggerd.h
  31. 1
      selfdrive/loggerd/tests/test_logger.cc
  32. 2
      selfdrive/test/process_replay/ref_commit
  33. 2
      selfdrive/ui/SConscript
  34. 19
      selfdrive/ui/qt/home.cc
  35. 5
      selfdrive/ui/qt/home.h
  36. 1
      selfdrive/ui/qt/offroad/driverview.cc
  37. 75
      selfdrive/ui/qt/offroad/experimental_mode.cc
  38. 31
      selfdrive/ui/qt/offroad/experimental_mode.h
  39. 66
      selfdrive/ui/qt/offroad/settings.cc
  40. 5
      selfdrive/ui/qt/offroad/settings.h
  41. 14
      selfdrive/ui/qt/onroad.cc
  42. 1
      selfdrive/ui/qt/onroad.h
  43. 2
      selfdrive/ui/qt/sidebar.h
  44. 10
      selfdrive/ui/qt/widgets/cameraview.cc
  45. 1
      selfdrive/ui/qt/widgets/cameraview.h
  46. 8
      selfdrive/ui/qt/widgets/controls.cc
  47. 35
      selfdrive/ui/qt/widgets/controls.h
  48. 4
      selfdrive/ui/qt/window.cc
  49. 2
      selfdrive/ui/qt/window.h
  50. 61
      selfdrive/ui/translations/main_ja.ts
  51. 55
      selfdrive/ui/translations/main_ko.ts
  52. 55
      selfdrive/ui/translations/main_pt-BR.ts
  53. 95
      selfdrive/ui/translations/main_zh-CHS.ts
  54. 55
      selfdrive/ui/translations/main_zh-CHT.ts
  55. 1
      selfdrive/ui/ui.cc
  56. 2
      selfdrive/ui/ui.h
  57. 55
      tools/cabana/detailwidget.cc
  58. 6
      tools/cabana/detailwidget.h
  59. 4
      tools/cabana/historylog.cc
  60. 9
      tools/cabana/mainwin.cc
  61. 15
      tools/cabana/signaledit.cc
  62. 6
      tools/cabana/signaledit.h

@ -7,7 +7,7 @@ on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref != 'refs/heads/master' && github.ref || github.run_id }}-${{ github.event_name }}
group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
cancel-in-progress: true
env:

@ -7,7 +7,7 @@ on:
pull_request:
concurrency:
group: ${{ github.workflow }}-${{ github.ref != 'refs/heads/master' && github.ref || github.run_id }}-${{ github.event_name }}
group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
cancel-in-progress: true
env:

2
Jenkinsfile vendored

@ -59,7 +59,7 @@ pipeline {
branch 'devel-staging'
}
steps {
phone_steps("tici", [
phone_steps("tici-needs-can", [
["build release3-staging & dashcam3-staging", "PUSH=1 $SOURCE_DIR/release/build_release.sh"],
])
}

@ -1,35 +1,35 @@
Version 0.8.17 (2022-11-21)
Version 0.9.0 (2022-11-21)
========================
* New driving model
* Internal feature space information content increased tenfold during training (to ~700 bits), which makes the model dramatically more accurate
* Internal feature space information content increased tenfold during training to ~700 bits, which makes the model dramatically more accurate
* Less reliance on previous frames makes model more reactive and snappy
* Trained in new reprojective simulator
* Trained in 36hrs from scratch, compared to one week for previous releases
* Trained in 36 hours from scratch, compared to one week for previous releases
* Training now simulates both lateral and longitudinal behavior, which allows openpilot to slow down for turns, stop at traffic lights, and more in experimental mode
* Driver monitoring updates
* New bigger model with added end-to-end distracted trigger
* Reduced false positives during driver calibration
* Experimental driving mode
* End-to-end longitudinal control
* Stops for traffic lights and stop signs
* Slows down for turns
* openpilot defaults to chill mode, enable experimental in settings
* openpilot defaults to chill mode, enable experimental mode in settings
* Driver monitoring updates
* New bigger model with added end-to-end distracted trigger
* Reduced false positives during driver calibration
* Self-tuning torque controller: learns parameters live for each car
* Torque controller used on all Toyota, Lexus, Hyundai, Kia, and Genesis models
* UI updates
* Multi-language in navigation
* Matched speeds shown on car's dash
* Multi-language in navigation
* Improved update experience
* Border turns grey while overriding steering
* Bookmark events while driving; view them in comma connect
* New onroad visualization for experimental mode
* AGNOS 6
* tools: new and improved cabana thanks to deanlee!
* Experimental longitudinal support for Volkswagen, CAN-FD Hyundai, and new GM models
* Genesis GV70 2022-23 support thanks to zunichky and sunnyhaibin!
* Hyundai Santa Cruz 2021-22 support thanks to sunnyhaibin!
* Kia Sportage 2023 support thanks to sunnyhaibin!
* Kia Sportage Hybrid 2023 support thanks to sunnyhaibin!
* Kia Stinger 2022 support thanks to sunnyhaibin!
Version 0.8.16 (2022-08-26)
========================

@ -1 +1 @@
Subproject commit afafa0a2a537d775842ab2e1bf20cb9a33b34f9a
Subproject commit 3bae09cf6527674d7eda3a9956242aad94a8f3d2

@ -103,6 +103,7 @@ std::unordered_map<std::string, uint32_t> keys = {
{"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON},
{"DisablePowerDown", PERSISTENT},
{"ExperimentalMode", PERSISTENT},
{"ExperimentalModeConfirmed", PERSISTENT},
{"ExperimentalLongitudinalEnabled", PERSISTENT}, // WARNING: THIS MAY DISABLE AEB
{"DisableUpdates", PERSISTENT},
{"DisengageOnAccelerator", PERSISTENT},

@ -1 +1 @@
#define COMMA_VERSION "0.8.17"
#define COMMA_VERSION "0.9.0"

@ -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.
# 214 Supported Cars
# 215 Supported Cars
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|
@ -60,8 +60,8 @@ A supported vehicle is one that just works when you install a comma three. All s
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai J|
|Hyundai|i30 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E|
|Hyundai|Ioniq 5 (with HDA II) 2022-23|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai Q|
|Hyundai|Ioniq 5 (without HDA II) 2022-23|Highway Driving Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K|
|Hyundai|Ioniq 5 (with HDA II) 2022-23|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai Q|
|Hyundai|Ioniq 5 (without HDA II) 2022-23|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K|
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|
|Hyundai|Ioniq Electric 2020|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H|
|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|
@ -83,13 +83,13 @@ A supported vehicle is one that just works when you install a comma three. All s
|Hyundai|Sonata Hybrid 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A|
|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L|
|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L|
|Hyundai|Tucson Hybrid 2022|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|
|Hyundai|Tucson Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|
|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E|
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA|
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|FCA|
|Kia|Ceed 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E|
|Kia|EV6 (with HDA II) 2022|Highway Driving Assist II|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai P|
|Kia|EV6 (without HDA II) 2022|Highway Driving Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L|
|Kia|EV6 (with HDA II) 2022|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai P|
|Kia|EV6 (without HDA II) 2022|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai L|
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai G|
|Kia|K5 2021-22|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A|
|Kia|Niro EV 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H|
@ -105,8 +105,9 @@ A supported vehicle is one that just works when you install a comma three. All s
|Kia|Sorento 2018|Advanced Smart Cruise Control|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai E|
|Kia|Sportage 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|
|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|
|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|
|Kia|Stinger 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K|
|Kia|Telluride 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H|
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota|
|Lexus|ES 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Toyota|

@ -0,0 +1,3 @@
<svg width="598" height="598" viewBox="0 0 598 598" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M523.25 236.708H510.792V174.417C511.555 158.737 506.091 143.391 495.59 131.723C485.089 120.055 470.401 113.011 454.729 112.125H143.271C127.599 113.011 112.911 120.055 102.409 131.723C91.9096 143.391 86.4454 158.737 87.2083 174.417V236.708H74.75C64.8416 236.72 55.3404 240.66 48.3343 247.668C41.3268 254.674 37.3865 264.175 37.375 274.083V398.667C37.3867 408.575 41.3266 418.076 48.3343 425.082C55.3404 432.09 64.8416 436.03 74.75 436.042H87.2083V473.417C87.2083 477.867 89.5832 481.98 93.4375 484.207C97.2918 486.432 102.042 486.432 105.896 484.207C109.75 481.98 112.125 477.866 112.125 473.417V436.042H485.875V473.417C485.875 477.867 488.25 481.98 492.104 484.207C495.958 486.432 500.708 486.432 504.563 484.207C508.417 481.98 510.792 477.866 510.792 473.417V436.042H523.25C533.158 436.03 542.66 432.09 549.666 425.082C556.673 418.076 560.614 408.575 560.625 398.667V274.083C560.613 264.175 556.673 254.674 549.666 247.668C542.66 240.66 533.158 236.72 523.25 236.708ZM143.271 137.042H454.729C463.783 137.949 472.117 142.373 477.941 149.364C483.765 156.352 486.615 165.349 485.875 174.417V239.006C478.608 241.565 472.313 246.311 467.851 252.593C463.39 258.873 460.982 266.381 460.958 274.086V336.377H137.042V274.086C137.018 266.381 134.61 258.873 130.149 252.593C125.687 246.312 119.392 241.566 112.125 239.006V174.417C111.385 165.349 114.235 156.352 120.059 149.364C125.884 142.374 134.217 137.949 143.271 137.042V137.042ZM62.2917 398.667V274.083C62.2936 270.78 63.6076 267.613 65.9435 265.277C68.2794 262.941 71.4466 261.627 74.7501 261.625H99.6667C102.97 261.627 106.137 262.941 108.473 265.277C110.809 267.613 112.123 270.78 112.125 274.083V411.125H74.7501C71.4467 411.123 68.2797 409.809 65.9436 407.473C63.6074 405.137 62.2937 401.97 62.2917 398.667L62.2917 398.667ZM137.042 361.292H460.958V411.125H137.042V361.292ZM535.708 398.667C535.706 401.97 534.392 405.137 532.056 407.473C529.721 409.809 526.553 411.123 523.25 411.125H485.875V274.083C485.877 270.78 487.191 267.613 489.527 265.277C491.863 262.941 495.03 261.627 498.333 261.625H523.25C526.553 261.627 529.72 262.941 532.057 265.277C534.393 267.613 535.706 270.78 535.708 274.083L535.708 398.667Z" fill="black" fill-opacity="0.4"/>
</svg>

After

Width:  |  Height:  |  Size: 2.3 KiB

@ -0,0 +1,10 @@
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M182.019 181.218C123.429 239.83 67.543 258.769 54.9241 245.243C51.3182 241.636 51.3182 236.226 51.3182 231.717C51.3182 207.37 74.7548 160.481 124.331 114.489C129.74 109.98 129.74 101.864 125.233 96.454C120.725 91.0438 112.612 91.0438 107.204 95.5525C95.4866 106.373 85.5713 117.194 76.5569 128.016C51.3181 89.242 45.9096 61.2866 54.0213 52.2701C63.9367 42.351 100.894 50.4672 144.162 82.9291C157.683 92.8482 171.203 104.57 183.823 117.196C193.738 127.115 203.654 137.936 211.767 148.757C202.754 160.48 192.838 170.399 182.021 181.22L182.019 181.218ZM246.019 54.0753C255.033 63.0928 248.724 91.9498 225.287 128.918C217.174 118.999 209.062 109.982 200.048 100.063C191.034 91.0451 181.119 82.0274 171.204 73.9125C209.064 49.5654 237.006 45.0578 246.019 54.0753ZM264.048 36.04C243.316 15.3002 200.047 24.318 150.471 58.5842C100.894 24.317 56.7244 15.3005 35.9947 36.04C15.2627 56.7799 24.2771 99.1619 59.4313 149.66C38.6993 179.417 26.0793 208.272 26.0793 231.718C26.0793 247.949 32.3888 257.868 36.896 263.278C45.0091 271.394 54.9244 275 67.5433 275C105.403 275 158.583 241.635 200.049 200.157C209.063 191.14 218.077 181.22 225.288 171.301C249.625 209.176 255.034 237.128 246.02 246.144C238.809 253.357 218.076 250.653 193.739 238.028C187.43 235.322 180.218 237.127 176.613 243.438C173.008 249.75 175.712 256.965 182.022 260.571C200.951 270.49 218.979 274.999 232.501 274.999C245.121 274.999 255.036 271.391 263.148 263.277C283.88 242.537 274.866 199.252 240.612 149.657C272.163 105.473 286.583 59.4852 264.05 36.0397L264.048 36.04Z" fill="url(#paint0_radial_1352_397)"/>
<path d="M175.414 154.169C175.414 171.6 161.29 185.729 143.866 185.729C126.441 185.729 112.317 171.6 112.317 154.169C112.317 136.738 126.441 122.609 143.866 122.609C161.29 122.609 175.414 136.738 175.414 154.169Z" fill="#E11C1C"/>
<defs>
<radialGradient id="paint0_radial_1352_397" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(150 150) rotate(90) scale(125)">
<stop offset="0.135417" stop-color="#E11C1C"/>
<stop offset="1" stop-color="#FF8C22"/>
</radialGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

@ -0,0 +1,4 @@
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M182.019 181.218C123.429 239.83 67.543 258.769 54.9241 245.243C51.3182 241.636 51.3182 236.226 51.3182 231.717C51.3182 207.37 74.7548 160.481 124.331 114.489C129.74 109.98 129.74 101.864 125.233 96.454C120.725 91.0438 112.612 91.0438 107.204 95.5525C95.4866 106.373 85.5713 117.194 76.5569 128.016C51.3181 89.242 45.9096 61.2866 54.0213 52.2701C63.9367 42.351 100.894 50.4672 144.162 82.9291C157.683 92.8482 171.203 104.57 183.823 117.196C193.738 127.115 203.654 137.936 211.767 148.757C202.754 160.48 192.838 170.399 182.021 181.22L182.019 181.218ZM246.019 54.0753C255.033 63.0928 248.724 91.9498 225.287 128.918C217.174 118.999 209.062 109.982 200.048 100.063C191.034 91.0451 181.119 82.0274 171.204 73.9125C209.064 49.5654 237.006 45.0578 246.019 54.0753ZM264.048 36.04C243.316 15.3002 200.047 24.318 150.471 58.5842C100.894 24.317 56.7244 15.3005 35.9947 36.04C15.2627 56.7799 24.2771 99.1619 59.4313 149.66C38.6993 179.417 26.0793 208.272 26.0793 231.718C26.0793 247.949 32.3888 257.868 36.896 263.278C45.0091 271.394 54.9244 275 67.5433 275C105.403 275 158.583 241.635 200.049 200.157C209.063 191.14 218.077 181.22 225.288 171.301C249.625 209.176 255.034 237.128 246.02 246.144C238.809 253.357 218.076 250.653 193.739 238.028C187.43 235.322 180.218 237.127 176.613 243.438C173.008 249.75 175.712 256.965 182.022 260.571C200.951 270.49 218.979 274.999 232.501 274.999C245.121 274.999 255.036 271.391 263.148 263.277C283.88 242.537 274.866 199.252 240.612 149.657C272.163 105.473 286.583 59.4852 264.05 36.0397L264.048 36.04Z" fill="black" fill-opacity="0.36"/>
<path d="M175.414 154.169C175.414 171.6 161.29 185.729 143.866 185.729C126.441 185.729 112.317 171.6 112.317 154.169C112.317 136.738 126.441 122.609 143.866 122.609C161.29 122.609 175.414 136.738 175.414 154.169Z" fill="black" fill-opacity="0.36"/>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

@ -0,0 +1,4 @@
<svg width="300" height="300" viewBox="0 0 300 300" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M182.019 181.218C123.429 239.83 67.543 258.769 54.9241 245.243C51.3182 241.636 51.3182 236.226 51.3182 231.717C51.3182 207.37 74.7548 160.481 124.331 114.489C129.74 109.98 129.74 101.864 125.233 96.454C120.725 91.0438 112.612 91.0438 107.204 95.5525C95.4866 106.373 85.5713 117.194 76.5569 128.016C51.3181 89.242 45.9096 61.2866 54.0213 52.2701C63.9367 42.351 100.894 50.4672 144.162 82.9291C157.683 92.8482 171.203 104.57 183.823 117.196C193.738 127.115 203.654 137.936 211.767 148.757C202.754 160.48 192.838 170.399 182.021 181.22L182.019 181.218ZM246.019 54.0753C255.033 63.0928 248.724 91.9498 225.287 128.918C217.174 118.999 209.062 109.982 200.048 100.063C191.034 91.0451 181.119 82.0274 171.204 73.9125C209.064 49.5654 237.006 45.0578 246.019 54.0753ZM264.048 36.04C243.316 15.3002 200.047 24.318 150.471 58.5842C100.894 24.317 56.7244 15.3005 35.9947 36.04C15.2627 56.7799 24.2771 99.1619 59.4313 149.66C38.6993 179.417 26.0793 208.272 26.0793 231.718C26.0793 247.949 32.3888 257.868 36.896 263.278C45.0091 271.394 54.9244 275 67.5433 275C105.403 275 158.583 241.635 200.049 200.157C209.063 191.14 218.077 181.22 225.288 171.301C249.625 209.176 255.034 237.128 246.02 246.144C238.809 253.357 218.076 250.653 193.739 238.028C187.43 235.322 180.218 237.127 176.613 243.438C173.008 249.75 175.712 256.965 182.022 260.571C200.951 270.49 218.979 274.999 232.501 274.999C245.121 274.999 255.036 271.391 263.148 263.277C283.88 242.537 274.866 199.252 240.612 149.657C272.163 105.473 286.583 59.4852 264.05 36.0397L264.048 36.04Z" fill="white"/>
<path d="M175.414 154.169C175.414 171.6 161.29 185.729 143.866 185.729C126.441 185.729 112.317 171.6 112.317 154.169C112.317 136.738 126.441 122.609 143.866 122.609C161.29 122.609 175.414 136.738 175.414 154.169Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.8 KiB

@ -90,7 +90,7 @@ class GMCarInfo(CarInfo):
CAR_INFO: Dict[str, Union[GMCarInfo, List[GMCarInfo]]] = {
CAR.HOLDEN_ASTRA: GMCarInfo("Holden Astra 2017"),
CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0),
CAR.VOLT: GMCarInfo("Chevrolet Volt 2017-18", min_enable_speed=0, video_link="https://youtu.be/QeMCN_4TFfQ"),
CAR.CADILLAC_ATS: GMCarInfo("Cadillac ATS Premium Performance 2018"),
CAR.MALIBU: GMCarInfo("Chevrolet Malibu Premier 2017"),
CAR.ACADIA: GMCarInfo("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo"),

@ -99,6 +99,12 @@ HUDData = namedtuple("HUDData",
"lanes_visible", "fcw", "acc_alert", "steer_required"])
def rate_limit_steer(new_steer, last_steer):
# TODO just hardcoded ramp to min/max in 0.33s for all Honda
MAX_DELTA = 3 * DT_CTRL
return clip(new_steer, last_steer - MAX_DELTA, last_steer + MAX_DELTA)
class CarController:
def __init__(self, dbc_name, CP, VM):
self.CP = CP
@ -116,6 +122,7 @@ class CarController:
self.speed = 0.0
self.gas = 0.0
self.brake = 0.0
self.last_steer = 0.0
def update(self, CC, CS):
actuators = CC.actuators
@ -130,6 +137,10 @@ class CarController:
accel = 0.0
gas, brake = 0.0, 0.0
# *** rate limit steer ***
limited_steer = rate_limit_steer(actuators.steer, self.last_steer)
self.last_steer = limited_steer
# *** apply brake hysteresis ***
pre_limit_brake, self.braking, self.brake_steady = actuator_hysteresis(brake, self.braking, self.brake_steady,
CS.out.vEgo, self.CP.carFingerprint)
@ -143,7 +154,7 @@ class CarController:
# **** process the car messages ****
# steer torque is converted back to CAN reference (positive when steering right)
apply_steer = int(interp(-actuators.steer * self.params.STEER_MAX,
apply_steer = int(interp(-limited_steer * self.params.STEER_MAX,
self.params.STEER_LOOKUP_BP, self.params.STEER_LOOKUP_V))
# Send CAN commands
@ -250,6 +261,7 @@ class CarController:
new_actuators.accel = self.accel
new_actuators.gas = self.gas
new_actuators.brake = self.brake
new_actuators.steer = self.last_steer
self.frame += 1
return new_actuators, can_sends

@ -85,7 +85,7 @@ class CarController:
# *** common hyundai stuff ***
# tester present - w/ no response (keeps relevant ECU disabled)
if self.frame % 100 == 0 and self.CP.openpilotLongitudinalControl:
if self.frame % 100 == 0 and not (self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) and self.CP.openpilotLongitudinalControl:
addr, bus = 0x7d0, 0
if self.CP.flags & HyundaiFlags.CANFD_HDA2.value:
addr, bus = 0x730, 5
@ -122,7 +122,8 @@ class CarController:
can_sends.append(hyundaicanfd.create_lfahda_cluster(self.packer, self.CP, CC.enabled))
if self.CP.openpilotLongitudinalControl:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.frame))
if hda2:
can_sends.extend(hyundaicanfd.create_adrv_messages(self.packer, self.frame))
if self.frame % 2 == 0:
can_sends.append(hyundaicanfd.create_acc_control(self.packer, self.CP, CC.enabled, self.accel_last, accel, stopping, CC.cruiseControl.override,
set_speed_in_units))
@ -175,7 +176,7 @@ class CarController:
if self.frame % 5 == 0 and self.car_fingerprint in (CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021,
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV, CAR.KONA_EV_2022,
CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022,
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020, CAR.SANTA_FE_PHEV_2022):
CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020, CAR.SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022):
can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled))
# 5 Hz ACC options

@ -20,7 +20,8 @@ def create_lkas11(packer, frame, car_fingerprint, apply_steer, steer_req,
if car_fingerprint in (CAR.SONATA, CAR.PALISADE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.SANTA_FE,
CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_SELTOS, CAR.ELANTRA_2021, CAR.GENESIS_G70_2020,
CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_EV, CAR.KONA_HEV, CAR.KONA_EV_2022,
CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022):
CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022,
CAR.SANTA_FE_PHEV_2022, CAR.KIA_STINGER_2022):
values["CF_Lkas_LdwsActivemode"] = int(left_lane) + (int(right_lane) << 1)
values["CF_Lkas_LdwsOpt_USM"] = 2

@ -158,7 +158,7 @@ class CarInterface(CarInterfaceBase):
tire_stiffness_factor = 0.5
if candidate == CAR.KIA_OPTIMA_G4:
ret.minSteerSpeed = 32 * CV.MPH_TO_MS
elif candidate == CAR.KIA_STINGER:
elif candidate in (CAR.KIA_STINGER, CAR.KIA_STINGER_2022):
ret.mass = 1825. + STD_CARGO_KG
ret.wheelbase = 2.78
ret.steerRatio = 14.4 * 1.15 # 15% higher at the center seems reasonable
@ -219,7 +219,7 @@ class CarInterface(CarInterfaceBase):
if candidate in CANFD_CAR:
ret.longitudinalTuning.kpV = [0.1]
ret.longitudinalTuning.kiV = [0.0]
ret.experimentalLongitudinalAvailable = bool(ret.flags & HyundaiFlags.CANFD_HDA2)
ret.experimentalLongitudinalAvailable = candidate in (HYBRID_CAR | EV_CAR) and candidate not in CANFD_RADAR_SCC_CAR
else:
ret.longitudinalTuning.kpV = [0.5]
ret.longitudinalTuning.kiV = [0.0]
@ -283,7 +283,7 @@ class CarInterface(CarInterfaceBase):
@staticmethod
def init(CP, logcan, sendcan):
if CP.openpilotLongitudinalControl:
if CP.openpilotLongitudinalControl and not (CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value):
addr, bus = 0x7d0, 0
if CP.flags & HyundaiFlags.CANFD_HDA2.value:
addr, bus = 0x730, 5

@ -95,6 +95,7 @@ class CAR:
KIA_SORENTO = "KIA SORENTO GT LINE 2018"
KIA_SPORTAGE_HYBRID_5TH_GEN = "KIA SPORTAGE HYBRID 5TH GEN"
KIA_STINGER = "KIA STINGER GT2 2018"
KIA_STINGER_2022 = "KIA STINGER 2022"
KIA_CEED = "KIA CEED INTRO ED 2019"
KIA_EV6 = "KIA EV6 2022"
@ -181,6 +182,7 @@ CAR_INFO: Dict[str, Optional[Union[HyundaiCarInfo, List[HyundaiCarInfo]]]] = {
],
CAR.KIA_SPORTAGE_HYBRID_5TH_GEN: HyundaiCarInfo("Kia Sportage Hybrid 2023", harness=Harness.hyundai_n),
CAR.KIA_STINGER: HyundaiCarInfo("Kia Stinger 2018-20", video_link="https://www.youtube.com/watch?v=MJ94qoofYw0", harness=Harness.hyundai_c),
CAR.KIA_STINGER_2022: HyundaiCarInfo("Kia Stinger 2022", "All", harness=Harness.hyundai_k),
CAR.KIA_CEED: HyundaiCarInfo("Kia Ceed 2019", harness=Harness.hyundai_e),
CAR.KIA_EV6: [
HyundaiCarInfo("Kia EV6 (without HDA II) 2022", "Highway Driving Assist", harness=Harness.hyundai_l),
@ -790,6 +792,23 @@ FW_VERSIONS = {
b'\xf1\x00bcsh8p54 E21\x00\x00\x00\x00\x00\x00\x00SCK0T33NB0\x88\xa2\xe6\xf0',
],
},
CAR.KIA_STINGER_2022: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00CK__ SCC F-CUP 1.00 1.00 99110-J5500 ',
],
(Ecu.engine, 0x7e0, None): [
b'\xf1\x81640R0051\x00\x00\x00\x00\x00\x00\x00\x00',
],
(Ecu.eps, 0x7d4, None): [
b'\xf1\x00CK MDPS R 1.00 5.03 57700-J5380 4C2VR503',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00CK MFC AT AUS RHD 1.00 1.00 99211-J5500 210622',
],
(Ecu.transmission, 0x7e1, None): [
b'\xf1\x87VCNLF11383972DK1vffV\x99\x99\x89\x98\x86eUU\x88wg\x89vfff\x97fff\x99\x87o\xff"\xc1\xf1\x81E30\x00\x00\x00\x00\x00\x00\x00\xf1\x00bcsh8p54 E30\x00\x00\x00\x00\x00\x00\x00SCK0T33GH0\xbe`\xfb\xc6',
],
},
CAR.PALISADE: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00LX2_ SCC F-CUP 1.00 1.04 99110-S8100 ',
@ -1451,7 +1470,7 @@ FEATURES = {
"use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022},
# these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12
"use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022},
"use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022},
}
CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN}
@ -1496,6 +1515,7 @@ DBC = {
CAR.KIA_SELTOS: dbc_dict('hyundai_kia_generic', None),
CAR.KIA_SORENTO: dbc_dict('hyundai_kia_generic', None), # Has 0x5XX messages, but different format
CAR.KIA_STINGER: dbc_dict('hyundai_kia_generic', None),
CAR.KIA_STINGER_2022: dbc_dict('hyundai_kia_generic', None),
CAR.KONA: dbc_dict('hyundai_kia_generic', None),
CAR.KONA_EV: dbc_dict('hyundai_kia_generic', None),
CAR.KONA_EV_2022: dbc_dict('hyundai_kia_generic', None),

@ -111,6 +111,7 @@ routes = [
CarTestRoute("ff973b941a69366f|2022-07-28--22-01-19", HYUNDAI.KONA_EV_2022, segment=11),
CarTestRoute("49f3c13141b6bc87|2021-07-28--08-05-13", HYUNDAI.KONA_HEV),
CarTestRoute("5dddcbca6eb66c62|2020-07-26--13-24-19", HYUNDAI.KIA_STINGER),
CarTestRoute("5b50b883a4259afb|2022-11-09--15-00-42", HYUNDAI.KIA_STINGER_2022),
CarTestRoute("d624b3d19adce635|2020-08-01--14-59-12", HYUNDAI.VELOSTER),
CarTestRoute("d545129f3ca90f28|2022-10-19--09-22-54", HYUNDAI.KIA_EV6), # HDA2
CarTestRoute("68d6a96e703c00c9|2022-09-10--16-09-39", HYUNDAI.KIA_EV6), # HDA1

@ -30,11 +30,10 @@ CHEVROLET SILVERADO 1500 2020: [1.9, 1.9, 0.112]
CHEVROLET EQUINOX 2019: [2.0, 2.0, 0.05]
VOLKSWAGEN PASSAT NMS: [2.5, 2.5, 0.1]
VOLKSWAGEN SHARAN 2ND GEN: [2.5, 2.5, 0.1]
HYUNDAI TUCSON HYBRID 4TH GEN: [2.5, 2.5, 0.0]
HYUNDAI SANTA CRUZ 1ST GEN: [2.7, 2.7, 0.0]
KIA SPORTAGE 5TH GEN: [2.7, 2.7, 0.0]
KIA SPORTAGE HYBRID 5TH GEN: [2.5, 2.5, 0.0]
GENESIS GV70 1ST GEN: [2.42, 2.42, 0.01]
HYUNDAI SANTA CRUZ 1ST GEN: [2.7, 2.7, 0.1]
KIA SPORTAGE 5TH GEN: [2.7, 2.7, 0.1]
KIA SPORTAGE HYBRID 5TH GEN: [2.5, 2.5, 0.1]
GENESIS GV70 1ST GEN: [2.42, 2.42, 0.1]
# Dashcam or fallback configured as ideal car
mock: [10.0, 10, 0.0]

@ -38,6 +38,7 @@ HYUNDAI SANTA FE PlUG-IN HYBRID 2022: [1.6953050513611045, 1.5837614296206861, 0
HYUNDAI SONATA 2019: [2.2200457811703953, 1.2967330275895228, 0.14039920986586393]
HYUNDAI SONATA 2020: [2.9638737459977467, 2.1259108157250735, 0.07813665616927593]
HYUNDAI SONATA HYBRID 2021: [2.8990264092395734, 2.061410192222139, 0.0899805488717382]
HYUNDAI TUCSON HYBRID 4TH GEN: [2.035545, 2.035545, 0.110272]
JEEP GRAND CHEROKEE 2019: [1.7321233388827006, 1.289689569171081, 0.15046331002097185]
JEEP GRAND CHEROKEE V6 2018: [1.8776598027756923, 1.4057367824262523, 0.11725947414922003]
KIA EV6 2022: [3.2, 3.0, 0.05]

@ -37,6 +37,7 @@ HYUNDAI ELANTRA 2017: HYUNDAI SONATA 2019
HYUNDAI ELANTRA HYBRID 2021: HYUNDAI SONATA 2020
HYUNDAI TUCSON 2019: HYUNDAI SANTA FE 2019
HYUNDAI SANTA FE 2022: HYUNDAI SANTA FE HYBRID 2022
KIA STINGER 2022: KIA STINGER GT2 2018
GENESIS G90 2017: GENESIS G70 2018
GENESIS G80 2017: GENESIS G70 2018
GENESIS G70 2020: HYUNDAI SONATA 2020

@ -777,6 +777,7 @@ class Controls:
controlsState.startMonoTime = int(start_time * 1e9)
controlsState.forceDecel = bool(force_decel)
controlsState.canErrorCounter = self.can_rcv_timeout_counter
controlsState.experimentalMode = self.params.get_bool("ExperimentalMode") and self.CP.openpilotLongitudinalControl
lat_tuning = self.CP.lateralTuning.which()
if self.joystick_mode:

@ -187,6 +187,7 @@ class Laikad:
"gpsTimeOfWeek": tow,
"positionECEF": measurement_msg(value=ecef_pos.tolist(), std=pos_std.tolist(), valid=kf_valid),
"velocityECEF": measurement_msg(value=ecef_vel.tolist(), std=vel_std.tolist(), valid=kf_valid),
# TODO std is incorrectly the dimension of the measurements and not 3D
"positionFixECEF": measurement_msg(value=self.last_pos_fix, std=self.last_pos_residual, valid=self.last_pos_fix_t == t),
"ubloxMonoTime": gnss_mono_time,
"correctedMeasurements": meas_msgs

@ -26,4 +26,16 @@ extern "C" {
memcpy(std_buff, stdev.data(), sizeof(double) * stdev.size());
}
bool is_gps_ok(Localizer *localizer){
return localizer->is_gps_ok();
}
bool are_inputs_ok(Localizer *localizer){
return localizer->are_inputs_ok();
}
void observation_timings_invalid_reset(Localizer *localizer){
localizer->observation_timings_invalid_reset();
}
}

@ -19,6 +19,9 @@ const double VALID_TIME_SINCE_RESET = 1.0; // s
const double VALID_POS_STD = 50.0; // m
const double MAX_RESET_TRACKER = 5.0;
const double SANE_GPS_UNCERTAINTY = 1500.0; // m
const double INPUT_INVALID_THRESHOLD = 5.0; // same as reset tracker
const double DECAY = 0.99995; // same as reset tracker
const double MAX_FILTER_REWIND_TIME = 0.8; // s
// TODO: GPS sensor time offsets are empirically calculated
// They should be replaced with synced time from a real clock
@ -200,6 +203,14 @@ VectorXd Localizer::get_stdev() {
return this->kf->get_P().diagonal().array().sqrt();
}
bool Localizer::are_inputs_ok() {
return this->critical_services_valid(this->observation_values_invalid) && !this->observation_timings_invalid;
}
void Localizer::observation_timings_invalid_reset(){
this->observation_timings_invalid = false;
}
void Localizer::handle_sensor(double current_time, const cereal::SensorEventData::Reader& log) {
// TODO does not yet account for double sensor readings in the log
@ -209,10 +220,15 @@ void Localizer::handle_sensor(double current_time, const cereal::SensorEventData
}
double sensor_time = 1e-9 * log.getTimestamp();
// sensor time and log time should be close
if (std::abs(current_time - sensor_time) > 0.1) {
LOGE("Sensor reading ignored, sensor timestamp more than 100ms off from log time");
this->observation_timings_invalid = true;
return;
}
else if (!this->is_timestamp_valid(sensor_time)) {
this->observation_timings_invalid = true;
return;
}
@ -227,6 +243,10 @@ void Localizer::handle_sensor(double current_time, const cereal::SensorEventData
auto meas = Vector3d(-v[2], -v[1], -v[0]);
if (meas.norm() < ROTATION_SANITY_CHECK) {
this->kf->predict_and_observe(sensor_time, OBSERVATION_PHONE_GYRO, { meas });
this->observation_values_invalid["gyroscope"] *= DECAY;
}
else{
this->observation_values_invalid["gyroscope"] += 1.0;
}
}
@ -242,6 +262,10 @@ void Localizer::handle_sensor(double current_time, const cereal::SensorEventData
auto meas = Vector3d(-v[2], -v[1], -v[0]);
if (meas.norm() < ACCEL_SANITY_CHECK) {
this->kf->predict_and_observe(sensor_time, OBSERVATION_PHONE_ACCEL, { meas });
this->observation_values_invalid["accelerometer"] *= DECAY;
}
else{
this->observation_values_invalid["accelerometer"] += 1.0;
}
}
}
@ -335,8 +359,14 @@ void Localizer::handle_car_state(double current_time, const cereal::CarState::Re
void Localizer::handle_cam_odo(double current_time, const cereal::CameraOdometry::Reader& log) {
VectorXd rot_device = this->device_from_calib * floatlist2vector(log.getRot());
VectorXd trans_device = this->device_from_calib * floatlist2vector(log.getTrans());
if (!this->is_timestamp_valid(current_time)) {
this->observation_timings_invalid = true;
return;
}
if ((rot_device.norm() > ROTATION_SANITY_CHECK) || (trans_device.norm() > TRANS_SANITY_CHECK)) {
this->observation_values_invalid["cameraOdometry"] += 1.0;
return;
}
@ -344,10 +374,12 @@ void Localizer::handle_cam_odo(double current_time, const cereal::CameraOdometry
VectorXd trans_calib_std = floatlist2vector(log.getTransStd());
if ((rot_calib_std.minCoeff() <= MIN_STD_SANITY_CHECK) || (trans_calib_std.minCoeff() <= MIN_STD_SANITY_CHECK)) {
this->observation_values_invalid["cameraOdometry"] += 1.0;
return;
}
if ((rot_calib_std.norm() > 10 * ROTATION_SANITY_CHECK) || (trans_calib_std.norm() > 10 * TRANS_SANITY_CHECK)) {
this->observation_values_invalid["cameraOdometry"] += 1.0;
return;
}
@ -363,12 +395,19 @@ void Localizer::handle_cam_odo(double current_time, const cereal::CameraOdometry
{ rot_device }, { rot_device_cov });
this->kf->predict_and_observe(current_time, OBSERVATION_CAMERA_ODO_TRANSLATION,
{ trans_device }, { trans_device_cov });
this->observation_values_invalid["cameraOdometry"] *= DECAY;
}
void Localizer::handle_live_calib(double current_time, const cereal::LiveCalibrationData::Reader& log) {
if (!this->is_timestamp_valid(current_time)) {
this->observation_timings_invalid = true;
return;
}
if (log.getRpyCalib().size() > 0) {
auto live_calib = floatlist2vector(log.getRpyCalib());
if ((live_calib.minCoeff() < -CALIB_RPY_SANITY_CHECK) || (live_calib.maxCoeff() > CALIB_RPY_SANITY_CHECK)) {
this->observation_values_invalid["liveCalibration"] += 1.0;
return;
}
@ -376,6 +415,7 @@ void Localizer::handle_live_calib(double current_time, const cereal::LiveCalibra
this->device_from_calib = euler2rot(this->calib);
this->calib_from_device = this->device_from_calib.transpose();
this->calibrated = log.getCalStatus() == 1;
this->observation_values_invalid["liveCalibration"] *= DECAY;
}
}
@ -407,8 +447,8 @@ void Localizer::time_check(double current_time) {
void Localizer::update_reset_tracker() {
// reset tracker is tuned to trigger when over 1reset/10s over 2min period
if (this->isGpsOK()) {
this->reset_tracker *= .99995;
if (this->is_gps_ok()) {
this->reset_tracker *= DECAY;
} else {
this->reset_tracker = 0.0;
}
@ -483,10 +523,28 @@ kj::ArrayPtr<capnp::byte> Localizer::get_message_bytes(MessageBuilder& msg_build
return msg_builder.toBytes();
}
bool Localizer::isGpsOK() {
bool Localizer::is_gps_ok() {
return this->gps_valid;
}
bool Localizer::critical_services_valid(std::map<std::string, double> critical_services) {
for (auto &kv : critical_services){
if (kv.second >= INPUT_INVALID_THRESHOLD){
return false;
}
}
return true;
}
bool Localizer::is_timestamp_valid(double current_time) {
double filter_time = this->kf->get_filter_time();
if (!std::isnan(filter_time) && ((filter_time - current_time) > MAX_FILTER_REWIND_TIME)) {
LOGE("Observation timestamp is older than the max rewind threshold of the filter");
return false;
}
return true;
}
void Localizer::determine_gps_mode(double current_time) {
// 1. If the pos_std is greater than what's not acceptable and localizer is in gps-mode, reset to no-gps-mode
// 2. If the pos_std is greater than what's not acceptable and localizer is in no-gps-mode, fake obs
@ -521,10 +579,15 @@ int Localizer::locationd_thread() {
uint64_t cnt = 0;
bool filterInitialized = false;
const std::vector<std::string> critical_input_services = {"cameraOdometry", "liveCalibration", "accelerometer", "gyroscope"};
for (std::string service : critical_input_services) {
this->observation_values_invalid.insert({service, 0.0});
}
while (!do_exit) {
sm.update();
if (filterInitialized){
this->observation_timings_invalid_reset();
for (const char* service : service_list) {
if (sm.updated(service) && sm.valid(service)){
const cereal::Event::Reader log = sm[service];
@ -538,8 +601,8 @@ int Localizer::locationd_thread() {
// 100Hz publish for notcars, 20Hz for cars
const char* trigger_msg = sm["carParams"].getCarParams().getNotCar() ? "accelerometer" : "cameraOdometry";
if (sm.updated(trigger_msg)) {
bool inputsOK = sm.allAliveAndValid();
bool gpsOK = this->isGpsOK();
bool inputsOK = sm.allAliveAndValid() && this->are_inputs_ok();
bool gpsOK = this->is_gps_ok();
bool sensorsOK = sm.allAliveAndValid({"accelerometer", "gyroscope"});
MessageBuilder msg_builder;

@ -3,6 +3,7 @@
#include <eigen3/Eigen/Dense>
#include <fstream>
#include <memory>
#include <map>
#include <string>
#include "cereal/messaging/messaging.h"
@ -32,8 +33,12 @@ public:
void finite_check(double current_time = NAN);
void time_check(double current_time = NAN);
void update_reset_tracker();
bool isGpsOK();
bool is_gps_ok();
bool critical_services_valid(std::map<std::string, double> critical_services);
bool is_timestamp_valid(double current_time);
void determine_gps_mode(double current_time);
bool are_inputs_ok();
void observation_timings_invalid_reset();
kj::ArrayPtr<capnp::byte> get_message_bytes(MessageBuilder& msg_builder,
bool inputsOK, bool sensorsOK, bool gpsOK, bool msgValid);
@ -73,4 +78,6 @@ private:
bool gps_mode = false;
bool gps_valid = false;
bool ublox_available = true;
bool observation_timings_invalid = false;
std::map<std::string, double> observation_values_invalid;
};

@ -16,9 +16,9 @@ from selfdrive.controls.lib.vehicle_model import ACCELERATION_DUE_TO_GRAVITY
HISTORY = 5 # secs
POINTS_PER_BUCKET = 1500
MIN_POINTS_TOTAL = 4000
MIN_POINTS_TOTAL_QLOG = 800
MIN_POINTS_TOTAL_QLOG = 600
FIT_POINTS_TOTAL = 2000
FIT_POINTS_TOTAL_QLOG = 800
FIT_POINTS_TOTAL_QLOG = 600
MIN_VEL = 15 # m/s
FRICTION_FACTOR = 1.5 # ~85% of data coverage
FACTOR_SANITY = 0.3

@ -10,6 +10,7 @@
#include <string>
#include <thread>
#include <unordered_map>
#include <utility>
#include "cereal/messaging/messaging.h"
#include "cereal/services.h"

@ -4,6 +4,7 @@
#include <condition_variable>
#include <sstream>
#include <thread>
#include <utility>
#include "catch2/catch.hpp"
#include "cereal/messaging/messaging.h"

@ -1 +1 @@
aa2d370836588fd80b648dbed8d156765ec804d5
959e63af52d9efdb62156cab4b773f88b154fd75

@ -58,7 +58,7 @@ qt_env.Program("qt/spinner", ["qt/spinner.cc"], LIBS=qt_libs)
qt_src = ["main.cc", "qt/sidebar.cc", "qt/onroad.cc", "qt/body.cc",
"qt/window.cc", "qt/home.cc", "qt/offroad/settings.cc",
"qt/offroad/software_settings.cc", "qt/offroad/onboarding.cc",
"qt/offroad/driverview.cc"]
"qt/offroad/driverview.cc", "qt/offroad/experimental_mode.cc"]
qt_env.Program("_ui", qt_src + [asset_obj], LIBS=qt_libs)
if GetOption('test'):
qt_src.remove("main.cc") # replaced by test_runner

@ -4,6 +4,7 @@
#include <QMouseEvent>
#include <QVBoxLayout>
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
#include "selfdrive/ui/qt/util.h"
#include "selfdrive/ui/qt/widgets/drive_stats.h"
#include "selfdrive/ui/qt/widgets/prime.h"
@ -22,7 +23,8 @@ HomeWindow::HomeWindow(QWidget* parent) : QWidget(parent) {
slayout = new QStackedLayout();
main_layout->addLayout(slayout);
home = new OffroadHome();
home = new OffroadHome(this);
QObject::connect(home, &OffroadHome::openSettings, this, &HomeWindow::openSettings);
slayout->addWidget(home);
onroad = new OnroadWindow(this);
@ -128,11 +130,24 @@ OffroadHome::OffroadHome(QWidget* parent) : QFrame(parent) {
main_layout->addSpacing(25);
center_layout = new QStackedLayout();
// Vertical experimental button and drive stats layout
QWidget* statsAndExperimentalModeButtonWidget = new QWidget(this);
QVBoxLayout* statsAndExperimentalModeButton = new QVBoxLayout(statsAndExperimentalModeButtonWidget);
statsAndExperimentalModeButton->setSpacing(30);
statsAndExperimentalModeButton->setMargin(0);
ExperimentalModeButton *experimental_mode = new ExperimentalModeButton(this);
QObject::connect(experimental_mode, &ExperimentalModeButton::openSettings, this, &OffroadHome::openSettings);
statsAndExperimentalModeButton->addWidget(experimental_mode, 1);
statsAndExperimentalModeButton->addWidget(new DriveStats, 1);
// Horizontal experimental + drive stats and setup widget
QWidget* statsAndSetupWidget = new QWidget(this);
QHBoxLayout* statsAndSetup = new QHBoxLayout(statsAndSetupWidget);
statsAndSetup->setMargin(0);
statsAndSetup->setSpacing(30);
statsAndSetup->addWidget(new DriveStats, 1);
statsAndSetup->addWidget(statsAndExperimentalModeButtonWidget, 1);
statsAndSetup->addWidget(new SetupWidget);
center_layout->addWidget(statsAndSetupWidget);

@ -22,6 +22,9 @@ class OffroadHome : public QFrame {
public:
explicit OffroadHome(QWidget* parent = 0);
signals:
void openSettings(int index = 0, const QString &param = "");
private:
void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override;
@ -45,7 +48,7 @@ public:
explicit HomeWindow(QWidget* parent = 0);
signals:
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void closeSettings();
public slots:

@ -35,6 +35,7 @@ void DriverViewScene::showEvent(QShowEvent* event) {
}
void DriverViewScene::hideEvent(QHideEvent* event) {
// TODO: stop vipc thread ?
params.putBool("IsDriverViewEnabled", false);
}

@ -0,0 +1,75 @@
#include "selfdrive/ui/qt/offroad/experimental_mode.h"
#include <QDebug>
#include <QHBoxLayout>
#include <QPainter>
#include <QStyle>
#include "selfdrive/ui/ui.h"
ExperimentalModeButton::ExperimentalModeButton(QWidget *parent) : QPushButton(parent) {
chill_pixmap = QPixmap("../assets/img_couch.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
experimental_pixmap = QPixmap("../assets/img_experimental_grey.svg").scaledToWidth(img_width, Qt::SmoothTransformation);
// go to toggles and expand experimental mode description
connect(this, &QPushButton::clicked, [=]() { emit openSettings(2, "ExperimentalMode"); });
setFixedHeight(125);
QHBoxLayout *main_layout = new QHBoxLayout;
main_layout->setContentsMargins(horizontal_padding, 0, horizontal_padding, 0);
mode_label = new QLabel;
mode_icon = new QLabel;
mode_icon->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
main_layout->addWidget(mode_label, 1, Qt::AlignLeft);
main_layout->addWidget(mode_icon, 0, Qt::AlignRight);
setLayout(main_layout);
setStyleSheet(R"(
QPushButton {
border: none;
}
QLabel {
font-size: 45px;
font-weight: 300;
text-align: left;
font-family: JetBrainsMono;
color: #000000;
}
)");
}
void ExperimentalModeButton::paintEvent(QPaintEvent *event) {
QPainter p(this);
p.setPen(Qt::NoPen);
p.setRenderHint(QPainter::Antialiasing);
QPainterPath path;
path.addRoundedRect(rect(), 10, 10);
// gradient
bool pressed = isDown();
QLinearGradient gradient(rect().left(), 0, rect().right(), 0);
if (experimental_mode) {
gradient.setColorAt(0, QColor(255, 155, 63, pressed ? 0xcc : 0xff));
gradient.setColorAt(1, QColor(219, 56, 34, pressed ? 0xcc : 0xff));
} else {
gradient.setColorAt(0, QColor(20, 255, 171, pressed ? 0xcc : 0xff));
gradient.setColorAt(1, QColor(35, 149, 255, pressed ? 0xcc : 0xff));
}
p.fillPath(path, gradient);
// vertical line
p.setPen(QPen(QColor(0, 0, 0, 0x4d), 3, Qt::SolidLine));
int line_x = rect().right() - img_width - (2 * horizontal_padding);
p.drawLine(line_x, rect().bottom(), line_x, rect().top());
}
void ExperimentalModeButton::showEvent(QShowEvent *event) {
experimental_mode = params.getBool("ExperimentalMode");
mode_icon->setPixmap(experimental_mode ? experimental_pixmap : chill_pixmap);
mode_label->setText(experimental_mode ? tr("EXPERIMENTAL MODE ON") : tr("CHILL MODE ON"));
}

@ -0,0 +1,31 @@
#pragma once
#include <QLabel>
#include <QPushButton>
#include "common/params.h"
class ExperimentalModeButton : public QPushButton {
Q_OBJECT
public:
explicit ExperimentalModeButton(QWidget* parent = 0);
signals:
void openSettings(int index = 0, const QString &toggle = "");
private:
void showEvent(QShowEvent *event) override;
Params params;
bool experimental_mode;
int img_width = 100;
int horizontal_padding = 30;
QPixmap experimental_pixmap;
QPixmap chill_pixmap;
QLabel *mode_label;
QLabel *mode_icon;
protected:
void paintEvent(QPaintEvent *event) override;
};

@ -28,57 +28,50 @@
TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
// param, title, desc, icon, confirm
std::vector<std::tuple<QString, QString, QString, QString, bool>> toggle_defs{
std::vector<std::tuple<QString, QString, QString, QString>> toggle_defs{
{
"OpenpilotEnabledToggle",
tr("Enable openpilot"),
tr("Use the openpilot system for adaptive cruise control and lane keep driver assistance. Your attention is required at all times to use this feature. Changing this setting takes effect when the car is powered off."),
"../assets/offroad/icon_openpilot.png",
false,
},
{
"ExperimentalMode",
tr("Experimental Mode"),
"",
"../assets/offroad/icon_road.png",
false,
"../assets/img_experimental_white.svg",
},
{
"ExperimentalLongitudinalEnabled",
tr("Experimental openpilot Longitudinal Control"),
QString("<b>%1</b><br>%2")
.arg(tr("WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB)."))
.arg(tr("openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control on this car. Enable this to switch to openpilot longitudinal control.")),
.arg(tr("On this car, openpilot defaults to the car's built-in ACC instead of openpilot's longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.")),
"../assets/offroad/icon_speed_limit.png",
true,
},
{
"IsLdwEnabled",
tr("Enable Lane Departure Warnings"),
tr("Receive alerts to steer back into the lane when your vehicle drifts over a detected lane line without a turn signal activated while driving over 31 mph (50 km/h)."),
"../assets/offroad/icon_warning.png",
false,
},
{
"IsMetric",
tr("Use Metric System"),
tr("Display speed in km/h instead of mph."),
"../assets/offroad/icon_metric.png",
false,
},
{
"RecordFront",
tr("Record and Upload Driver Camera"),
tr("Upload data from the driver facing camera and help improve the driver monitoring algorithm."),
"../assets/offroad/icon_monitoring.png",
false,
},
{
"DisengageOnAccelerator",
tr("Disengage on Accelerator Pedal"),
tr("When enabled, pressing the accelerator pedal will disengage openpilot."),
"../assets/offroad/icon_disengage_on_accelerator.svg",
false,
},
#ifdef ENABLE_MAPS
{
@ -86,20 +79,18 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
tr("Show ETA in 24h Format"),
tr("Use 24h format instead of am/pm"),
"../assets/offroad/icon_metric.png",
false,
},
{
"NavSettingLeftSide",
tr("Show Map on Left Side of UI"),
tr("Show map on left side when in split screen view."),
"../assets/offroad/icon_road.png",
false,
},
#endif
};
for (auto &[param, title, desc, icon, confirm] : toggle_defs) {
auto toggle = new ParamControl(param, title, desc, icon, confirm, this);
for (auto &[param, title, desc, icon] : toggle_defs) {
auto toggle = new ParamControl(param, title, desc, icon, this);
bool locked = params.getBool((param + "Lock").toStdString());
toggle->setEnabled(!locked);
@ -108,11 +99,20 @@ TogglesPanel::TogglesPanel(SettingsWindow *parent) : ListWidget(parent) {
toggles[param.toStdString()] = toggle;
}
// Toggles with confirmation dialogs
toggles["ExperimentalMode"]->setActiveIcon("../assets/img_experimental.svg");
toggles["ExperimentalMode"]->setConfirmation(true, true);
toggles["ExperimentalLongitudinalEnabled"]->setConfirmation(true, false);
connect(toggles["ExperimentalLongitudinalEnabled"], &ToggleControl::toggleFlipped, [=]() {
updateToggles();
});
}
void TogglesPanel::expandToggleDescription(const QString &param) {
toggles[param.toStdString()]->showDescription();
}
void TogglesPanel::showEvent(QShowEvent *event) {
updateToggles();
}
@ -120,13 +120,17 @@ void TogglesPanel::showEvent(QShowEvent *event) {
void TogglesPanel::updateToggles() {
auto e2e_toggle = toggles["ExperimentalMode"];
auto op_long_toggle = toggles["ExperimentalLongitudinalEnabled"];
const QString e2e_description = tr("\
openpilot defaults to driving in <b>chill mode</b>.\
Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. \
Experimental features are listed below:\
<br> \
<h4>🌮 End-to-End Longitudinal Control 🌮</h4> \
Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.");
const QString e2e_description = QString("%1<br>"
"<h4>%2</h4><br>"
"%3<br>"
"<h4>%4</h4><br>"
"%5")
.arg(tr("openpilot defaults to driving in <b>chill mode</b>. Experimental mode enables <b>alpha-level features</b> that aren't ready for chill mode. Experimental features are listed below:"))
.arg(tr("🌮 End-to-End Longitudinal Control 🌮"))
.arg(tr("Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. "
"Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected."))
.arg(tr("New Driving Visualization"))
.arg(tr("The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner."));
auto cp_bytes = params.get("CarParamsPersistent");
if (!cp_bytes.empty()) {
@ -150,8 +154,8 @@ void TogglesPanel::updateToggles() {
e2e_toggle->setEnabled(false);
params.remove("ExperimentalMode");
const QString no_long = tr("openpilot longitudinal control is not currently available for this car.");
const QString exp_long = tr("Enable experimental longitudinal control to enable this.");
const QString no_long = tr("Experimental mode is currently unavailable on this car, since the car's stock ACC is used for longitudinal control.");
const QString exp_long = tr("Enable experimental longitudinal control to allow experimental mode.");
e2e_toggle->setDescription("<b>" + (CP.getExperimentalLongitudinalAvailable() ? exp_long : no_long) + "</b><br><br>" + e2e_description);
}
@ -299,8 +303,15 @@ void DevicePanel::poweroff() {
}
void SettingsWindow::showEvent(QShowEvent *event) {
panel_widget->setCurrentIndex(0);
nav_btns->buttons()[0]->setChecked(true);
setCurrentPanel(0);
}
void SettingsWindow::setCurrentPanel(int index, const QString &param) {
panel_widget->setCurrentIndex(index);
nav_btns->buttons()[index]->setChecked(true);
if (!param.isEmpty()) {
emit expandToggleDescription(param);
}
}
SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
@ -341,10 +352,13 @@ SettingsWindow::SettingsWindow(QWidget *parent) : QFrame(parent) {
QObject::connect(device, &DevicePanel::reviewTrainingGuide, this, &SettingsWindow::reviewTrainingGuide);
QObject::connect(device, &DevicePanel::showDriverView, this, &SettingsWindow::showDriverView);
TogglesPanel *toggles = new TogglesPanel(this);
QObject::connect(this, &SettingsWindow::expandToggleDescription, toggles, &TogglesPanel::expandToggleDescription);
QList<QPair<QString, QWidget *>> panels = {
{tr("Device"), device},
{tr("Network"), new Networking(this)},
{tr("Toggles"), new TogglesPanel(this)},
{tr("Toggles"), toggles},
{tr("Software"), new SoftwarePanel(this)},
};

@ -17,6 +17,7 @@ class SettingsWindow : public QFrame {
public:
explicit SettingsWindow(QWidget *parent = 0);
void setCurrentPanel(int index, const QString &param = "");
protected:
void showEvent(QShowEvent *event) override;
@ -25,6 +26,7 @@ signals:
void closeSettings();
void reviewTrainingGuide();
void showDriverView();
void expandToggleDescription(const QString &param);
private:
QPushButton *sidebar_alert_widget;
@ -56,6 +58,9 @@ public:
explicit TogglesPanel(SettingsWindow *parent);
void showEvent(QShowEvent *event) override;
public slots:
void expandToggleDescription(const QString &param);
private:
Params params;
std::map<std::string, ParamControl*> toggles;

@ -174,6 +174,7 @@ AnnotatedCameraWidget::AnnotatedCameraWidget(VisionStreamType type, QWidget* par
pm = std::make_unique<PubMaster, const std::initializer_list<const char *>>({"uiDebug"});
engage_img = loadPixmap("../assets/img_chffr_wheel.png", {img_size, img_size});
experimental_img = loadPixmap("../assets/img_experimental.svg", {img_size - 5, img_size - 5});
dm_img = loadPixmap("../assets/img_driver_face.png", {img_size, img_size});
}
@ -378,8 +379,9 @@ void AnnotatedCameraWidget::drawHud(QPainter &p) {
// engage-ability icon
if (engageable) {
SubMaster &sm = *(uiState()->sm);
drawIcon(p, rect().right() - radius / 2 - bdr_s * 2, radius / 2 + int(bdr_s * 1.5),
engage_img, bg_colors[status], 1.0);
sm["controlsState"].getControlsState().getExperimentalMode() ? experimental_img : engage_img, blackColor(166), 1.0);
}
// dm icon
@ -409,7 +411,7 @@ void AnnotatedCameraWidget::drawIcon(QPainter &p, int x, int y, QPixmap &img, QB
p.setBrush(bg);
p.drawEllipse(x - radius / 2, y - radius / 2, radius, radius);
p.setOpacity(opacity);
p.drawPixmap(x - img_size / 2, y - img_size / 2, img);
p.drawPixmap(x - img.size().width() / 2, y - img.size().height() / 2, img);
}
@ -446,6 +448,8 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
painter.save();
const UIScene &scene = s->scene;
SubMaster &sm = *(s->sm);
// lanelines
for (int i = 0; i < std::size(scene.lane_line_vertices); ++i) {
painter.setBrush(QColor::fromRgbF(1.0, 1.0, 1.0, std::clamp<float>(scene.lane_line_probs[i], 0.0, 0.7)));
@ -461,8 +465,8 @@ void AnnotatedCameraWidget::drawLaneLines(QPainter &painter, const UIState *s) {
// paint path
QLinearGradient bg(0, height(), 0, height() / 4);
float start_hue, end_hue;
if (scene.experimental_mode) {
const auto &acceleration = (*s->sm)["modelV2"].getModelV2().getAcceleration();
if (sm["controlsState"].getControlsState().getExperimentalMode()) {
const auto &acceleration = sm["modelV2"].getModelV2().getAcceleration();
float acceleration_future = 0;
if (acceleration.getZ().size() > 16) {
acceleration_future = acceleration.getX()[16]; // 2.5 seconds
@ -555,7 +559,7 @@ void AnnotatedCameraWidget::paintGL() {
} else if (v_ego > 15) {
wide_cam_requested = false;
}
wide_cam_requested = wide_cam_requested && s->scene.experimental_mode;
wide_cam_requested = wide_cam_requested && sm["controlsState"].getControlsState().getExperimentalMode();
// 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;

@ -51,6 +51,7 @@ private:
void drawText(QPainter &p, int x, int y, const QString &text, int alpha = 255);
QPixmap engage_img;
QPixmap experimental_img;
QPixmap dm_img;
const int radius = 192;
const int img_size = (radius / 2) * 1.5;

@ -20,7 +20,7 @@ public:
explicit Sidebar(QWidget* parent = 0);
signals:
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void valueChanged();
public slots:

@ -102,6 +102,7 @@ CameraWidget::CameraWidget(std::string stream_name, VisionStreamType type, bool
CameraWidget::~CameraWidget() {
makeCurrent();
stopVipcThread();
if (isValid()) {
glDeleteVertexArrays(1, &frame_vao);
glDeleteBuffers(1, &frame_vbo);
@ -171,6 +172,15 @@ void CameraWidget::showEvent(QShowEvent *event) {
}
}
void CameraWidget::stopVipcThread() {
if (vipc_thread) {
vipc_thread->requestInterruption();
vipc_thread->quit();
vipc_thread->wait();
vipc_thread = nullptr;
}
}
void CameraWidget::updateFrameMat() {
int w = width(), h = height();

@ -51,6 +51,7 @@ protected:
void updateCalibration(const mat3 &calib);
void vipcThread();
void clearFrames();
void stopVipcThread();
bool zoomed_view;
GLuint frame_vao, frame_vbo, frame_ibo;

@ -26,10 +26,10 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
hlayout->setSpacing(20);
// left icon
icon_label = new QLabel();
if (!icon.isEmpty()) {
QPixmap pix(icon);
QLabel *icon_label = new QLabel();
icon_label->setPixmap(pix.scaledToWidth(80, Qt::SmoothTransformation));
icon_pixmap = QPixmap(icon).scaledToWidth(80, Qt::SmoothTransformation);
icon_label->setPixmap(icon_pixmap);
icon_label->setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed));
hlayout->addWidget(icon_label);
}
@ -38,7 +38,7 @@ AbstractControl::AbstractControl(const QString &title, const QString &desc, cons
title_label = new QPushButton(title);
title_label->setFixedHeight(120);
title_label->setStyleSheet("font-size: 50px; font-weight: 400; text-align: left");
hlayout->addWidget(title_label);
hlayout->addWidget(title_label, 1);
// value next to control button
value = new ElidedLabel();

@ -54,6 +54,9 @@ public:
return description->text();
}
QLabel *icon_label;
QPixmap icon_pixmap;
public slots:
void showDescription() {
description->setVisible(true);
@ -139,23 +142,38 @@ class ParamControl : public ToggleControl {
Q_OBJECT
public:
ParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon, const bool confirm, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, false, parent) {
ParamControl(const QString &param, const QString &title, const QString &desc, const QString &icon, QWidget *parent = nullptr) : ToggleControl(title, desc, icon, false, parent) {
key = param.toStdString();
QObject::connect(this, &ParamControl::toggleFlipped, [=](bool state) {
QString content("<body><h2 style=\"text-align: center;\">" + title + "</h2><br>"
"<p style=\"text-align: center; margin: 0 128px; font-size: 50px;\">" + getDescription() + "</p></body>");
ConfirmationDialog dialog(content, tr("Enable"), tr("Cancel"), true, this);
if (!confirm || !state || dialog.exec()) {
bool confirmed = store_confirm && params.getBool(key + "Confirmed");
if (!confirm || confirmed || !state || dialog.exec()) {
if (store_confirm && state) params.putBool(key + "Confirmed", true);
params.putBool(key, state);
setIcon(state);
} else {
toggle.togglePosition();
}
});
}
void setConfirmation(bool _confirm, bool _store_confirm) {
confirm = _confirm;
store_confirm = _store_confirm;
};
void setActiveIcon(const QString &icon) {
active_icon_pixmap = QPixmap(icon).scaledToWidth(80, Qt::SmoothTransformation);
}
void refresh() {
if (params.getBool(key) != toggle.on) {
bool state = params.getBool(key);
if (state != toggle.on) {
toggle.togglePosition();
setIcon(state);
}
};
@ -164,8 +182,19 @@ public:
};
private:
void setIcon(bool state) {
if (state && !active_icon_pixmap.isNull()) {
icon_label->setPixmap(active_icon_pixmap);
} else if (!icon_pixmap.isNull()) {
icon_label->setPixmap(icon_pixmap);
}
};
std::string key;
Params params;
QPixmap active_icon_pixmap;
bool confirm = false;
bool store_confirm = false;
};
class ListWidget : public QWidget {

@ -53,6 +53,7 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
QFontDatabase::addApplicationFont("../assets/fonts/Inter-Regular.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/Inter-SemiBold.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/Inter-Thin.ttf");
QFontDatabase::addApplicationFont("../assets/fonts/JetBrainsMono-Medium.ttf");
// no outline to prevent the focus rectangle
setStyleSheet(R"(
@ -64,8 +65,9 @@ MainWindow::MainWindow(QWidget *parent) : QWidget(parent) {
setAttribute(Qt::WA_NoSystemBackground);
}
void MainWindow::openSettings() {
void MainWindow::openSettings(int index, const QString &param) {
main_layout->setCurrentWidget(settingsWindow);
settingsWindow->setCurrentPanel(index, param);
}
void MainWindow::closeSettings() {

@ -15,7 +15,7 @@ public:
private:
bool eventFilter(QObject *obj, QEvent *event) override;
void openSettings();
void openSettings(int index = 0, const QString &param = "");
void closeSettings();
Device device;

@ -60,11 +60,11 @@
</message>
<message>
<source>Cellular Metered</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Prevent large data uploads when on a metered connection</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -240,11 +240,11 @@
</message>
<message>
<source>Reset</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Review</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>
@ -864,7 +875,7 @@ location set</source>
</message>
<message>
<source>Uninstall</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -970,14 +981,6 @@ location set</source>
<source>Experimental openpilot Longitudinal Control</source>
<translation>openpilotによるアクセル制御</translation>
</message>
<message>
<source>openpilot longitudinal control is not currently available for this car.</source>
<translation>openpilotによるアクセル制御は</translation>
</message>
<message>
<source>Enable experimental longitudinal control to enable this.</source>
<translation>使openpilotによるアクセル制御</translation>
</message>
<message>
<source>Disengage on Accelerator Pedal</source>
<translation> openpilot </translation>
@ -1004,18 +1007,42 @@ location set</source>
</message>
<message>
<source>Experimental Mode</source>
<translation></translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>警告: この車種でのopenpilotによるアクセル制御は実験段階であり(AEB)</translation>
</message>
<message>
<source>On this car, openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source> openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below: &lt;br&gt; &lt;h4&gt;🌮 End-to-End Longitudinal Control 🌮&lt;/h4&gt; Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.</source>
<source>Experimental mode is currently unavailable on this car, since the car&apos;s stock ACC is used for longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control on this car. Enable this to switch to openpilot longitudinal control.</source>
<source>Enable experimental longitudinal control to allow experimental mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<source>openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below:</source>
<translation>openpilotは標準ではゆっくりとくつろげる運転を提供します</translation>
</message>
<message>
<source>🌮 End-to-End Longitudinal Control 🌮</source>
<translation>🌮 🌮</translation>
</message>
<message>
<source>Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Driving Visualization</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.</source>
<translation type="unfinished"></translation>
</message>
</context>
@ -1074,7 +1101,7 @@ location set</source>
</message>
<message>
<source>Forget</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
</TS>

@ -281,6 +281,17 @@
<translation> </translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>
@ -970,14 +981,6 @@ location set</source>
<source>Experimental openpilot Longitudinal Control</source>
<translation>openpilot ()</translation>
</message>
<message>
<source>openpilot longitudinal control is not currently available for this car.</source>
<translation> openpilot .</translation>
</message>
<message>
<source>Enable experimental longitudinal control to enable this.</source>
<translation>openpilot . ()</translation>
</message>
<message>
<source>Disengage on Accelerator Pedal</source>
<translation> </translation>
@ -1007,16 +1010,40 @@ location set</source>
<translation> </translation>
</message>
<message>
<source> openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below: &lt;br&gt; &lt;h4&gt;🌮 End-to-End Longitudinal Control 🌮&lt;/h4&gt; Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.</source>
<translation> openpilot은 &lt;b&gt; &lt;/b&gt; . &lt;b&gt; &lt;/b&gt; . &lt;br&gt; &lt;h4&gt;🌮 E2E 🌮&lt;/h4&gt; . openpilot . .</translation>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>경고: openpilot (AEB) .</translation>
</message>
<message>
<source>openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control on this car. Enable this to switch to openpilot longitudinal control.</source>
<translation>openpilot은 ACC로 . .</translation>
<source>On this car, openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>경고: openpilot (AEB) .</translation>
<source>Experimental mode is currently unavailable on this car, since the car&apos;s stock ACC is used for longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable experimental longitudinal control to allow experimental mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below:</source>
<translation>openpilot은 &lt;b&gt; &lt;/b&gt; . &lt;b&gt; &lt;/b&gt; . </translation>
</message>
<message>
<source>🌮 End-to-End Longitudinal Control 🌮</source>
<translation>🌮 E2E 🌮</translation>
</message>
<message>
<source>Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Driving Visualization</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

@ -281,6 +281,17 @@
<translation>câmera iniciando</translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>
@ -974,14 +985,6 @@ trabalho definido</translation>
<source>Experimental openpilot Longitudinal Control</source>
<translation>Controle longitudinal experimental openpilot</translation>
</message>
<message>
<source>openpilot longitudinal control is not currently available for this car.</source>
<translation>controle longitudinal openpilot não está disponível para este carro.</translation>
</message>
<message>
<source>Enable experimental longitudinal control to enable this.</source>
<translation>Habilite o controle longitudinal experimental para habilitar isso.</translation>
</message>
<message>
<source>Disengage on Accelerator Pedal</source>
<translation>Desacionar Com Pedal Do Acelerador</translation>
@ -1011,16 +1014,40 @@ trabalho definido</translation>
<translation>Modo Experimental</translation>
</message>
<message>
<source> openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below: &lt;br&gt; &lt;h4&gt;🌮 End-to-End Longitudinal Control 🌮&lt;/h4&gt; Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.</source>
<translation> openpilot por padrão funciona em &lt;b&gt;modo chill&lt;/b&gt;. modo Experimental ativa &lt;b&gt;recursos de nível-alfa&lt;/b&gt; que não estão prontos para o modo chill. Recursos experimentais estão listados abaixo: &lt;br&gt; &lt;h4&gt;🌮 Controle Longitudinal de Ponta a Ponta 🌮&lt;/h4&gt; Deixe o modelo de condução controlar o acelerador e os freios. Uma vez que o modelo de condução decide qual velocidade dirigir, a velocidade definida só funcionará como um limite superior.</translation>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>ATENÇÃO: o controle longitudinal do openpilot é experimental para este carro e desativará a Frenagem Automática de Emergência (AEB).</translation>
</message>
<message>
<source>openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control on this car. Enable this to switch to openpilot longitudinal control.</source>
<translation>O padrão do openpilot é o ACC integrado do carro em vez do controle longitudinal do openpilot neste carro. Habilite isto para alternar para controle longitudinal do openpilot.</translation>
<source>On this car, openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>ATENÇÃO: o controle longitudinal do openpilot é experimental para este carro e desativará a Frenagem Automática de Emergência (AEB).</translation>
<source>Experimental mode is currently unavailable on this car, since the car&apos;s stock ACC is used for longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable experimental longitudinal control to allow experimental mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below:</source>
<translation>openpilot por padrão funciona em &lt;b&gt;modo chill&lt;/b&gt;. modo Experimental ativa &lt;b&gt;recursos de nível-alfa&lt;/b&gt; que não estão prontos para o modo chill. Recursos experimentais estão listados abaixo:</translation>
</message>
<message>
<source>🌮 End-to-End Longitudinal Control 🌮</source>
<translation>🌮 Controle Longitudinal de Ponta a Ponta 🌮</translation>
</message>
<message>
<source>Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Driving Visualization</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

@ -60,11 +60,11 @@
</message>
<message>
<source>Cellular Metered</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Prevent large data uploads when on a metered connection</source>
<translation type="unfinished"></translation>
<translation>使</translation>
</message>
</context>
<context>
@ -140,7 +140,7 @@
</message>
<message>
<source>Preview the driver facing camera to ensure that driver monitoring has good visibility. (vehicle must be off)</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Reset Calibration</source>
@ -204,7 +204,7 @@
</message>
<message>
<source> Your device is pointed %1° %2 and %3° %4.</source>
<translation>%1° %2%3° %4</translation>
<translation> %1° %2%3° %4</translation>
</message>
<message>
<source>down</source>
@ -240,11 +240,11 @@
</message>
<message>
<source>Reset</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Review</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>
@ -814,35 +825,35 @@ location set</source>
<name>SoftwarePanel</name>
<message>
<source>Updates are only downloaded while the car is off.</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Current Version</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Download</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Install Update</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>INSTALL</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Target Branch</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>SELECT</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>Select a branch</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source>UNINSTALL</source>
@ -862,7 +873,7 @@ location set</source>
</message>
<message>
<source>Uninstall</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
<context>
@ -966,15 +977,7 @@ location set</source>
</message>
<message>
<source>Experimental openpilot Longitudinal Control</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>openpilot longitudinal control is not currently available for this car.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable experimental longitudinal control to enable this.</source>
<translation type="unfinished"></translation>
<translation>openpilot纵向控制</translation>
</message>
<message>
<source>Disengage on Accelerator Pedal</source>
@ -1002,19 +1005,43 @@ location set</source>
</message>
<message>
<source>Experimental Mode</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
<message>
<source> openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below: &lt;br&gt; &lt;h4&gt;🌮 End-to-End Longitudinal Control 🌮&lt;/h4&gt; Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.</source>
<translation type="unfinished"></translation>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation> openpilot纵向控制是试验性功能AEB自动刹车功能</translation>
</message>
<message>
<source>openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control on this car. Enable this to switch to openpilot longitudinal control.</source>
<translation type="unfinished"></translation>
<source>On this car, openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.</source>
<translation>openpilot默认使用车辆自带的ACCopenpilot的纵向控制openpilot纵向控制使openpilot纵向控制时</translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation type="unfinished"></translation>
<source>Experimental mode is currently unavailable on this car, since the car&apos;s stock ACC is used for longitudinal control.</source>
<translation>使ACC纵向控制使</translation>
</message>
<message>
<source>Enable experimental longitudinal control to allow experimental mode.</source>
<translation>便使</translation>
</message>
<message>
<source>openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below:</source>
<translation>openpilot &lt;b&gt;&lt;/b&gt; &lt;b&gt;&lt;/b&gt;</translation>
</message>
<message>
<source>🌮 End-to-End Longitudinal Control 🌮</source>
<translation>🌮 End-to-End 🌮</translation>
</message>
<message>
<source>Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected.</source>
<translation>openpilot将模仿人类驾驶车辆</translation>
</message>
<message>
<source>New Driving Visualization</source>
<translation></translation>
</message>
<message>
<source>The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.</source>
<translation>广便</translation>
</message>
</context>
<context>
@ -1064,15 +1091,15 @@ location set</source>
</message>
<message>
<source>FORGET</source>
<translation></translation>
<translation></translation>
</message>
<message>
<source>Forget Wi-Fi Network &quot;%1&quot;?</source>
<translation>WiFi网络 &quot;%1&quot;?</translation>
<translation>WiFi网络 &quot;%1&quot;?</translation>
</message>
<message>
<source>Forget</source>
<translation type="unfinished"></translation>
<translation></translation>
</message>
</context>
</TS>

@ -281,6 +281,17 @@
<translation></translation>
</message>
</context>
<context>
<name>ExperimentalModeButton</name>
<message>
<source>EXPERIMENTAL MODE ON</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>CHILL MODE ON</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>
<name>InputDialog</name>
<message>
@ -970,14 +981,6 @@ location set</source>
<source>Experimental openpilot Longitudinal Control</source>
<translation>使 openpilot </translation>
</message>
<message>
<source>openpilot longitudinal control is not currently available for this car.</source>
<translation>openpilot </translation>
</message>
<message>
<source>Enable experimental longitudinal control to enable this.</source>
<translation></translation>
</message>
<message>
<source>Disengage on Accelerator Pedal</source>
<translation></translation>
@ -1007,16 +1010,40 @@ location set</source>
<translation></translation>
</message>
<message>
<source> openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below: &lt;br&gt; &lt;h4&gt;🌮 End-to-End Longitudinal Control 🌮&lt;/h4&gt; Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides which speed to drive, the set speed will only act as an upper bound.</source>
<translation> openpilot &lt;b&gt;&lt;/b&gt; &lt;b&gt;alpha &lt;/b&gt; &lt;br&gt; &lt;h4&gt;🌮🌮&lt;/h4&gt; openpilot </translation>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>openpilot (AEB) </translation>
</message>
<message>
<source>openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control on this car. Enable this to switch to openpilot longitudinal control.</source>
<translation>openpilot 使 (ACC)使 openpilot openpilot </translation>
<source>On this car, openpilot defaults to the car&apos;s built-in ACC instead of openpilot&apos;s longitudinal control. Enable this to switch to openpilot longitudinal control. Enabling Experimental mode is recommended when using experimental openpilot longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>WARNING: openpilot longitudinal control is experimental for this car and will disable Automatic Emergency Braking (AEB).</source>
<translation>openpilot (AEB) </translation>
<source>Experimental mode is currently unavailable on this car, since the car&apos;s stock ACC is used for longitudinal control.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>Enable experimental longitudinal control to allow experimental mode.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>openpilot defaults to driving in &lt;b&gt;chill mode&lt;/b&gt;. Experimental mode enables &lt;b&gt;alpha-level features&lt;/b&gt; that aren&apos;t ready for chill mode. Experimental features are listed below:</source>
<translation>openpilot &lt;b&gt;&lt;/b&gt; &lt;b&gt;alpha &lt;/b&gt;</translation>
</message>
<message>
<source>🌮 End-to-End Longitudinal Control 🌮</source>
<translation>🌮🌮</translation>
</message>
<message>
<source>Let the driving model control the gas and brakes. openpilot will drive as it thinks a human would, including stopping for red lights and stop signs. Since the driving model decides the speed to drive, the set speed will only act as an upper bound. This is an alpha quality feature; mistakes should be expected.</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>New Driving Visualization</source>
<translation type="unfinished"></translation>
</message>
<message>
<source>The driving visualization will transition to the road-facing wide-angle camera at low speeds to better show some turns. The Experimental mode logo will also be shown in the top right corner.</source>
<translation type="unfinished"></translation>
</message>
</context>
<context>

@ -174,7 +174,6 @@ void ui_update_params(UIState *s) {
auto params = Params();
s->scene.is_metric = params.getBool("IsMetric");
s->scene.map_on_left = params.getBool("NavSettingLeftSide");
s->scene.experimental_mode = params.getBool("ExperimentalMode");
}
void UIState::updateStatus() {

@ -104,7 +104,7 @@ typedef struct UIScene {
QPointF lead_vertices[2];
float light_sensor;
bool started, ignition, is_metric, map_on_left, longitudinal_control, experimental_mode;
bool started, ignition, is_metric, map_on_left, longitudinal_control;
uint64_t started_frame;
} UIScene;

@ -64,31 +64,35 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart
frame_layout->addWidget(warning_widget);
main_layout->addWidget(title_frame);
QWidget *container = new QWidget(this);
QVBoxLayout *container_layout = new QVBoxLayout(container);
container_layout->setSpacing(0);
container_layout->setContentsMargins(0, 0, 0, 0);
scroll = new QScrollArea(this);
scroll->setWidget(container);
scroll->setWidgetResizable(true);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
main_layout->addWidget(scroll);
// msg widget
QWidget *msg_widget = new QWidget(this);
QVBoxLayout *msg_layout = new QVBoxLayout(msg_widget);
msg_layout->setContentsMargins(0, 0, 0, 0);
// binary view
binary_view = new BinaryView(this);
container_layout->addWidget(binary_view);
msg_layout->addWidget(binary_view);
// signals
signals_layout = new QVBoxLayout();
container_layout->addLayout(signals_layout);
signals_layout->setSpacing(0);
msg_layout->addLayout(signals_layout);
msg_layout->addStretch(0);
scroll = new QScrollArea(this);
scroll->setFrameShape(QFrame::NoFrame);
scroll->setWidget(msg_widget);
scroll->setWidgetResizable(true);
scroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
// history log
tab_widget = new QTabWidget(this);
tab_widget->setTabPosition(QTabWidget::South);
tab_widget->addTab(scroll, "Msg");
history_log = new HistoryLog(this);
container_layout->addWidget(history_log);
tab_widget->addTab(history_log, "Logs");
main_layout->addWidget(tab_widget);
QObject::connect(binary_view, &BinaryView::resizeSignal, this, &DetailWidget::resizeSignal);
QObject::connect(binary_view, &BinaryView::addSignal, this, &DetailWidget::addSignal);
QObject::connect(tab_widget, &QTabWidget::currentChanged, [this]() { updateState(); });
QObject::connect(can, &CANMessages::msgsReceived, this, &DetailWidget::updateState);
QObject::connect(dbc(), &DBCManager::DBCFileChanged, [this]() { dbcMsgChanged(); });
QObject::connect(tabbar, &QTabBar::customContextMenuRequested, this, &DetailWidget::showTabBarContextMenu);
@ -151,6 +155,7 @@ void DetailWidget::dbcMsgChanged(int show_form_idx) {
form = new SignalEdit(i);
QObject::connect(form, &SignalEdit::remove, this, &DetailWidget::removeSignal);
QObject::connect(form, &SignalEdit::save, this, &DetailWidget::saveSignal);
QObject::connect(form, &SignalEdit::showFormClicked, this, &DetailWidget::showFormClicked);
QObject::connect(form, &SignalEdit::highlight, binary_view, &BinaryView::highlight);
QObject::connect(binary_view, &BinaryView::signalHovered, form, &SignalEdit::signalHovered);
QObject::connect(form, &SignalEdit::showChart, charts, &ChartsWidget::showChart);
@ -176,16 +181,26 @@ void DetailWidget::dbcMsgChanged(int show_form_idx) {
warning_label->setText(warnings.join('\n'));
warning_widget->setVisible(!warnings.isEmpty());
QTimer::singleShot(1, [this]() { setUpdatesEnabled(true); });
setUpdatesEnabled(true);
}
void DetailWidget::updateState(const QHash<QString, CanData> * msgs) {
time_label->setText(QString::number(can->currentSec(), 'f', 3));
if (!msgs->contains(msg_id))
if (msg_id.isEmpty() || (msgs && !msgs->contains(msg_id)))
return;
binary_view->updateState();
history_log->updateState();
if (tab_widget->currentIndex() == 0)
binary_view->updateState();
else
history_log->updateState();
}
void DetailWidget::showFormClicked() {
auto s = qobject_cast<SignalEdit *>(sender());
setUpdatesEnabled(false);
for (auto f : signal_list)
f->updateForm(f == s && !f->isFormVisible());
setUpdatesEnabled(true);
}
void DetailWidget::updateChartState(const QString &id, const Signal *sig, bool opened) {

@ -1,7 +1,7 @@
#pragma once
#include <QScrollArea>
#include <QTabBar>
#include <QTabWidget>
#include <QToolBar>
#include <QUndoStack>
@ -28,6 +28,7 @@ public:
QUndoStack *undo_stack = nullptr;
private:
void showFormClicked();
void updateChartState(const QString &id, const Signal *sig, bool opened);
void showTabBarContextMenu(const QPoint &pt);
void addSignal(int start_bit, int size, bool little_endian);
@ -36,13 +37,14 @@ private:
void removeSignal(const Signal *sig);
void editMsg();
void removeMsg();
void updateState(const QHash<QString, CanData> * msgs);
void updateState(const QHash<QString, CanData> * msgs = nullptr);
QString msg_id;
QLabel *name_label, *time_label, *warning_label;
QWidget *warning_widget;
QVBoxLayout *signals_layout;
QTabBar *tabbar;
QTabWidget *tab_widget;
QToolBar *toolbar;
QAction *remove_msg_act;
HistoryLog *history_log;

@ -86,10 +86,8 @@ HistoryLog::HistoryLog(QWidget *parent) : QTableView(parent) {
horizontalHeader()->setDefaultAlignment(Qt::AlignLeft | (Qt::Alignment)Qt::TextWordWrap);
horizontalHeader()->setSectionResizeMode(0, QHeaderView::ResizeToContents);
verticalHeader()->setVisible(false);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setSizeAdjustPolicy(QAbstractScrollArea::AdjustToContents);
setFrameShape(QFrame::NoFrame);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
setStyleSheet("QTableView::item { border:0px; padding-left:5px; padding-right:5px; }");
}

@ -72,7 +72,8 @@ MainWindow::MainWindow() : QMainWindow() {
video_widget = new VideoWidget(this);
r_layout->addWidget(video_widget, 0, Qt::AlignTop);
r_layout->addWidget(charts_widget);
r_layout->addWidget(charts_widget, 1);
r_layout->addStretch(0);
main_layout->addWidget(right_container);
setCentralWidget(central_widget);
@ -192,9 +193,10 @@ void MainWindow::saveDBCToFile() {
if (!file_name.isEmpty()) {
settings.last_dir = QFileInfo(file_name).absolutePath();
QFile file(file_name);
if (file.open(QIODevice::WriteOnly))
if (file.open(QIODevice::WriteOnly)) {
file.write(dbc()->generateDBC().toUtf8());
detail_widget->undo_stack->clear();
}
}
}
@ -216,11 +218,12 @@ void MainWindow::updateDownloadProgress(uint64_t cur, uint64_t total, bool succe
void MainWindow::dockCharts(bool dock) {
if (dock && floating_window) {
floating_window->removeEventFilter(charts_widget);
r_layout->addWidget(charts_widget);
r_layout->insertWidget(2, charts_widget, 1);
floating_window->deleteLater();
floating_window = nullptr;
} else if (!dock && !floating_window) {
floating_window = new QWidget(nullptr);
floating_window->setWindowTitle("Charts - Cabana");
floating_window->setLayout(new QVBoxLayout());
floating_window->layout()->addWidget(charts_widget);
floating_window->installEventFilter(charts_widget);

@ -4,7 +4,6 @@
#include <QFormLayout>
#include <QHBoxLayout>
#include <QScrollArea>
#include <QTimer>
#include <QToolBar>
#include <QVBoxLayout>
@ -189,26 +188,12 @@ void SignalEdit::updateForm(bool visible) {
icon->setText(visible ? "" : "> ");
}
void SignalEdit::showFormClicked() {
parentWidget()->setUpdatesEnabled(false);
for (auto &edit : parentWidget()->findChildren<SignalEdit*>())
edit->updateForm(edit == this && !form->isVisible());
QTimer::singleShot(1, [this]() { parentWidget()->setUpdatesEnabled(true); });
}
void SignalEdit::signalHovered(const Signal *s) {
auto bg_color = sig == s ? hoverColor(getColor(form_idx)) : QColor(getColor(form_idx));
auto color = sig == s ? "white" : "black";
color_label->setStyleSheet(QString("color:%1; background-color:%2").arg(color).arg(bg_color.name()));
}
void SignalEdit::hideEvent(QHideEvent *event) {
msg_id = "";
sig = nullptr;
updateForm(false);
QWidget::hideEvent(event);
}
void SignalEdit::enterEvent(QEvent *event) {
emit highlight(sig);
QWidget::enterEvent(event);

@ -34,6 +34,8 @@ public:
void setSignal(const QString &msg_id, const Signal *sig);
void setChartOpened(bool opened);
void signalHovered(const Signal *sig);
void updateForm(bool show);
inline bool isFormVisible() const { return form->isVisible(); }
const Signal *sig = nullptr;
QString msg_id;
@ -42,14 +44,12 @@ signals:
void showChart(const QString &name, const Signal *sig, bool show);
void remove(const Signal *sig);
void save(const Signal *sig, const Signal &new_sig);
void showFormClicked();
protected:
void hideEvent(QHideEvent *event) override;
void enterEvent(QEvent *event) override;
void leaveEvent(QEvent *event) override;
void saveSignal();
void updateForm(bool show);
void showFormClicked();
SignalForm *form = nullptr;
ElidedLabel *title;

Loading…
Cancel
Save