mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-20 01:02:07 +08:00
Compare commits
503 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 70424bd661 | |||
| d215eab1d4 | |||
| 91316c8cb5 | |||
| fa284be7e6 | |||
| 6e7d9e5e52 | |||
| a4a7c2335d | |||
| ae573c7c3f | |||
| 7d7b6ee306 | |||
| 6a4c59c3e0 | |||
| fb5cb7a1cc | |||
| 049dfd2eaa | |||
| be20848487 | |||
| cdd232b606 | |||
| b21c70b1ba | |||
| 67e5bd3c1e | |||
| 74692d0b5f | |||
| dd35c27981 | |||
| 159140e64e | |||
| f1ab6c8dfb | |||
| e1fe30fd3e | |||
| fba521dcff | |||
| a8ef55bfaa | |||
| a232f54e2d | |||
| 2697008aa7 | |||
| ad5abd242a | |||
| 6c1e0f370b | |||
| 1083f5bf21 | |||
| dc5116c718 | |||
| 8611e08dc6 | |||
| dc0f73c63b | |||
| 46b9253729 | |||
| 40875ef72f | |||
| 36a9c02b8f | |||
| 3137a32db4 | |||
| 69e2c321e4 | |||
| c87f613659 | |||
| 249cafe897 | |||
| 0f17a98793 | |||
| 04e2351246 | |||
| bd148abbc4 | |||
| c76f481ddc | |||
| ce08f5290b | |||
| bc2b0d8272 | |||
| 965f47efe3 | |||
| 5bbcc32b5d | |||
| 517b9a2d5f | |||
| 5063c2055f | |||
| 9f3448f662 | |||
| 609a5c3cfa | |||
| d937401511 | |||
| 8499de6afe | |||
| 3452e878a7 | |||
| 804d9016ae | |||
| ad522f8444 | |||
| 9f59a4a5ca | |||
| 417efb3c05 | |||
| 4df40d2c19 | |||
| 069b912056 | |||
| a8772eb0af | |||
| a81617d8ee | |||
| 5408c86b7b | |||
| 4cd93f3eee | |||
| dfc3c98b22 | |||
| 4585e93066 | |||
| 5af72796f2 | |||
| ccac1e28de | |||
| bdca897248 | |||
| b93d166ff8 | |||
| d9553eeec7 | |||
| 9d74412fec | |||
| 95f562c298 | |||
| d489dd8909 | |||
| 1f227bbe20 | |||
| 9844075bb2 | |||
| a3cc9c7ac3 | |||
| aff9f9ffae | |||
| 38faa7c2cb | |||
| 52e182611d | |||
| 82338fd8c5 | |||
| 12aaacdffc | |||
| 6941a913a3 | |||
| 27e37f9d95 | |||
| 43d61f043c | |||
| 77017a913a | |||
| 24ff455bc0 | |||
| 2920503f94 | |||
| 46e3c907f6 | |||
| 2ed88a1dff | |||
| 107a6f4c00 | |||
| 059d0b6c4c | |||
| 65405bafa6 | |||
| d4a83deb7d | |||
| dd58eb68f0 | |||
| 4cfd774855 | |||
| e9cf5d67cf | |||
| 74554a523f | |||
| 2d4ac33ed7 | |||
| c9d77fb3fb | |||
| a432afd173 | |||
| c51ffe3808 | |||
| ef94b134c3 | |||
| f24ad7e27a | |||
| b88adeb4ad | |||
| a15aed1a79 | |||
| aa26dded8b | |||
| a06f31b472 | |||
| b3ed39525d | |||
| 57c44831da | |||
| 8ebc51a8aa | |||
| 4ecbdb0d7a | |||
| 4b945a1b79 | |||
| e8a03f7f32 | |||
| 69d3066d82 | |||
| 9574eee0e3 | |||
| 492ed73127 | |||
| af92603d17 | |||
| ecb661fe85 | |||
| dff6a80faf | |||
| 3a764c0ae3 | |||
| 11c14a138f | |||
| bdee8731b7 | |||
| 4b81dda1b5 | |||
| edc3ce89fa | |||
| 02f66e6e84 | |||
| 15267e4082 | |||
| 628e230b63 | |||
| 98512fc62b | |||
| 38ffb324f8 | |||
| 78007e82e0 | |||
| 534fb19714 | |||
| 294cb687f6 | |||
| 2a86d0cea5 | |||
| bbe5b38643 | |||
| 2691aa8e39 | |||
| da62722d07 | |||
| f6e2dd280d | |||
| 8583826166 | |||
| 93ed08ba20 | |||
| 6b6b7f0f33 | |||
| bea893820e | |||
| e624da2eed | |||
| 656de3f17b | |||
| 63508d0481 | |||
| b1a6223b14 | |||
| e771dfa007 | |||
| d7c562e130 | |||
| f87bc52405 | |||
| 1268227ce5 | |||
| 76f1f189db | |||
| 9fdcbae8de | |||
| f18aa113a5 | |||
| a3d3d0fea6 | |||
| 5745909e9b | |||
| fd37cd1d03 | |||
| ab1a962803 | |||
| 32671d1c3f | |||
| 01e7606b70 | |||
| bd1c7f39ec | |||
| c28eb95874 | |||
| a544cd7d39 | |||
| b7725c5cbb | |||
| 7ed960f713 | |||
| 6420e8d92a | |||
| 695a2d783f | |||
| 2596de8543 | |||
| 7a6dc19104 | |||
| 7e2b8430c5 | |||
| 521fa09b0d | |||
| 5adcff1221 | |||
| b9aa1962ca | |||
| 6b1b6aca05 | |||
| 41a8bc3fc4 | |||
| 540f4f5933 | |||
| 0e58ac33ad | |||
| 53e5ae0578 | |||
| dd0690da6f | |||
| 57d0a58855 | |||
| f64f3944a6 | |||
| 65b2bfe5d8 | |||
| 1caae26cfc | |||
| 94cf600bfe | |||
| 4a1b721636 | |||
| 55f033ced0 | |||
| 2182be05ea | |||
| 3e44c90c68 | |||
| 2d35bd895f | |||
| 855d5022ad | |||
| 6a363365ab | |||
| d238a1ccc4 | |||
| 1eeba86ec1 | |||
| 96d55a3283 | |||
| 5752095bc2 | |||
| 8560f2732a | |||
| b8bcf32457 | |||
| 1a93104bfd | |||
| ab43fd1369 | |||
| 605dfaa1a9 | |||
| b279aa6015 | |||
| 0f542bef38 | |||
| f364110a36 | |||
| 635a3bc7ab | |||
| 56b3b4d245 | |||
| 168b9831b2 | |||
| d20794f900 | |||
| 7b79305d99 | |||
| dd7da3153a | |||
| 39849def72 | |||
| 4db23ed4c6 | |||
| a4e016c142 | |||
| 61f7c7ea03 | |||
| 82a959ef8e | |||
| b3f369612d | |||
| ae0962cd0c | |||
| f00ff77c55 | |||
| dab51a864f | |||
| 360fd1555f | |||
| 813d794f05 | |||
| ddb9039493 | |||
| 0b7df7df10 | |||
| dd3feac854 | |||
| f7644c913e | |||
| 13ea74bcb4 | |||
| dc6e644359 | |||
| 85f00ff80a | |||
| 3af3c7e748 | |||
| 545ad018e0 | |||
| e86d4e86a6 | |||
| 7002d24213 | |||
| 10a33a4bf1 | |||
| d1e069210f | |||
| 8714203d2c | |||
| ee54e82090 | |||
| 79cd8420eb | |||
| 8c533b14c0 | |||
| 494eba5961 | |||
| ad875632ac | |||
| 63068481d7 | |||
| 275206c14d | |||
| c3b0f0d11a | |||
| 1c69770c53 | |||
| 551e2f77bf | |||
| ad04c6a038 | |||
| bb4b96e05d | |||
| 7d71354fd0 | |||
| 49685fc2bc | |||
| 0eacf34e15 | |||
| 0be0d7fa94 | |||
| 736cf6d9df | |||
| df6d34e52b | |||
| 39d1eec575 | |||
| 2266a9dd9c | |||
| f8372ccc4d | |||
| f8c45d307c | |||
| ca04b70d0a | |||
| 571a547671 | |||
| b29d0a17af | |||
| 859bd215bf | |||
| 4988a62b31 | |||
| e202bbe4aa | |||
| 4286a64083 | |||
| 341786acb5 | |||
| 04b23ff849 | |||
| 6996e87f8d | |||
| 18406e77ee | |||
| b6432e705d | |||
| fdd43f49e0 | |||
| 5d7155fdda | |||
| b9986cae06 | |||
| 2c0903e45e | |||
| f93481d0d4 | |||
| 389b639ef2 | |||
| 5f6e05410d | |||
| 5624a4ccd6 | |||
| d81d66193f | |||
| d1d6fae613 | |||
| 35aeeee657 | |||
| a6fdef77df | |||
| df66604a45 | |||
| c001f3c9b4 | |||
| 752fe03118 | |||
| 84c276bb6c | |||
| 9042cfa1ad | |||
| 83e6e7da93 | |||
| 31403f4a5c | |||
| 117d5cee4f | |||
| fa18e6395c | |||
| 75e352e5d0 | |||
| 63ab2fb1b3 | |||
| 97f1bac71d | |||
| 00b7c8e8ad | |||
| 1276452cfc | |||
| 8b2eac4d1f | |||
| e78e6261ca | |||
| 61915eb914 | |||
| d5f1d8c33a | |||
| e16d422cf4 | |||
| 3509fccec7 | |||
| 613d13bbfb | |||
| f70a156c7e | |||
| d204d626bd | |||
| fd590b206e | |||
| 6102aedf05 | |||
| c7efc009a4 | |||
| c23f2dce2c | |||
| 4a15bdcdae | |||
| 30a858c23d | |||
| d95bc0dcfe | |||
| 2406b32d55 | |||
| 6979849305 | |||
| bf2294dee2 | |||
| fcb0a496ed | |||
| c91a0a83f6 | |||
| 63107e6e6b | |||
| 0584a5f5eb | |||
| f24dfd6ee9 | |||
| 9022b4d322 | |||
| b782958abd | |||
| 3fa6726f88 | |||
| 8c240cc1a4 | |||
| 9541692eb0 | |||
| f83b749ec2 | |||
| b930f5c3f1 | |||
| 0a58d8b761 | |||
| 64e785d00f | |||
| 9db432e8fb | |||
| 6ce156ee16 | |||
| a89ed55b65 | |||
| 9dc4986e21 | |||
| f17a0aac94 | |||
| 934fd5a5a8 | |||
| b5576de97e | |||
| 58090f5f7e | |||
| 09a55a7833 | |||
| 8abfbc56a1 | |||
| 8b53f9158d | |||
| 21538e5a09 | |||
| 19d56f685b | |||
| 508863e5a8 | |||
| f28d6fb6bc | |||
| 54a2d31e97 | |||
| b0b9079437 | |||
| c7382f8258 | |||
| 08401a96c2 | |||
| f37fd3ea34 | |||
| e541489b33 | |||
| e5ac18702c | |||
| 3c93d4cba1 | |||
| dc4dae6794 | |||
| f170440f4a | |||
| fa329eb9ff | |||
| 310ba9d2c0 | |||
| f0053d4619 | |||
| 052692b25d | |||
| 79bf1e1450 | |||
| b5d2026fc7 | |||
| d398f9951e | |||
| 55c3885742 | |||
| cb32793300 | |||
| d8569b07eb | |||
| efd5301f65 | |||
| 5dcaf3bef8 | |||
| bf43c7e8c7 | |||
| 1dec68014f | |||
| 8badc7d813 | |||
| 9be7a48ccd | |||
| 6b94c47c6a | |||
| b706673e1c | |||
| e4813645fa | |||
| 12f1be19cc | |||
| e5ebd45576 | |||
| 0870e26fb6 | |||
| d75b8f4540 | |||
| f4b8384332 | |||
| 5766202763 | |||
| 6871203c45 | |||
| 1d48cbdffa | |||
| 54db569c2c | |||
| 31e4fe55ac | |||
| a8b5c74507 | |||
| 470c3f4a92 | |||
| af09b7a45b | |||
| 7fae59167e | |||
| 08d8bb9975 | |||
| 240e0036d2 | |||
| d5e75dd0af | |||
| e53cc41b47 | |||
| d0382e2d48 | |||
| 78b15773c9 | |||
| f95959afdb | |||
| 1c14375796 | |||
| 1658898498 | |||
| 9a8795f063 | |||
| d5b25e14fd | |||
| 23c774eb19 | |||
| a68ea44af3 | |||
| 5e7f5dd840 | |||
| cc4f786846 | |||
| f4657aa2d5 | |||
| 46bbe6890a | |||
| 380d91c8f7 | |||
| 24121f8abf | |||
| 9d19cca006 | |||
| ee9da82aab | |||
| 06630e8a39 | |||
| 2cc70ef2e4 | |||
| 37ac33fbcc | |||
| 0376660023 | |||
| 5908b7cda0 | |||
| d0375942b8 | |||
| bbed1a2551 | |||
| 2b0aab3a38 | |||
| d8ae8c201a | |||
| 9bcd965f0b | |||
| 6e7587a75c | |||
| c631a22eb6 | |||
| 7dfb7967b6 | |||
| 58d6211bc2 | |||
| 4e239dbc22 | |||
| 3469d9aadb | |||
| 18da21e65b | |||
| 50f0cf25a6 | |||
| bea040095c | |||
| 3584523a93 | |||
| d3bcc80d28 | |||
| 0ce679f687 | |||
| d55ccba5fe | |||
| f85b3473a2 | |||
| b750229e70 | |||
| 40b61a8212 | |||
| 5927316788 | |||
| dd89bc30fa | |||
| bf4bf0e5b7 | |||
| 9164148d48 | |||
| ac3dcbe62f | |||
| ba19527181 | |||
| 4acf0438c8 | |||
| bd5fbbabda | |||
| 1777d548bf | |||
| 095d96fbe0 | |||
| 2ca6f893df | |||
| a17a8daad5 | |||
| acace97ef8 | |||
| 0208d26845 | |||
| dd8aa4a21e | |||
| d6c85abcd3 | |||
| 56d1961625 | |||
| 1dbae159a8 | |||
| 76458d175f | |||
| ad181ba501 | |||
| 71290f3805 | |||
| e42ee228c2 | |||
| 9510e05dc0 | |||
| 6e87e66bc5 | |||
| 1197ea9ab9 | |||
| 9d7edbf57a | |||
| acec60d19e | |||
| 6a3dcc74e8 | |||
| 6e851ff886 | |||
| 7a5d8a813b | |||
| 4742bf0230 | |||
| 4bf2bfb122 | |||
| 797b769478 | |||
| 024e2af269 | |||
| e35513afc4 | |||
| 6607283cec | |||
| 08162be765 | |||
| 7061c18cee | |||
| c36c30e74b | |||
| 1f9ec135a4 | |||
| 0557283e3d | |||
| 793f8fee32 | |||
| 5e1a576f3d | |||
| fd98db72ab | |||
| 2f1a58f991 | |||
| 4cc68f57cf | |||
| 5e2a5b5355 | |||
| 44ec08c112 | |||
| 60ec7dc7b6 | |||
| af1fb2644e | |||
| 4651bc6a1f | |||
| ac1dd692af | |||
| 363735f7ce | |||
| 5303afb0dc | |||
| 118d903e2d | |||
| 93eb8418b7 | |||
| 6922d58762 | |||
| b4b747e5cb | |||
| 2d53f4cf01 | |||
| 4a1101c032 | |||
| 41bba2b55a | |||
| d801cebb2e | |||
| 3a19f85512 | |||
| dcc166343f | |||
| 4f5df6589d | |||
| 3cc9d89d45 | |||
| e59f675715 | |||
| 5beae930e4 | |||
| 0274b73760 | |||
| 055b29b226 | |||
| 6330a9c53a | |||
| 2c4e114b51 | |||
| e264b4269f | |||
| fef89d1039 |
+1
-10
@@ -11,13 +11,4 @@
|
|||||||
*.wav filter=lfs diff=lfs merge=lfs -text
|
*.wav filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|
||||||
selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text
|
selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text
|
||||||
system/hardware/tici/updater_weston filter=lfs diff=lfs merge=lfs -text
|
system/hardware/tici/updater filter=lfs diff=lfs merge=lfs -text
|
||||||
system/hardware/tici/updater_magic filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/**/*.a filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/**/*.so filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/**/*.so.* filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/**/*.dylib filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/acados/*/t_renderer filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/qt5/larch64/bin/lrelease filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/qt5/larch64/bin/lupdate filter=lfs diff=lfs merge=lfs -text
|
|
||||||
third_party/catch2/include/catch2/catch.hpp filter=lfs diff=lfs merge=lfs -text
|
|
||||||
|
|||||||
@@ -1,8 +0,0 @@
|
|||||||
---
|
|
||||||
name: Enhancement
|
|
||||||
about: For openpilot enhancement suggestions
|
|
||||||
title: ''
|
|
||||||
labels: 'enhancement'
|
|
||||||
assignees: ''
|
|
||||||
---
|
|
||||||
|
|
||||||
@@ -34,10 +34,10 @@ jobs:
|
|||||||
echo "tinygrad_ref=$ref" >> $GITHUB_OUTPUT
|
echo "tinygrad_ref=$ref" >> $GITHUB_OUTPUT
|
||||||
echo "tinygrad_ref is $ref"
|
echo "tinygrad_ref is $ref"
|
||||||
|
|
||||||
- name: Checkout docs repo (sunnypilot-docs, gh-pages)
|
- name: Checkout docs repo (sunnypilot-models, gh-pages)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: sunnypilot/sunnypilot-docs
|
repository: sunnypilot/sunnypilot-models
|
||||||
ref: gh-pages
|
ref: gh-pages
|
||||||
path: docs
|
path: docs
|
||||||
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
||||||
@@ -120,6 +120,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upstream_branch: ${{ matrix.model.ref }}
|
upstream_branch: ${{ matrix.model.ref }}
|
||||||
custom_name: ${{ matrix.model.display_name }}
|
custom_name: ${{ matrix.model.display_name }}
|
||||||
|
is_20hz: ${{ matrix.model.is_20hz }}
|
||||||
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
||||||
json_version: ${{ needs.setup.outputs.json_version }}
|
json_version: ${{ needs.setup.outputs.json_version }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
@@ -157,6 +158,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upstream_branch: ${{ matrix.model.ref }}
|
upstream_branch: ${{ matrix.model.ref }}
|
||||||
custom_name: ${{ matrix.model.display_name }}
|
custom_name: ${{ matrix.model.display_name }}
|
||||||
|
is_20hz: ${{ matrix.model.is_20hz }}
|
||||||
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
||||||
json_version: ${{ needs.setup.outputs.json_version }}
|
json_version: ${{ needs.setup.outputs.json_version }}
|
||||||
artifact_suffix: -retry
|
artifact_suffix: -retry
|
||||||
@@ -202,7 +204,7 @@ jobs:
|
|||||||
- name: Checkout docs repo
|
- name: Checkout docs repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: sunnypilot/sunnypilot-docs
|
repository: sunnypilot/sunnypilot-models
|
||||||
ref: gh-pages
|
ref: gh-pages
|
||||||
path: docs
|
path: docs
|
||||||
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
||||||
|
|||||||
@@ -12,11 +12,11 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
recompiled_dir:
|
recompiled_dir:
|
||||||
description: 'Existing recompiled directory number (e.g. 3 for recompiled3)'
|
description: 'Existing recompiled directory number (e.g. 1 for recompiled1)'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
json_version:
|
json_version:
|
||||||
description: 'driving_models version number to update (e.g. 5 for driving_models_v5.json)'
|
description: 'driving_models version number to update (e.g. 18 for driving_models_v18.json)'
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
artifact_suffix:
|
artifact_suffix:
|
||||||
@@ -24,6 +24,11 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
|
is_20hz:
|
||||||
|
description: 'Is this a 20Hz model'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
bypass_push:
|
bypass_push:
|
||||||
description: 'Bypass pushing to GitLab for build-all'
|
description: 'Bypass pushing to GitLab for build-all'
|
||||||
required: false
|
required: false
|
||||||
@@ -39,6 +44,11 @@ on:
|
|||||||
description: 'Custom name for the model (no date, only name)'
|
description: 'Custom name for the model (no date, only name)'
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
|
is_20hz:
|
||||||
|
description: 'Is this a 20Hz model'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
recompiled_dir:
|
recompiled_dir:
|
||||||
description: 'Existing recompiled directory number (e.g. 3 for recompiled3)'
|
description: 'Existing recompiled directory number (e.g. 3 for recompiled3)'
|
||||||
required: true
|
required: true
|
||||||
@@ -53,12 +63,11 @@ on:
|
|||||||
default: 'None'
|
default: 'None'
|
||||||
options:
|
options:
|
||||||
- None
|
- None
|
||||||
- Simple Plan Models
|
- Master Models
|
||||||
- Space Lab Models
|
- Release Models
|
||||||
- TR Models
|
- 2025 World Models
|
||||||
- DTR Models
|
- 2026 World Models
|
||||||
- Custom Merge Models
|
- Custom Merge Models
|
||||||
- FOF series models
|
|
||||||
- Other
|
- Other
|
||||||
custom_model_folder:
|
custom_model_folder:
|
||||||
description: 'Custom model folder name (if "Other" selected)'
|
description: 'Custom model folder name (if "Other" selected)'
|
||||||
@@ -82,7 +91,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
upstream_branch: ${{ inputs.upstream_branch }}
|
upstream_branch: ${{ inputs.upstream_branch }}
|
||||||
custom_name: ${{ inputs.custom_name || inputs.upstream_branch }}
|
custom_name: ${{ inputs.custom_name || inputs.upstream_branch }}
|
||||||
is_20hz: true
|
is_20hz: ${{ inputs.is_20hz }}
|
||||||
artifact_suffix: ${{ inputs.artifact_suffix }}
|
artifact_suffix: ${{ inputs.artifact_suffix }}
|
||||||
secrets: inherit
|
secrets: inherit
|
||||||
|
|
||||||
@@ -119,7 +128,7 @@ jobs:
|
|||||||
- name: Checkout docs repo
|
- name: Checkout docs repo
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: sunnypilot/sunnypilot-docs
|
repository: sunnypilot/sunnypilot-models
|
||||||
ref: gh-pages
|
ref: gh-pages
|
||||||
path: docs
|
path: docs
|
||||||
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
||||||
|
|||||||
@@ -23,56 +23,43 @@ env:
|
|||||||
CI: 1
|
CI: 1
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
generate_cereal_artifact:
|
|
||||||
name: Generate cereal validation artifacts
|
|
||||||
runs-on: ubuntu-24.04
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- run: ./tools/op.sh setup
|
|
||||||
- name: Build openpilot
|
|
||||||
run: scons -j$(nproc) cereal
|
|
||||||
- name: Generate the log file
|
|
||||||
run: |
|
|
||||||
export PYTHONPATH=${{ github.workspace }}
|
|
||||||
python3 cereal/messaging/tests/validate_sp_cereal_upstream.py -g -f schema_instances.bin
|
|
||||||
- name: 'Prepare artifact'
|
|
||||||
run: |
|
|
||||||
mkdir -p "cereal/messaging/tests/cereal_validations"
|
|
||||||
cp cereal/messaging/tests/validate_sp_cereal_upstream.py "cereal/messaging/tests/cereal_validations/validate_sp_cereal_upstream.py"
|
|
||||||
cp schema_instances.bin "cereal/messaging/tests/cereal_validations/schema_instances.bin"
|
|
||||||
- name: 'Upload Artifact'
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: cereal_validations
|
|
||||||
path: cereal/messaging/tests/cereal_validations
|
|
||||||
|
|
||||||
validate_cereal_with_upstream:
|
validate_cereal_with_upstream:
|
||||||
name: Validate cereal with Upstream
|
name: Validate cereal with Upstream
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
needs: generate_cereal_artifact
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout sunnypilot
|
- name: Checkout sunnypilot cereal
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
- name: Checkout upstream openpilot
|
with:
|
||||||
|
sparse-checkout: cereal
|
||||||
|
|
||||||
|
- name: Init sunnypilot opendbc submodule
|
||||||
|
run: git submodule update --init --depth 1 opendbc_repo
|
||||||
|
|
||||||
|
- name: Checkout upstream openpilot cereal
|
||||||
uses: actions/checkout@v6
|
uses: actions/checkout@v6
|
||||||
with:
|
with:
|
||||||
repository: 'commaai/openpilot'
|
repository: 'commaai/openpilot'
|
||||||
path: openpilot
|
path: upstream_openpilot
|
||||||
submodules: true
|
sparse-checkout: cereal
|
||||||
ref: "refs/heads/master"
|
ref: "refs/heads/master"
|
||||||
- run: ./tools/op.sh setup
|
|
||||||
- name: Build openpilot
|
- name: Init upstream opendbc submodule
|
||||||
working-directory: openpilot
|
working-directory: upstream_openpilot
|
||||||
run: scons -j$(nproc) cereal
|
run: git submodule update --init --depth 1 opendbc_repo
|
||||||
- name: Download build artifacts
|
|
||||||
uses: actions/download-artifact@v4
|
- name: Install uv
|
||||||
with:
|
run: pip install uv
|
||||||
name: cereal_validations
|
|
||||||
path: openpilot/cereal/messaging/tests/cereal_validations
|
- name: Generate sunnypilot schema
|
||||||
- name: 'Run the validation'
|
|
||||||
run: |
|
run: |
|
||||||
export PYTHONPATH=${{ github.workspace }}/openpilot
|
PYCAPNP_VER=$(python3 -c "import re; m=re.search(r'name = \"pycapnp\"\nversion = \"([^\"]+)\"', open('uv.lock').read()); print(m.group(1))")
|
||||||
chmod +x openpilot/cereal/messaging/tests/cereal_validations/validate_sp_cereal_upstream.py
|
uv run --isolated --with "pycapnp==${PYCAPNP_VER}" \
|
||||||
python3 openpilot/cereal/messaging/tests/cereal_validations/validate_sp_cereal_upstream.py -r -f openpilot/cereal/messaging/tests/cereal_validations/schema_instances.bin
|
python3 cereal/messaging/tests/validate_sp_cereal_upstream.py \
|
||||||
|
-g -f /tmp/sp_schema.json --cereal-dir cereal
|
||||||
|
|
||||||
|
- name: Validate against upstream
|
||||||
|
run: |
|
||||||
|
PYCAPNP_VER=$(python3 -c "import re; m=re.search(r'name = \"pycapnp\"\nversion = \"([^\"]+)\"', open('uv.lock').read()); print(m.group(1))")
|
||||||
|
uv run --isolated --with "pycapnp==${PYCAPNP_VER}" \
|
||||||
|
python3 cereal/messaging/tests/validate_sp_cereal_upstream.py \
|
||||||
|
-r -f /tmp/sp_schema.json --cereal-dir upstream_openpilot/cereal
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
name: diff report
|
||||||
|
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [opened, synchronize, reopened]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
comment:
|
||||||
|
name: comment
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
timeout-minutes: 10
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
pull-requests: write
|
||||||
|
actions: read
|
||||||
|
steps:
|
||||||
|
- name: Wait for process replay
|
||||||
|
id: wait
|
||||||
|
continue-on-error: true
|
||||||
|
uses: lewagon/wait-on-check-action@v1.3.4
|
||||||
|
with:
|
||||||
|
ref: ${{ github.event.pull_request.head.sha }}
|
||||||
|
check-name: process replay
|
||||||
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
allowed-conclusions: success,failure
|
||||||
|
wait-interval: 20
|
||||||
|
- name: Download diff
|
||||||
|
if: steps.wait.outcome == 'success'
|
||||||
|
uses: dawidd6/action-download-artifact@v6
|
||||||
|
with:
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
workflow: tests.yaml
|
||||||
|
workflow_conclusion: ''
|
||||||
|
pr: ${{ github.event.number }}
|
||||||
|
name: diff_report_${{ github.event.number }}
|
||||||
|
path: .
|
||||||
|
allow_forks: true
|
||||||
|
- name: Comment on PR
|
||||||
|
if: steps.wait.outcome == 'success'
|
||||||
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
|
with:
|
||||||
|
filePath: diff_report.txt
|
||||||
|
comment_tag: diff_report
|
||||||
|
pr_number: ${{ github.event.number }}
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -29,9 +29,9 @@ jobs:
|
|||||||
# Build
|
# Build
|
||||||
- name: Build docs
|
- name: Build docs
|
||||||
run: |
|
run: |
|
||||||
# TODO: can we install just the "docs" dependency group without the normal deps?
|
git lfs pull
|
||||||
pip install mkdocs
|
pip install zensical
|
||||||
mkdocs build
|
python scripts/docs.py build
|
||||||
|
|
||||||
# Push to docs.comma.ai
|
# Push to docs.comma.ai
|
||||||
- uses: actions/checkout@v6
|
- uses: actions/checkout@v6
|
||||||
|
|||||||
@@ -9,28 +9,6 @@ env:
|
|||||||
PYTHONPATH: ${{ github.workspace }}
|
PYTHONPATH: ${{ github.workspace }}
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update_translations:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
if: github.repository == 'sunnypilot/sunnypilot'
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v6
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- run: ./tools/op.sh setup
|
|
||||||
- name: Update translations
|
|
||||||
run: python3 selfdrive/ui/update_translations.py --vanish
|
|
||||||
- name: Create Pull Request
|
|
||||||
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
|
|
||||||
with:
|
|
||||||
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
|
|
||||||
commit-message: "Update translations"
|
|
||||||
title: "[bot] Update translations"
|
|
||||||
body: "Automatic PR from repo-maintenance -> update_translations"
|
|
||||||
branch: "update-translations"
|
|
||||||
base: "master"
|
|
||||||
delete-branch: true
|
|
||||||
labels: bot
|
|
||||||
|
|
||||||
package_updates:
|
package_updates:
|
||||||
name: package_updates
|
name: package_updates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
@@ -72,7 +50,6 @@ jobs:
|
|||||||
git add .
|
git add .
|
||||||
- name: update car docs
|
- name: update car docs
|
||||||
run: |
|
run: |
|
||||||
scons -j$(nproc) --minimal opendbc_repo
|
|
||||||
python selfdrive/car/docs.py
|
python selfdrive/car/docs.py
|
||||||
git add docs/CARS.md
|
git add docs/CARS.md
|
||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
|
|||||||
@@ -30,6 +30,11 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
default: ''
|
default: ''
|
||||||
|
target_hardware:
|
||||||
|
description: 'Hardware target to compile for (qcom or usbgpu)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: 'qcom'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
upstream_branch:
|
upstream_branch:
|
||||||
@@ -46,6 +51,14 @@ on:
|
|||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
default: true
|
default: true
|
||||||
|
target_hardware:
|
||||||
|
description: 'Hardware target to compile for'
|
||||||
|
required: true
|
||||||
|
type: choice
|
||||||
|
options:
|
||||||
|
- qcom
|
||||||
|
- usbgpu
|
||||||
|
default: 'qcom'
|
||||||
|
|
||||||
|
|
||||||
run-name: Build model [${{ inputs.custom_name || inputs.upstream_branch }}] from ref [${{ inputs.upstream_branch }}]
|
run-name: Build model [${{ inputs.custom_name || inputs.upstream_branch }}] from ref [${{ inputs.upstream_branch }}]
|
||||||
@@ -164,26 +177,63 @@ jobs:
|
|||||||
source /etc/profile
|
source /etc/profile
|
||||||
export UV_PROJECT_ENVIRONMENT=${HOME}/venv
|
export UV_PROJECT_ENVIRONMENT=${HOME}/venv
|
||||||
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
|
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
|
||||||
export PYTHONPATH="${PYTHONPATH}:${{ env.TINYGRAD_PATH }}"
|
export PYTHONPATH="${PYTHONPATH}:${{ env.TINYGRAD_PATH }}:${{ github.workspace }}"
|
||||||
|
|
||||||
# Loop through all .onnx files
|
COMPILE_MODELD="${{ github.workspace }}/sunnypilot/modeld_v2/compile_modeld.py"
|
||||||
|
MODEL_SIZE=$(python3 -c "from openpilot.common.transformations.model import MEDMODEL_INPUT_SIZE as s; print(f'{s[0]}x{s[1]}')")
|
||||||
|
CAMERA_RES=$(python3 -c "from openpilot.common.transformations.camera import _ar_ox_fisheye as a, _os_fisheye as o; print(f'{a.width}x{a.height} {o.width}x{o.height}')")
|
||||||
|
|
||||||
|
if [ "${{ inputs.target_hardware }}" == "usbgpu" ]; then
|
||||||
|
echo "USBGPU build"
|
||||||
|
export USBGPU=1
|
||||||
|
TG_FLAGS="DEV=AMD USBGPU=1 IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1"
|
||||||
|
OUTPUT_PKL="${{ env.MODELS_DIR }}/big_driving_tinygrad.pkl"
|
||||||
|
else
|
||||||
|
echo "QCOM build"
|
||||||
|
TG_FLAGS="DEV=QCOM IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1"
|
||||||
|
OUTPUT_PKL="${{ env.MODELS_DIR }}/driving_tinygrad.pkl"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Generate metadata for all ONNX files
|
||||||
find "${{ env.MODELS_DIR }}" -maxdepth 1 -name '*.onnx' | while IFS= read -r onnx_file; do
|
find "${{ env.MODELS_DIR }}" -maxdepth 1 -name '*.onnx' | while IFS= read -r onnx_file; do
|
||||||
base_name=$(basename "$onnx_file" .onnx)
|
echo "Generating metadata: $onnx_file"
|
||||||
output_file="${{ env.MODELS_DIR }}/${base_name}_tinygrad.pkl"
|
env ${TG_FLAGS} python3 "${{ env.MODELS_DIR }}/../get_model_metadata.py" "$onnx_file" || true
|
||||||
|
|
||||||
echo "Compiling: $onnx_file -> $output_file"
|
|
||||||
QCOM=1 python3 "${{ env.TINYGRAD_PATH }}/examples/openpilot/compile3.py" "$onnx_file" "$output_file"
|
|
||||||
DEV=QCOM FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 python3 "${{ env.MODELS_DIR }}/../get_model_metadata.py" "$onnx_file" || true
|
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Validate Model Outputs
|
# Detect model type and build compile args
|
||||||
run: |
|
VISION_ONNX="${{ env.MODELS_DIR }}/driving_vision.onnx"
|
||||||
source /etc/profile
|
POLICY_ONNX="${{ env.MODELS_DIR }}/driving_policy.onnx"
|
||||||
export UV_PROJECT_ENVIRONMENT=${HOME}/venv
|
OFF_POLICY_ONNX="${{ env.MODELS_DIR }}/driving_off_policy.onnx"
|
||||||
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
|
ON_POLICY_ONNX="${{ env.MODELS_DIR }}/driving_on_policy.onnx"
|
||||||
python3 "${{ github.workspace }}/release/ci/model_generator.py" \
|
SUPERCOMBO_ONNX="${{ env.MODELS_DIR }}/supercombo.onnx"
|
||||||
--validate-only \
|
|
||||||
--model-dir "${{ env.MODELS_DIR }}"
|
MODEL_TYPE="" ONNX_ARGS="" OUTPUT_NAME=""
|
||||||
|
if [ -f "$VISION_ONNX" ]; then
|
||||||
|
ONNX_ARGS="--vision-onnx $VISION_ONNX"
|
||||||
|
if [ -f "$ON_POLICY_ONNX" ] && [ -f "$OFF_POLICY_ONNX" ]; then
|
||||||
|
MODEL_TYPE=vision_multi_policy
|
||||||
|
ONNX_ARGS="$ONNX_ARGS --off-policy-onnx $OFF_POLICY_ONNX --on-policy-onnx $ON_POLICY_ONNX"
|
||||||
|
elif [ -f "$OFF_POLICY_ONNX" ] && [ -f "$POLICY_ONNX" ]; then
|
||||||
|
MODEL_TYPE=vision_multi_policy
|
||||||
|
ONNX_ARGS="$ONNX_ARGS --policy-onnx $POLICY_ONNX --off-policy-onnx $OFF_POLICY_ONNX"
|
||||||
|
elif [ -f "$POLICY_ONNX" ]; then
|
||||||
|
MODEL_TYPE=vision_policy
|
||||||
|
ONNX_ARGS="$ONNX_ARGS --policy-onnx $POLICY_ONNX"
|
||||||
|
fi
|
||||||
|
elif [ -f "$SUPERCOMBO_ONNX" ]; then
|
||||||
|
MODEL_TYPE=supercombo
|
||||||
|
ONNX_ARGS="--supercombo-onnx $SUPERCOMBO_ONNX"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "$MODEL_TYPE" ]; then
|
||||||
|
echo "Detected: $MODEL_TYPE -> $OUTPUT_PKL"
|
||||||
|
env ${TG_FLAGS} python3 "$COMPILE_MODELD" \
|
||||||
|
--model-type $MODEL_TYPE \
|
||||||
|
--model-size $MODEL_SIZE \
|
||||||
|
--camera-resolutions $CAMERA_RES \
|
||||||
|
$ONNX_ARGS \
|
||||||
|
--output "$OUTPUT_PKL"
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Prepare Output
|
- name: Prepare Output
|
||||||
run: |
|
run: |
|
||||||
@@ -194,6 +244,8 @@ jobs:
|
|||||||
rsync -avm \
|
rsync -avm \
|
||||||
--include='*.dlc' \
|
--include='*.dlc' \
|
||||||
--include='*.pkl' \
|
--include='*.pkl' \
|
||||||
|
--include='*.chunk*' \
|
||||||
|
--include='*.chunkmanifest' \
|
||||||
--include='*.onnx' \
|
--include='*.onnx' \
|
||||||
--exclude='*' \
|
--exclude='*' \
|
||||||
--delete-excluded \
|
--delete-excluded \
|
||||||
|
|||||||
@@ -185,7 +185,7 @@ jobs:
|
|||||||
echo "Building sunnypilot's locationd..."
|
echo "Building sunnypilot's locationd..."
|
||||||
scons -j2 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal sunnypilot/selfdrive/locationd
|
scons -j2 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal sunnypilot/selfdrive/locationd
|
||||||
echo "Building openpilot's locationd..."
|
echo "Building openpilot's locationd..."
|
||||||
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal selfdrive/locationd
|
scons -j1 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal selfdrive/locationd
|
||||||
echo "Building rest of sunnypilot"
|
echo "Building rest of sunnypilot"
|
||||||
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal
|
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal
|
||||||
touch ${BUILD_DIR}/prebuilt
|
touch ${BUILD_DIR}/prebuilt
|
||||||
@@ -215,8 +215,8 @@ jobs:
|
|||||||
--exclude='**/SConstruct' \
|
--exclude='**/SConstruct' \
|
||||||
--exclude='**/SConscript' \
|
--exclude='**/SConscript' \
|
||||||
--exclude='**/.venv/' \
|
--exclude='**/.venv/' \
|
||||||
--exclude='selfdrive/modeld/models/driving_vision.onnx' \
|
--exclude='selfdrive/modeld/models/*.onnx*' \
|
||||||
--exclude='selfdrive/modeld/models/driving_policy.onnx' \
|
--exclude='sunnypilot/modeld*/models/*.onnx*' \
|
||||||
--exclude='third_party/*x86*' \
|
--exclude='third_party/*x86*' \
|
||||||
--exclude='third_party/*Darwin*' \
|
--exclude='third_party/*Darwin*' \
|
||||||
--delete-excluded \
|
--delete-excluded \
|
||||||
|
|||||||
@@ -123,7 +123,7 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
- run: ./tools/op.sh setup
|
- run: ./tools/op.sh setup
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: scons -j$(nproc)
|
run: scons
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 999 }}
|
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 999 }}
|
||||||
run: |
|
run: |
|
||||||
@@ -147,7 +147,7 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
- run: ./tools/op.sh setup
|
- run: ./tools/op.sh setup
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: scons -j$(nproc)
|
run: scons
|
||||||
- name: Run replay
|
- name: Run replay
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 20 }}
|
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 20 }}
|
||||||
continue-on-error: ${{ github.ref == 'refs/heads/master' }}
|
continue-on-error: ${{ github.ref == 'refs/heads/master' }}
|
||||||
@@ -156,12 +156,22 @@ jobs:
|
|||||||
id: print-diff
|
id: print-diff
|
||||||
if: always()
|
if: always()
|
||||||
run: cat selfdrive/test/process_replay/diff.txt
|
run: cat selfdrive/test/process_replay/diff.txt
|
||||||
|
- name: Print diff report
|
||||||
|
if: always()
|
||||||
|
run: cat selfdrive/test/process_replay/diff_report.txt
|
||||||
- uses: actions/upload-artifact@v6
|
- uses: actions/upload-artifact@v6
|
||||||
if: always()
|
if: always()
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
with:
|
with:
|
||||||
name: process_replay_diff.txt
|
name: process_replay_diff.txt
|
||||||
path: selfdrive/test/process_replay/diff.txt
|
path: selfdrive/test/process_replay/diff.txt
|
||||||
|
- name: Upload diff report
|
||||||
|
uses: actions/upload-artifact@v6
|
||||||
|
if: always() && github.event_name == 'pull_request'
|
||||||
|
continue-on-error: true
|
||||||
|
with:
|
||||||
|
name: diff_report_${{ github.event.number }}
|
||||||
|
path: selfdrive/test/process_replay/diff_report.txt
|
||||||
- name: Checkout ci-artifacts
|
- name: Checkout ci-artifacts
|
||||||
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
|
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
@@ -169,7 +179,7 @@ jobs:
|
|||||||
repository: commaai/ci-artifacts
|
repository: commaai/ci-artifacts
|
||||||
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
||||||
path: ${{ github.workspace }}/ci-artifacts
|
path: ${{ github.workspace }}/ci-artifacts
|
||||||
- name: Push refs
|
- name: Prepare refs
|
||||||
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
|
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
|
||||||
working-directory: ${{ github.workspace }}/ci-artifacts
|
working-directory: ${{ github.workspace }}/ci-artifacts
|
||||||
run: |
|
run: |
|
||||||
@@ -181,7 +191,13 @@ jobs:
|
|||||||
echo "${{ github.sha }}" > ref_commit
|
echo "${{ github.sha }}" > ref_commit
|
||||||
git add .
|
git add .
|
||||||
git commit -m "process-replay refs for ${{ github.repository }}@${{ github.sha }}" || echo "No changes to commit"
|
git commit -m "process-replay refs for ${{ github.repository }}@${{ github.sha }}" || echo "No changes to commit"
|
||||||
git push origin process-replay
|
- name: Push refs
|
||||||
|
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
|
||||||
|
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e
|
||||||
|
with:
|
||||||
|
timeout_minutes: 2
|
||||||
|
max_attempts: 3
|
||||||
|
command: cd ${{ github.workspace }}/ci-artifacts && git push origin process-replay --force
|
||||||
- name: Run regen
|
- name: Run regen
|
||||||
if: false
|
if: false
|
||||||
timeout-minutes: 4
|
timeout-minutes: 4
|
||||||
@@ -204,7 +220,7 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
- run: ./tools/op.sh setup
|
- run: ./tools/op.sh setup
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: scons -j$(nproc)
|
run: scons
|
||||||
- name: Driving test
|
- name: Driving test
|
||||||
timeout-minutes: 2
|
timeout-minutes: 2
|
||||||
run: |
|
run: |
|
||||||
@@ -225,7 +241,7 @@ jobs:
|
|||||||
submodules: true
|
submodules: true
|
||||||
- run: ./tools/op.sh setup
|
- run: ./tools/op.sh setup
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: scons -j$(nproc)
|
run: scons
|
||||||
- name: Create UI Report
|
- name: Create UI Report
|
||||||
run: |
|
run: |
|
||||||
source selfdrive/test/setup_xvfb.sh
|
source selfdrive/test/setup_xvfb.sh
|
||||||
|
|||||||
+15
-26
@@ -13,13 +13,13 @@ venv/
|
|||||||
a.out
|
a.out
|
||||||
.hypothesis
|
.hypothesis
|
||||||
.cache/
|
.cache/
|
||||||
|
bin/
|
||||||
/docs_site/
|
|
||||||
|
|
||||||
*.mp4
|
*.mp4
|
||||||
*.dylib
|
*.dylib
|
||||||
*.DSYM
|
*.DSYM
|
||||||
*.d
|
*.d
|
||||||
|
*.pem
|
||||||
*.pyc
|
*.pyc
|
||||||
*.pyo
|
*.pyo
|
||||||
.*.swp
|
.*.swp
|
||||||
@@ -39,11 +39,15 @@ a.out
|
|||||||
*.mo
|
*.mo
|
||||||
*_pyx.cpp
|
*_pyx.cpp
|
||||||
*.stats
|
*.stats
|
||||||
|
*.pkl
|
||||||
|
*.pkl*
|
||||||
config.json
|
config.json
|
||||||
clcache
|
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
compare_runtime*.html
|
compare_runtime*.html
|
||||||
|
selfdrive/modeld/models/tg_input_devices.json
|
||||||
|
|
||||||
|
# build artifacts
|
||||||
|
docs_site/
|
||||||
selfdrive/pandad/pandad
|
selfdrive/pandad/pandad
|
||||||
cereal/services.h
|
cereal/services.h
|
||||||
cereal/gen
|
cereal/gen
|
||||||
@@ -56,51 +60,36 @@ system/camerad/test/ae_gray_test
|
|||||||
.coverage*
|
.coverage*
|
||||||
coverage.xml
|
coverage.xml
|
||||||
htmlcov
|
htmlcov
|
||||||
pandaextra
|
|
||||||
|
|
||||||
.mypy_cache/
|
|
||||||
flycheck_*
|
|
||||||
|
|
||||||
cppcheck_report.txt
|
|
||||||
comma*.sh
|
|
||||||
|
|
||||||
selfdrive/modeld/models/*.pkl*
|
|
||||||
sunnypilot/modeld*/models/*.pkl
|
|
||||||
|
|
||||||
# openpilot log files
|
# openpilot log files
|
||||||
*.bz2
|
*.bz2
|
||||||
*.zst
|
*.zst
|
||||||
|
*.rlog
|
||||||
|
|
||||||
build/
|
build/
|
||||||
|
|
||||||
!**/.gitkeep
|
!**/.gitkeep
|
||||||
|
|
||||||
poetry.toml
|
|
||||||
Pipfile
|
|
||||||
|
|
||||||
### VisualStudioCode ###
|
### VisualStudioCode ###
|
||||||
|
*.vsix
|
||||||
|
.history
|
||||||
|
.ionide
|
||||||
.vscode/*
|
.vscode/*
|
||||||
|
.history/
|
||||||
!.vscode/settings.json
|
!.vscode/settings.json
|
||||||
!.vscode/tasks.json
|
!.vscode/tasks.json
|
||||||
!.vscode/launch.json
|
!.vscode/launch.json
|
||||||
!.vscode/extensions.json
|
!.vscode/extensions.json
|
||||||
!.vscode/*.code-snippets
|
!.vscode/*.code-snippets
|
||||||
|
|
||||||
# Local History for Visual Studio Code
|
# agents
|
||||||
.history/
|
|
||||||
|
|
||||||
# Built Visual Studio Code Extensions
|
|
||||||
*.vsix
|
|
||||||
|
|
||||||
### VisualStudioCode Patch ###
|
|
||||||
# Ignore all local history of files
|
|
||||||
.history
|
|
||||||
.ionide
|
|
||||||
|
|
||||||
.claude/
|
.claude/
|
||||||
.context/
|
.context/
|
||||||
PLAN.md
|
PLAN.md
|
||||||
TASK.md
|
TASK.md
|
||||||
|
CLAUDE.md
|
||||||
|
SKILL.md
|
||||||
|
|
||||||
### JetBrains ###
|
### JetBrains ###
|
||||||
!.idea/customTargets.xml
|
!.idea/customTargets.xml
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
3.12.13
|
||||||
Vendored
+3
@@ -52,6 +52,9 @@
|
|||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "attach",
|
"request": "attach",
|
||||||
"pid": "${command:pickMyProcess}",
|
"pid": "${command:pickMyProcess}",
|
||||||
|
"sourceMap": {
|
||||||
|
".": "${workspaceFolder}/opendbc/safety"
|
||||||
|
},
|
||||||
"initCommands": [
|
"initCommands": [
|
||||||
"script import time; time.sleep(3)"
|
"script import time; time.sleep(3)"
|
||||||
]
|
]
|
||||||
|
|||||||
Vendored
-1
@@ -21,7 +21,6 @@
|
|||||||
"common/**",
|
"common/**",
|
||||||
"selfdrive/**",
|
"selfdrive/**",
|
||||||
"system/**",
|
"system/**",
|
||||||
"third_party/**",
|
|
||||||
"tools/**",
|
"tools/**",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
+89
-1
@@ -1,4 +1,7 @@
|
|||||||
sunnypilot Version 2026.001.000 (2026-03-xx)
|
sunnypilot Version 2026.002.000 (2026-xx-xx)
|
||||||
|
========================
|
||||||
|
|
||||||
|
sunnypilot Version 2026.001.000 (2026-05-06)
|
||||||
========================
|
========================
|
||||||
* What's Changed (sunnypilot/sunnypilot)
|
* What's Changed (sunnypilot/sunnypilot)
|
||||||
* Complete rewrite of the user interface from Qt C++ to Raylib Python
|
* Complete rewrite of the user interface from Qt C++ to Raylib Python
|
||||||
@@ -66,6 +69,64 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
|
|||||||
* Pause Lateral Control with Blinker: Post-Blinker Delay by @CHaucke89
|
* Pause Lateral Control with Blinker: Post-Blinker Delay by @CHaucke89
|
||||||
* SCC-V: Use p97 for predicted lateral accel by @yasu-oh
|
* SCC-V: Use p97 for predicted lateral accel by @yasu-oh
|
||||||
* Controls: Support for Torque Lateral Control v0 Tune by @sunnyhaibin
|
* Controls: Support for Torque Lateral Control v0 Tune by @sunnyhaibin
|
||||||
|
* [TIZI/TICI] ui: ensure null checks for `CarParams` and `CarParamsSP` by @sunnyhaibin
|
||||||
|
* [TIZI/TICI] ui: use `vCruiseCluster` and `vEgoCluster` for SLA `preActive` by @sunnyhaibin
|
||||||
|
* Fix display of values when using use_float_scaling by @CHaucke89
|
||||||
|
* models: fix default & index "0" by @nayan8teen
|
||||||
|
* [TIZI/TICI] visuals: Improved speed limit by @angaz
|
||||||
|
* ICBM: ensure button timers update on disable to clear stale presses by @jamesmikesell
|
||||||
|
* [TIZI/TICI] ui: simplify Smart Cruise Control text rendering by @sunnyhaibin
|
||||||
|
* controlsd: fix steer_limited_by_safety not updating under MADS by @zephleggett
|
||||||
|
* soundd: trigger timeout warning during MADS lateral-only by @zephleggett
|
||||||
|
* pandad: flasher for Rivian long upgrade module by @lukasloetkolben
|
||||||
|
* modeld_v2: tinygrad transformation warp by @Discountchubbs
|
||||||
|
* tools: block `manage_sunnylinkd` in sim startup script by @sunnyhaibin
|
||||||
|
* [MICI] ui: need superclass `_render` in `HudRendererSP` by @sunnyhaibin
|
||||||
|
* [TIZI/TICI] ui: Speed Limit Assist active status by @sunnyhaibin
|
||||||
|
* ui: reimplement "Screen Off" option to Onroad Brightness by @sunnyhaibin
|
||||||
|
* ui: don't hide steering wheel when blindspot disabled by @royjr
|
||||||
|
* ui: Speed Limit Assist `preActive` improvements by @sunnyhaibin
|
||||||
|
* ui: consolidate Speed Limit Assist `preActive` status rendering by @sunnyhaibin
|
||||||
|
* [MICI] ui: Speed Limit Assist `preActive` status by @sunnyhaibin
|
||||||
|
* sunnypilot modeld: remove thneed modeld by @Discountchubbs
|
||||||
|
* modeld_v2: decouple planplus scaling from accel by @Discountchubbs
|
||||||
|
* sunnylink: Handle exceptions in `getParamsAllKeysV1` to log crashes by @devtekve
|
||||||
|
* [TIZI/TICI] ui: Developer UI cleanup by @sunnyhaibin
|
||||||
|
* [TIZI/TICI] ui: dynamic alert size by @nayan8teen
|
||||||
|
* i18n(fr): Add French translations by @didlawowo
|
||||||
|
* Toyota: Stop and Go Hack (Alpha) by @sunnyhaibin
|
||||||
|
* ui: `AlertFadeAnimator` for longitudinal-related statuses by @sunnyhaibin
|
||||||
|
* pandad: gate unsupported pandas before flashing by @sunnyhaibin
|
||||||
|
* Rivian: Flash xnor's Longitudinal Upgrade Kit prior supported panda check by @lukasloetkolben
|
||||||
|
* [TIZI/TICI] ui: add back gate steering arc behind toggle by @sunnyhaibin
|
||||||
|
* ui: gate Onroad Brightness Delay on readiness by @sunnyhaibin
|
||||||
|
* ui: add new timer options for Onroad Brightness Delay by @sunnyhaibin
|
||||||
|
* [TIZI/TICI] ui: branch switcher is always available by @sunnyhaibin
|
||||||
|
* pandad: always prioritize internal panda by @sunnyhaibin
|
||||||
|
* sunnylinkd: fetch compressed params schema by @sunnyhaibin
|
||||||
|
* sunnypilot locationd: remove unused car_ekf filter by @sunnyhaibin
|
||||||
|
* modeld_v2: update deprecated temporalPose ref by @sunnyhaibin
|
||||||
|
* NNLC: restore pre-v1 PID gains in torque extension by @mmmorks
|
||||||
|
* MADS safety: enable heartbeat and lateral controls mismatch checks by @sunnyhaibin
|
||||||
|
* [MICI] ui: models panel enhancements by @nayan8teen
|
||||||
|
* [TIZI/TICI] ui: fix unintended selection while scrolling in TreeOptionDialog by @TheSecurityDev
|
||||||
|
* tools: script for video concatenation by @Discountchubbs
|
||||||
|
* tools: profile memory usage by @Discountchubbs
|
||||||
|
* [TIZI/TICI] ui: remove per-frame param sync by @sunnyhaibin
|
||||||
|
* [MICI] ui: always offroad by @nayan8teen
|
||||||
|
* controls: always default Torque Lateral Control to v0 Tune by @sunnyhaibin
|
||||||
|
* Revert "controls: always default Torque Lateral Control to v0 Tune" by @sunnyhaibin
|
||||||
|
* Reapply "controls: always default Torque Lateral Control to v0 Tune" (#1806) by @sunnyhaibin
|
||||||
|
* [MICI] ui: add sunnylink info & connectivity check by @nayan8teen
|
||||||
|
* sunnylink: Remove unused API endpoint by @devtekve
|
||||||
|
* DM: wheel touch enforcement in MADS by @sunnyhaibin
|
||||||
|
* torque: show static override values in Dev UI & gate `useParams` on custom torque tune by @sunnyhaibin
|
||||||
|
* MADS: suppress espActive event when long is not engaged by @sunnyhaibin
|
||||||
|
* sunnylink: SDUI by @sunnyhaibin
|
||||||
|
* [MICI] ui: align upstream changes with sunnypilot settings buttons by @nayan8teen
|
||||||
|
* ui: fix cellular toggles by @AmyJeanes
|
||||||
|
* sunnylink: switch athena domain by @devtekve
|
||||||
|
* Platform List: dynamically migrate CarPlatformBundle by @sunnyhaibin
|
||||||
* What's Changed (sunnypilot/opendbc)
|
* What's Changed (sunnypilot/opendbc)
|
||||||
* Honda: DBC for Accord 9th Generation by @mvl-boston
|
* Honda: DBC for Accord 9th Generation by @mvl-boston
|
||||||
* FCA: update tire stiffness values for `RAM_HD` by @dparring
|
* FCA: update tire stiffness values for `RAM_HD` by @dparring
|
||||||
@@ -84,12 +145,25 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
|
|||||||
* Honda: add missing `GasInterceptor` messages to Taiwan Odyssey DBC by @mvl-boston
|
* Honda: add missing `GasInterceptor` messages to Taiwan Odyssey DBC by @mvl-boston
|
||||||
* GM: remove `CHEVROLET_EQUINOX_NON_ACC_3RD_GEN` from `dashcamOnly` by @sunnyhaibin
|
* GM: remove `CHEVROLET_EQUINOX_NON_ACC_3RD_GEN` from `dashcamOnly` by @sunnyhaibin
|
||||||
* GM: remove `CHEVROLET_BOLT_NON_ACC_2ND_GEN` from `dashcamOnly` by @sunnyhaibin
|
* GM: remove `CHEVROLET_BOLT_NON_ACC_2ND_GEN` from `dashcamOnly` by @sunnyhaibin
|
||||||
|
* Hyundai Longitudinal: deprecate ramp update for dynamic tune by @Discountchubbs
|
||||||
|
* Rivian: long upgrade messages on bus 1 by @lukasloetkolben
|
||||||
|
* Toyota: Stop and Go Hack (Alpha) by @sunnyhaibin
|
||||||
|
* Toyota: gate Smart DSU behind Alpha Longitudinal by @sunnyhaibin
|
||||||
|
* Toyota: Gas Interceptor always set `standstill_req` by @sunnyhaibin
|
||||||
|
* MADS safety: dedicated `controls_allowed_lateral` by @sunnyhaibin
|
||||||
|
* Platform List: include community supported platforms by @sunnyhaibin
|
||||||
* New Contributors (sunnypilot/sunnypilot)
|
* New Contributors (sunnypilot/sunnypilot)
|
||||||
* @TheSecurityDev made their first contribution in "ui: fix sidebar scroll in UI screenshots"
|
* @TheSecurityDev made their first contribution in "ui: fix sidebar scroll in UI screenshots"
|
||||||
* @zikeji made their first contribution in "sunnylink: block remote modification of SSH key parameters"
|
* @zikeji made their first contribution in "sunnylink: block remote modification of SSH key parameters"
|
||||||
* @Candy0707 made their first contribution in "[TIZI/TICI] ui: Fix misaligned turn signals and blindspot indicators with sidebar"
|
* @Candy0707 made their first contribution in "[TIZI/TICI] ui: Fix misaligned turn signals and blindspot indicators with sidebar"
|
||||||
* @CHaucke89 made their first contribution in "Pause Lateral Control with Blinker: Post-Blinker Delay"
|
* @CHaucke89 made their first contribution in "Pause Lateral Control with Blinker: Post-Blinker Delay"
|
||||||
* @yasu-oh made their first contribution in "SCC-V: Use p97 for predicted lateral accel"
|
* @yasu-oh made their first contribution in "SCC-V: Use p97 for predicted lateral accel"
|
||||||
|
* @angaz made their first contribution in "[TIZI/TICI] visuals: Improved speed limit"
|
||||||
|
* @jamesmikesell made their first contribution in "ICBM: ensure button timers update on disable to clear stale presses"
|
||||||
|
* @zephleggett made their first contribution in "controlsd: fix steer_limited_by_safety not updating under MADS"
|
||||||
|
* @lukasloetkolben made their first contribution in "pandad: flasher for Rivian long upgrade module"
|
||||||
|
* @didlawowo made their first contribution in "i18n(fr): Add French translations"
|
||||||
|
* @mmmorks made their first contribution in "NNLC: restore pre-v1 PID gains in torque extension"
|
||||||
* New Contributors (sunnypilot/opendbc)
|
* New Contributors (sunnypilot/opendbc)
|
||||||
* @AmyJeanes made their first contribution in "Tesla: Fix stock LKAS being blocked when MADS is enabled"
|
* @AmyJeanes made their first contribution in "Tesla: Fix stock LKAS being blocked when MADS is enabled"
|
||||||
* @mvl-boston made their first contribution in "Honda: Update Clarity brake to renamed DBC message name"
|
* @mvl-boston made their first contribution in "Honda: Update Clarity brake to renamed DBC message name"
|
||||||
@@ -99,6 +173,20 @@ sunnypilot Version 2026.001.000 (2026-03-xx)
|
|||||||
* @royjr made their first contribution in "HKG: add KIA_FORTE_2019_NON_SCC fingerprint"
|
* @royjr made their first contribution in "HKG: add KIA_FORTE_2019_NON_SCC fingerprint"
|
||||||
* @ssysm made their first contribution in "Tesla: remove `TESLA_MODEL_X` from `dashcamOnly`"
|
* @ssysm made their first contribution in "Tesla: remove `TESLA_MODEL_X` from `dashcamOnly`"
|
||||||
* Full Changelog: https://github.com/sunnypilot/sunnypilot/compare/v2025.002.000...v2026.001.000
|
* Full Changelog: https://github.com/sunnypilot/sunnypilot/compare/v2025.002.000...v2026.001.000
|
||||||
|
************************
|
||||||
|
* Synced with commaai's openpilot (v0.11.1)
|
||||||
|
* master commit c001f3c9b490a80e69539f0af6022f6e07ceb721 (April 16, 2026)
|
||||||
|
* New driver monitoring model
|
||||||
|
* Improved image processing pipeline for driver camera
|
||||||
|
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
|
||||||
|
* New driving model #36798
|
||||||
|
* Fully trained using a learned simulator
|
||||||
|
* Improved longitudinal performance in Experimental mode
|
||||||
|
* Reduce comma four standby power usage by 77% to 52 mW
|
||||||
|
* Kia K7 2017 support thanks to royjr!
|
||||||
|
* Lexus LS 2018 support thanks to Hacheoy!
|
||||||
|
* Improved inter-process communication memory efficiency
|
||||||
|
* comma four support
|
||||||
|
|
||||||
sunnypilot Version 2025.002.000 (2025-11-06)
|
sunnypilot Version 2025.002.000 (2025-11-06)
|
||||||
========================
|
========================
|
||||||
|
|||||||
Vendored
+5
-6
@@ -166,8 +166,8 @@ node {
|
|||||||
env.GIT_BRANCH = checkout(scm).GIT_BRANCH
|
env.GIT_BRANCH = checkout(scm).GIT_BRANCH
|
||||||
env.GIT_COMMIT = checkout(scm).GIT_COMMIT
|
env.GIT_COMMIT = checkout(scm).GIT_COMMIT
|
||||||
|
|
||||||
def excludeBranches = ['__nightly', 'devel', 'devel-staging', 'release3', 'release3-staging',
|
def excludeBranches = ['__nightly', 'devel', 'devel-staging',
|
||||||
'release-tici', 'release-tizi', 'release-tizi-staging', 'testing-closet*', 'hotfix-*']
|
'release-tizi', 'release-tizi-staging', 'release-mici', 'release-mici-staging', 'testing-closet*', 'hotfix-*']
|
||||||
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
|
def excludeRegex = excludeBranches.join('|').replaceAll('\\*', '.*')
|
||||||
|
|
||||||
if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
|
if (env.BRANCH_NAME != 'master' && !env.BRANCH_NAME.contains('__jenkins_loop_')) {
|
||||||
@@ -179,7 +179,7 @@ node {
|
|||||||
try {
|
try {
|
||||||
if (env.BRANCH_NAME == 'devel-staging') {
|
if (env.BRANCH_NAME == 'devel-staging') {
|
||||||
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
|
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
|
||||||
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging $SOURCE_DIR/release/build_release.sh"),
|
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging,release-mici-staging $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,14 +218,14 @@ node {
|
|||||||
'camerad OX03C10': {
|
'camerad OX03C10': {
|
||||||
deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [
|
deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"),
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'camerad OS04C10': {
|
'camerad OS04C10': {
|
||||||
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
|
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"),
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
@@ -247,7 +247,6 @@ node {
|
|||||||
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
||||||
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
||||||
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
||||||
step("test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py", [diffPaths: ["system/qcomgpsd/"]]),
|
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
+17
-2
@@ -1,8 +1,23 @@
|
|||||||
Version 0.10.4 (2026-02-17)
|
Version 0.11.2 (2026-06-15)
|
||||||
========================
|
========================
|
||||||
|
|
||||||
|
|
||||||
|
Version 0.11.1 (2026-05-18)
|
||||||
|
========================
|
||||||
|
* New driver monitoring model
|
||||||
|
* Improved image processing pipeline for driver camera
|
||||||
|
* Improved thermal policy for comma four
|
||||||
|
* Acura MDX 2022-24 support thanks to mvl-boston!
|
||||||
|
* Rivian R1S and R1T 2025 support thanks to lukasloetkolben!
|
||||||
|
|
||||||
|
Version 0.11.0 (2026-03-17)
|
||||||
|
========================
|
||||||
|
* New driving model #36798
|
||||||
|
* Fully trained using a learned simulator
|
||||||
|
* Improved longitudinal performance in Experimental mode
|
||||||
|
* Reduce comma four standby power usage by 77% to 52 mW
|
||||||
* Kia K7 2017 support thanks to royjr!
|
* Kia K7 2017 support thanks to royjr!
|
||||||
* Lexus LS 2018 support thanks to Hacheoy!
|
* Lexus LS 2018 support thanks to Hacheoy!
|
||||||
* Reduce comma four standby power usage by 77% to 52 mW
|
|
||||||
|
|
||||||
Version 0.10.3 (2025-12-17)
|
Version 0.10.3 (2025-12-17)
|
||||||
========================
|
========================
|
||||||
|
|||||||
+124
-70
@@ -4,32 +4,34 @@ import sys
|
|||||||
import sysconfig
|
import sysconfig
|
||||||
import platform
|
import platform
|
||||||
import shlex
|
import shlex
|
||||||
|
import importlib
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import SCons.Errors
|
import SCons.Errors
|
||||||
|
from SCons.Defaults import _stripixes
|
||||||
|
|
||||||
|
TICI = os.path.isfile('/TICI')
|
||||||
|
|
||||||
SCons.Warnings.warningAsException(True)
|
SCons.Warnings.warningAsException(True)
|
||||||
|
|
||||||
Decider('MD5-timestamp')
|
Decider('MD5-timestamp')
|
||||||
|
|
||||||
SetOption('num_jobs', max(1, int(os.cpu_count()/2)))
|
SetOption('num_jobs', max(1, int(os.cpu_count()/(1 if "CI" in os.environ else 2))))
|
||||||
|
|
||||||
AddOption('--asan', action='store_true', help='turn on ASAN')
|
|
||||||
AddOption('--ubsan', action='store_true', help='turn on UBSan')
|
|
||||||
AddOption('--mutation', action='store_true', help='generate mutation-ready code')
|
|
||||||
AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line')
|
AddOption('--ccflags', action='store', type='string', default='', help='pass arbitrary flags over the command line')
|
||||||
AddOption('--verbose', action='store_true', default=False, help='show full build commands')
|
AddOption('--verbose', action='store_true', default=False, help='show full build commands')
|
||||||
|
release = not os.path.exists(File('#.gitattributes').abspath) # file absent on release branch, see release_files.py
|
||||||
AddOption('--minimal',
|
AddOption('--minimal',
|
||||||
action='store_false',
|
action='store_false',
|
||||||
dest='extras',
|
dest='extras',
|
||||||
default=os.path.exists(File('#.gitattributes').abspath), # minimal by default on release branch (where there's no LFS)
|
default=(not TICI and not release),
|
||||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||||
|
|
||||||
# Detect platform
|
# Detect platform
|
||||||
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
arch = "Darwin"
|
arch = "Darwin"
|
||||||
elif arch == "aarch64" and os.path.isfile('/TICI'):
|
elif arch == "aarch64" and TICI:
|
||||||
arch = "larch64"
|
arch = "larch64"
|
||||||
assert arch in [
|
assert arch in [
|
||||||
"larch64", # linux tici arm64
|
"larch64", # linux tici arm64
|
||||||
@@ -38,31 +40,61 @@ assert arch in [
|
|||||||
"Darwin", # macOS arm64 (x86 not supported)
|
"Darwin", # macOS arm64 (x86 not supported)
|
||||||
]
|
]
|
||||||
|
|
||||||
if arch != "larch64":
|
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd']
|
||||||
import bzip2
|
pkgs = [importlib.import_module(name) for name in pkg_names]
|
||||||
import capnproto
|
acados = pkgs[pkg_names.index('acados')]
|
||||||
import eigen
|
acados_include_dirs = [
|
||||||
import ffmpeg as ffmpeg_pkg
|
acados.INCLUDE_DIR,
|
||||||
import libjpeg
|
os.path.join(acados.INCLUDE_DIR, "blasfeo", "include"),
|
||||||
import libyuv
|
os.path.join(acados.INCLUDE_DIR, "hpipm", "include"),
|
||||||
import ncurses
|
]
|
||||||
import python3_dev
|
|
||||||
import zeromq
|
|
||||||
import zstd
|
# ***** enforce a whitelist of system libraries *****
|
||||||
pkgs = [bzip2, capnproto, eigen, ffmpeg_pkg, libjpeg, libyuv, ncurses, zeromq, zstd]
|
# this prevents silently relying on a 3rd party package,
|
||||||
py_include = python3_dev.INCLUDE_DIR
|
# e.g. apt-installed libusb. all libraries should either
|
||||||
else:
|
# be distributed with all Linux distros and macOS, or
|
||||||
# TODO: remove when AGNOS has our new vendor pkgs
|
# vendored in commaai/dependencies.
|
||||||
pkgs = []
|
allowed_system_libs = {
|
||||||
py_include = sysconfig.get_paths()['include']
|
"EGL", "GLESv2", "GL",
|
||||||
|
"Qt5Charts", "Qt5Core", "Qt5Gui", "Qt5Widgets",
|
||||||
|
"dl", "drm", "gbm", "m", "pthread",
|
||||||
|
}
|
||||||
|
|
||||||
|
def _resolve_lib(env, name):
|
||||||
|
for d in env.Flatten(env.get('LIBPATH', [])):
|
||||||
|
p = Dir(str(d)).abspath
|
||||||
|
for ext in ('.a', '.so', '.dylib'):
|
||||||
|
f = File(os.path.join(p, f'lib{name}{ext}'))
|
||||||
|
if f.exists() or f.has_builder():
|
||||||
|
return name
|
||||||
|
if name in allowed_system_libs:
|
||||||
|
return name
|
||||||
|
raise SCons.Errors.UserError(f"Unexpected non-vendored library '{name}'")
|
||||||
|
|
||||||
|
def _libflags(target, source, env, for_signature):
|
||||||
|
libs = []
|
||||||
|
lp = env.subst('$LIBLITERALPREFIX')
|
||||||
|
for lib in env.Flatten(env.get('LIBS', [])):
|
||||||
|
if isinstance(lib, str):
|
||||||
|
if os.sep in lib or lib.startswith('#'):
|
||||||
|
libs.append(File(lib))
|
||||||
|
elif lib.startswith('-') or (lp and lib.startswith(lp)):
|
||||||
|
libs.append(lib)
|
||||||
|
else:
|
||||||
|
libs.append(_resolve_lib(env, lib))
|
||||||
|
else:
|
||||||
|
libs.append(lib)
|
||||||
|
return _stripixes(env['LIBLINKPREFIX'], libs, env['LIBLINKSUFFIX'],
|
||||||
|
env['LIBPREFIXES'], env['LIBSUFFIXES'], env, env['LIBLITERALPREFIX'])
|
||||||
|
|
||||||
env = Environment(
|
env = Environment(
|
||||||
ENV={
|
ENV={
|
||||||
"PATH": os.environ['PATH'],
|
"PATH": os.environ['PATH'],
|
||||||
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
"PYTHONPATH": Dir("#").abspath,
|
||||||
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
"ACADOS_SOURCE_DIR": acados.DIR,
|
||||||
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
"ACADOS_PYTHON_INTERFACE_PATH": acados.TEMPLATE_DIR,
|
||||||
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
"TERA_PATH": acados.TERA_PATH
|
||||||
},
|
},
|
||||||
CCFLAGS=[
|
CCFLAGS=[
|
||||||
"-g",
|
"-g",
|
||||||
@@ -82,22 +114,14 @@ env = Environment(
|
|||||||
CPPPATH=[
|
CPPPATH=[
|
||||||
"#",
|
"#",
|
||||||
"#msgq",
|
"#msgq",
|
||||||
"#third_party",
|
acados_include_dirs,
|
||||||
"#third_party/json11",
|
|
||||||
"#third_party/linux/include",
|
|
||||||
"#third_party/acados/include",
|
|
||||||
"#third_party/acados/include/blasfeo/include",
|
|
||||||
"#third_party/acados/include/hpipm/include",
|
|
||||||
"#third_party/catch2/include",
|
|
||||||
[x.INCLUDE_DIR for x in pkgs],
|
[x.INCLUDE_DIR for x in pkgs],
|
||||||
],
|
],
|
||||||
LIBPATH=[
|
LIBPATH=[
|
||||||
"#common",
|
"#common",
|
||||||
"#msgq_repo",
|
"#msgq_repo",
|
||||||
"#third_party",
|
|
||||||
"#selfdrive/pandad",
|
"#selfdrive/pandad",
|
||||||
"#rednose/helpers",
|
"#rednose/helpers",
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
[x.LIB_DIR for x in pkgs],
|
[x.LIB_DIR for x in pkgs],
|
||||||
],
|
],
|
||||||
RPATH=[],
|
RPATH=[],
|
||||||
@@ -107,14 +131,14 @@ env = Environment(
|
|||||||
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
tools=["default", "cython", "compilation_db", "rednose_filter"],
|
||||||
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
||||||
)
|
)
|
||||||
|
if arch != "larch64":
|
||||||
|
env['_LIBFLAGS'] = _libflags
|
||||||
|
|
||||||
# Arch-specific flags and paths
|
# Arch-specific flags and paths
|
||||||
if arch == "larch64":
|
if arch == "larch64":
|
||||||
env["CC"] = "clang"
|
env["CC"] = "clang"
|
||||||
env["CXX"] = "clang++"
|
env["CXX"] = "clang++"
|
||||||
env.Append(LIBPATH=[
|
env.Append(LIBPATH=[
|
||||||
"/usr/local/lib",
|
|
||||||
"/system/vendor/lib64",
|
|
||||||
"/usr/lib/aarch64-linux-gnu",
|
"/usr/lib/aarch64-linux-gnu",
|
||||||
])
|
])
|
||||||
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57", "-DQCOM2"]
|
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57", "-DQCOM2"]
|
||||||
@@ -126,19 +150,6 @@ elif arch == "Darwin":
|
|||||||
])
|
])
|
||||||
env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
else:
|
|
||||||
env.Append(LIBPATH=[
|
|
||||||
"/usr/lib",
|
|
||||||
"/usr/local/lib",
|
|
||||||
])
|
|
||||||
|
|
||||||
# Sanitizers and extra CCFLAGS from CLI
|
|
||||||
if GetOption('asan'):
|
|
||||||
env.Append(CCFLAGS=["-fsanitize=address", "-fno-omit-frame-pointer"])
|
|
||||||
env.Append(LINKFLAGS=["-fsanitize=address"])
|
|
||||||
elif GetOption('ubsan'):
|
|
||||||
env.Append(CCFLAGS=["-fsanitize=undefined"])
|
|
||||||
env.Append(LINKFLAGS=["-fsanitize=undefined"])
|
|
||||||
|
|
||||||
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
||||||
if _extra_cc:
|
if _extra_cc:
|
||||||
@@ -164,19 +175,9 @@ if not GetOption('verbose'):
|
|||||||
):
|
):
|
||||||
env[f"{action}COMSTR"] = f" [{short}] $TARGET"
|
env[f"{action}COMSTR"] = f" [{short}] $TARGET"
|
||||||
|
|
||||||
# progress output
|
|
||||||
node_interval = 5
|
|
||||||
node_count = 0
|
|
||||||
def progress_function(node):
|
|
||||||
global node_count
|
|
||||||
node_count += node_interval
|
|
||||||
sys.stderr.write("progress: %d\n" % node_count)
|
|
||||||
if os.environ.get('SCONS_PROGRESS'):
|
|
||||||
Progress(progress_function, interval=node_interval)
|
|
||||||
|
|
||||||
# ********** Cython build environment **********
|
# ********** Cython build environment **********
|
||||||
envCython = env.Clone()
|
envCython = env.Clone()
|
||||||
envCython["CPPPATH"] += [py_include, np.get_include()]
|
envCython["CPPPATH"] += [sysconfig.get_paths()['include'], np.get_include()]
|
||||||
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-cpp", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
envCython["CCFLAGS"] += ["-Wno-#warnings", "-Wno-cpp", "-Wno-shadow", "-Wno-deprecated-declarations"]
|
||||||
envCython["CCFLAGS"].remove("-Werror")
|
envCython["CCFLAGS"].remove("-Werror")
|
||||||
|
|
||||||
@@ -189,14 +190,24 @@ else:
|
|||||||
np_version = SCons.Script.Value(np.__version__)
|
np_version = SCons.Script.Value(np.__version__)
|
||||||
Export('envCython', 'np_version')
|
Export('envCython', 'np_version')
|
||||||
|
|
||||||
Export('env', 'arch')
|
Export('env', 'arch', 'acados', 'release')
|
||||||
|
|
||||||
# Setup cache dir
|
# Setup cache dir
|
||||||
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
||||||
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
||||||
|
cache_size_limit = 4e9 if "CI" in os.environ else 2e9
|
||||||
CacheDir(cache_dir)
|
CacheDir(cache_dir)
|
||||||
Clean(["."], cache_dir)
|
Clean(["."], cache_dir)
|
||||||
|
|
||||||
|
def prune_cache_dir(target=None, source=None, env=None):
|
||||||
|
cache_files = sorted((os.path.join(root, f) for root, _, files in os.walk(cache_dir) for f in files), key=os.path.getmtime)
|
||||||
|
cache_size = sum(os.path.getsize(f) for f in cache_files)
|
||||||
|
for f in cache_files:
|
||||||
|
if cache_size < cache_size_limit:
|
||||||
|
break
|
||||||
|
cache_size -= os.path.getsize(f)
|
||||||
|
os.unlink(f)
|
||||||
|
|
||||||
# ********** start building stuff **********
|
# ********** start building stuff **********
|
||||||
|
|
||||||
# Build common module
|
# Build common module
|
||||||
@@ -210,7 +221,6 @@ Export('common')
|
|||||||
env_swaglog = env.Clone()
|
env_swaglog = env.Clone()
|
||||||
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
|
||||||
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
|
||||||
SConscript(['opendbc_repo/SConscript'], exports={'env': env_swaglog})
|
|
||||||
|
|
||||||
SConscript(['cereal/SConscript'])
|
SConscript(['cereal/SConscript'])
|
||||||
|
|
||||||
@@ -233,15 +243,59 @@ SConscript([
|
|||||||
if arch == "larch64":
|
if arch == "larch64":
|
||||||
SConscript(['system/camerad/SConscript'])
|
SConscript(['system/camerad/SConscript'])
|
||||||
|
|
||||||
# Build openpilot
|
# Build selfdrive
|
||||||
SConscript(['third_party/SConscript'])
|
SConscript([
|
||||||
|
'selfdrive/pandad/SConscript',
|
||||||
SConscript(['selfdrive/SConscript'])
|
'selfdrive/controls/lib/lateral_mpc_lib/SConscript',
|
||||||
|
'selfdrive/controls/lib/longitudinal_mpc_lib/SConscript',
|
||||||
|
'selfdrive/locationd/SConscript',
|
||||||
|
'selfdrive/modeld/SConscript',
|
||||||
|
'selfdrive/ui/SConscript',
|
||||||
|
])
|
||||||
|
|
||||||
SConscript(['sunnypilot/SConscript'])
|
SConscript(['sunnypilot/SConscript'])
|
||||||
|
|
||||||
if Dir('#tools/cabana/').exists() and arch != "larch64":
|
# Build desktop-only tools
|
||||||
SConscript(['tools/cabana/SConscript'])
|
if GetOption('extras') and arch != "larch64":
|
||||||
|
SConscript([
|
||||||
|
'tools/replay/SConscript',
|
||||||
|
'tools/cabana/SConscript',
|
||||||
|
'tools/jotpluggler/SConscript',
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
env.CompilationDatabase('compile_commands.json')
|
env.CompilationDatabase('compile_commands.json')
|
||||||
|
|
||||||
|
# progress output
|
||||||
|
def count_scons_nodes(nodes):
|
||||||
|
seen = set()
|
||||||
|
stack = list(nodes)
|
||||||
|
|
||||||
|
while stack:
|
||||||
|
node = stack.pop().disambiguate()
|
||||||
|
if node in seen:
|
||||||
|
continue
|
||||||
|
seen.add(node)
|
||||||
|
executor = node.get_executor()
|
||||||
|
if executor is not None:
|
||||||
|
stack += executor.get_all_prerequisites() + executor.get_all_children()
|
||||||
|
|
||||||
|
return len(seen)
|
||||||
|
|
||||||
|
progress_interval = 5
|
||||||
|
progress_count = 0
|
||||||
|
progress_total = max(1, count_scons_nodes(env.arg2nodes(BUILD_TARGETS or [Dir('.')], env.fs.Entry)))
|
||||||
|
|
||||||
|
def progress_function(node):
|
||||||
|
global progress_count
|
||||||
|
if progress_count >= progress_total:
|
||||||
|
return
|
||||||
|
progress_count = min(progress_count + progress_interval, progress_total)
|
||||||
|
progress = round(100. * progress_count / progress_total, 1)
|
||||||
|
sys.stderr.write("\rBuilding: %5.1f%%" % progress if sys.stderr.isatty() else "progress: %.1f\n" % progress)
|
||||||
|
if progress == 100. and sys.stderr.isatty():
|
||||||
|
sys.stderr.write("\n")
|
||||||
|
sys.stderr.flush()
|
||||||
|
|
||||||
|
Progress(progress_function, interval=progress_interval)
|
||||||
|
AddPostAction(BUILD_TARGETS or [Dir('.')], prune_cache_dir)
|
||||||
|
|||||||
+1
-1
@@ -4,7 +4,7 @@ cereal_dir = Dir('.')
|
|||||||
gen_dir = Dir('gen')
|
gen_dir = Dir('gen')
|
||||||
|
|
||||||
# Build cereal
|
# Build cereal
|
||||||
schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp', 'custom.capnp']
|
schema_files = ['log.capnp', 'car.capnp', 'deprecated.capnp', 'custom.capnp']
|
||||||
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
||||||
schema_files,
|
schema_files,
|
||||||
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
||||||
|
|||||||
@@ -137,10 +137,16 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
|
|||||||
eta @2 :UInt32;
|
eta @2 :UInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Chunk {
|
||||||
|
fileName @0 :Text;
|
||||||
|
sha256 @1 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
struct Artifact {
|
struct Artifact {
|
||||||
fileName @0 :Text;
|
fileName @0 :Text;
|
||||||
downloadUri @1 :DownloadUri;
|
downloadUri @1 :DownloadUri;
|
||||||
downloadProgress @2 :DownloadProgress;
|
downloadProgress @2 :DownloadProgress;
|
||||||
|
chunks @3 :List(Chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Model {
|
struct Model {
|
||||||
@@ -154,6 +160,8 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
|
|||||||
vision @2;
|
vision @2;
|
||||||
policy @3;
|
policy @3;
|
||||||
offPolicy @4;
|
offPolicy @4;
|
||||||
|
onPolicy @5;
|
||||||
|
chunked @6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ $Cxx.namespace("cereal");
|
|||||||
|
|
||||||
@0x80ef1ec4889c2a63;
|
@0x80ef1ec4889c2a63;
|
||||||
|
|
||||||
# legacy.capnp: a home for deprecated structs
|
# deprecated.capnp: a home for deprecated structs
|
||||||
|
|
||||||
struct LogRotate @0x9811e1f38f62f2d1 {
|
struct LogRotate @0x9811e1f38f62f2d1 {
|
||||||
segmentNum @0 :Int32;
|
segmentNum @0 :Int32;
|
||||||
@@ -571,4 +571,219 @@ struct LidarPts @0xe3d6685d4e9d8f7a {
|
|||||||
pkt @4 :Data;
|
pkt @4 :Data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct LiveTracksDEPRECATED @0xb16f60103159415a {
|
||||||
|
trackId @0 :Int32;
|
||||||
|
dRel @1 :Float32;
|
||||||
|
yRel @2 :Float32;
|
||||||
|
vRel @3 :Float32;
|
||||||
|
aRel @4 :Float32;
|
||||||
|
timeStamp @5 :Float32;
|
||||||
|
status @6 :Float32;
|
||||||
|
currentTime @7 :Float32;
|
||||||
|
stationary @8 :Bool;
|
||||||
|
oncoming @9 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveMpcData @0x92a5e332a85f32a0 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
psi @2 :List(Float32);
|
||||||
|
curvature @3 :List(Float32);
|
||||||
|
qpIterations @4 :UInt32;
|
||||||
|
calculationTime @5 :UInt64;
|
||||||
|
cost @6 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LiveLongitudinalMpcData @0xe7e17c434f865ae2 {
|
||||||
|
xEgo @0 :List(Float32);
|
||||||
|
vEgo @1 :List(Float32);
|
||||||
|
aEgo @2 :List(Float32);
|
||||||
|
xLead @3 :List(Float32);
|
||||||
|
vLead @4 :List(Float32);
|
||||||
|
aLead @5 :List(Float32);
|
||||||
|
aLeadTau @6 :Float32; # lead accel time constant
|
||||||
|
qpIterations @7 :UInt32;
|
||||||
|
mpcId @8 :UInt32;
|
||||||
|
calculationTime @9 :UInt64;
|
||||||
|
cost @10 :Float64;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DriverStateDEPRECATED @0xb83c6cc593ed0a00 {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
modelExecutionTime @14 :Float32;
|
||||||
|
dspExecutionTime @16 :Float32;
|
||||||
|
rawPredictions @15 :Data;
|
||||||
|
|
||||||
|
faceOrientation @3 :List(Float32);
|
||||||
|
facePosition @4 :List(Float32);
|
||||||
|
faceProb @5 :Float32;
|
||||||
|
leftEyeProb @6 :Float32;
|
||||||
|
rightEyeProb @7 :Float32;
|
||||||
|
leftBlinkProb @8 :Float32;
|
||||||
|
rightBlinkProb @9 :Float32;
|
||||||
|
faceOrientationStd @11 :List(Float32);
|
||||||
|
facePositionStd @12 :List(Float32);
|
||||||
|
sunglassesProb @13 :Float32;
|
||||||
|
poorVision @17 :Float32;
|
||||||
|
partialFace @18 :Float32;
|
||||||
|
distractedPose @19 :Float32;
|
||||||
|
distractedEyes @20 :Float32;
|
||||||
|
eyesOnRoad @21 :Float32;
|
||||||
|
phoneUse @22 :Float32;
|
||||||
|
occludedProb @23 :Float32;
|
||||||
|
|
||||||
|
readyProb @24 :List(Float32);
|
||||||
|
notReadyProb @25 :List(Float32);
|
||||||
|
|
||||||
|
irPwrDEPRECATED @10 :Float32;
|
||||||
|
descriptorDEPRECATED @1 :List(Float32);
|
||||||
|
stdDEPRECATED @2 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NavModelData @0xac3de5c437be057a {
|
||||||
|
frameId @0 :UInt32;
|
||||||
|
locationMonoTime @6 :UInt64;
|
||||||
|
modelExecutionTime @1 :Float32;
|
||||||
|
dspExecutionTime @2 :Float32;
|
||||||
|
features @3 :List(Float32);
|
||||||
|
# predicted future position
|
||||||
|
position @4 :XYData;
|
||||||
|
desirePrediction @5 :List(Float32);
|
||||||
|
|
||||||
|
# All SI units and in device frame
|
||||||
|
struct XYData @0xbe09e615b2507e26 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
xStd @2 :List(Float32);
|
||||||
|
yStd @3 :List(Float32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidBuildInfo @0xfe2919d5c21f426c {
|
||||||
|
board @0 :Text;
|
||||||
|
bootloader @1 :Text;
|
||||||
|
brand @2 :Text;
|
||||||
|
device @3 :Text;
|
||||||
|
display @4 :Text;
|
||||||
|
fingerprint @5 :Text;
|
||||||
|
hardware @6 :Text;
|
||||||
|
host @7 :Text;
|
||||||
|
id @8 :Text;
|
||||||
|
manufacturer @9 :Text;
|
||||||
|
model @10 :Text;
|
||||||
|
product @11 :Text;
|
||||||
|
radioVersion @12 :Text;
|
||||||
|
serial @13 :Text;
|
||||||
|
supportedAbis @14 :List(Text);
|
||||||
|
tags @15 :Text;
|
||||||
|
time @16 :Int64;
|
||||||
|
type @17 :Text;
|
||||||
|
user @18 :Text;
|
||||||
|
|
||||||
|
versionCodename @19 :Text;
|
||||||
|
versionRelease @20 :Text;
|
||||||
|
versionSdk @21 :Int32;
|
||||||
|
versionSecurityPatch @22 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidSensor @0x9b513b93a887dbcd {
|
||||||
|
id @0 :Int32;
|
||||||
|
name @1 :Text;
|
||||||
|
vendor @2 :Text;
|
||||||
|
version @3 :Int32;
|
||||||
|
handle @4 :Int32;
|
||||||
|
type @5 :Int32;
|
||||||
|
maxRange @6 :Float32;
|
||||||
|
resolution @7 :Float32;
|
||||||
|
power @8 :Float32;
|
||||||
|
minDelay @9 :Int32;
|
||||||
|
fifoReservedEventCount @10 :UInt32;
|
||||||
|
fifoMaxEventCount @11 :UInt32;
|
||||||
|
stringType @12 :Text;
|
||||||
|
maxDelay @13 :Int32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct IosBuildInfo @0xd97e3b28239f5580 {
|
||||||
|
appVersion @0 :Text;
|
||||||
|
appBuild @1 :UInt32;
|
||||||
|
osVersion @2 :Text;
|
||||||
|
deviceModel @3 :Text;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum FrameTypeDEPRECATED @0xa37f0d8558e193fd {
|
||||||
|
unknown @0;
|
||||||
|
neo @1;
|
||||||
|
chffrAndroid @2;
|
||||||
|
front @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AndroidCaptureResult @0xbcc3efbac41d2048 {
|
||||||
|
sensitivity @0 :Int32;
|
||||||
|
frameDuration @1 :Int64;
|
||||||
|
exposureTime @2 :Int64;
|
||||||
|
rollingShutterSkew @3 :UInt64;
|
||||||
|
colorCorrectionTransform @4 :List(Int32);
|
||||||
|
colorCorrectionGains @5 :List(Float32);
|
||||||
|
displayRotation @6 :Int8;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UsbPowerModeDEPRECATED @0xa8883583b32c9877 {
|
||||||
|
none @0;
|
||||||
|
client @1;
|
||||||
|
cdp @2;
|
||||||
|
dcp @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralINDIState @0x939463348632375e {
|
||||||
|
active @0 :Bool;
|
||||||
|
steeringAngleDeg @1 :Float32;
|
||||||
|
steeringRateDeg @2 :Float32;
|
||||||
|
steeringAccelDeg @3 :Float32;
|
||||||
|
rateSetPoint @4 :Float32;
|
||||||
|
accelSetPoint @5 :Float32;
|
||||||
|
accelError @6 :Float32;
|
||||||
|
delayedOutput @7 :Float32;
|
||||||
|
delta @8 :Float32;
|
||||||
|
output @9 :Float32;
|
||||||
|
saturated @10 :Bool;
|
||||||
|
steeringAngleDesiredDeg @11 :Float32;
|
||||||
|
steeringRateDesiredDeg @12 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralLQRState @0x9024e2d790c82ade {
|
||||||
|
active @0 :Bool;
|
||||||
|
steeringAngleDeg @1 :Float32;
|
||||||
|
i @2 :Float32;
|
||||||
|
output @3 :Float32;
|
||||||
|
lqrOutput @4 :Float32;
|
||||||
|
saturated @5 :Bool;
|
||||||
|
steeringAngleDesiredDeg @6 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralCurvatureState @0xad9d8095c06f7c61 {
|
||||||
|
active @0 :Bool;
|
||||||
|
actualCurvature @1 :Float32;
|
||||||
|
desiredCurvature @2 :Float32;
|
||||||
|
error @3 :Float32;
|
||||||
|
p @4 :Float32;
|
||||||
|
i @5 :Float32;
|
||||||
|
f @6 :Float32;
|
||||||
|
output @7 :Float32;
|
||||||
|
saturated @8 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct LateralPlannerSolution @0x84caeca5a6b4acfe {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
yaw @2 :List(Float32);
|
||||||
|
yawRate @3 :List(Float32);
|
||||||
|
xStd @4 :List(Float32);
|
||||||
|
yStd @5 :List(Float32);
|
||||||
|
yawStd @6 :List(Float32);
|
||||||
|
yawRateStd @7 :List(Float32);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct GpsTrajectory @0x8cfeb072f5301000 {
|
||||||
|
x @0 :List(Float32);
|
||||||
|
y @1 :List(Float32);
|
||||||
|
}
|
||||||
+398
-475
File diff suppressed because it is too large
Load Diff
@@ -259,11 +259,11 @@ class PubMaster:
|
|||||||
self.sock[s].send(dat)
|
self.sock[s].send(dat)
|
||||||
|
|
||||||
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
||||||
for _ in range(int(timeout*(1./dt))):
|
try:
|
||||||
if self.sock[s].all_readers_updated():
|
self.sock[s].wait_for_readers(timeout=timeout, interval=dt)
|
||||||
return True
|
return True
|
||||||
time.sleep(dt)
|
except TimeoutError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def all_readers_updated(self, s: str) -> bool:
|
def all_readers_updated(self, s: str) -> bool:
|
||||||
return self.sock[s].all_readers_updated() # type: ignore
|
return self.sock[s].all_readers_updated()
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ def zmq_sleep(t=1):
|
|||||||
|
|
||||||
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
||||||
def random_carstate():
|
def random_carstate():
|
||||||
fields = ["vEgo", "aEgo", "brake", "steeringAngleDeg"]
|
fields = ["vEgo", "aEgo", "steeringTorque", "steeringAngleDeg"]
|
||||||
msg = messaging.new_message("carState")
|
msg = messaging.new_message("carState")
|
||||||
cs = msg.carState
|
cs = msg.carState
|
||||||
for f in fields:
|
for f in fields:
|
||||||
|
|||||||
@@ -1,222 +1,256 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
"""Schema-level cereal compat check between sunnypilot and upstream openpilot.
|
||||||
|
|
||||||
|
Rules (per struct matched across sides by typeId):
|
||||||
|
R1 shared ordinal must reference the same type.
|
||||||
|
R2 sunnypilot-only ordinal in a union -> FAIL (unknown discriminant upstream).
|
||||||
|
R3 sunnypilot-only ordinal on a regular field -> OK (additive struct evolution).
|
||||||
|
R4 upstream-only ordinal -> OK.
|
||||||
|
R5 sunnypilot-only struct referenced via an upstream-shared field -> FAIL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import json
|
||||||
|
import os
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, List, Tuple
|
from typing import Any
|
||||||
|
|
||||||
DEBUG = False
|
NO_DISCRIMINANT = 0xFFFF
|
||||||
|
|
||||||
|
|
||||||
def print_debug(string: str) -> None:
|
def hex_id(value: int) -> str:
|
||||||
if DEBUG:
|
return f"0x{value:016x}"
|
||||||
print(string)
|
|
||||||
|
|
||||||
|
|
||||||
def create_schema_instance(struct: Any, prop: Tuple[str, Any]) -> Any:
|
def encode_type(type_node: Any) -> dict:
|
||||||
"""
|
which = type_node.which()
|
||||||
Create a new instance of a schema type, handling different field types.
|
if which == "struct":
|
||||||
|
return {"kind": "struct", "typeId": hex_id(type_node.struct.typeId)}
|
||||||
Args:
|
if which == "enum":
|
||||||
struct: The Cap'n Proto schema structure
|
return {"kind": "enum", "typeId": hex_id(type_node.enum.typeId)}
|
||||||
prop: A tuple containing the field name and field metadata
|
if which == "interface":
|
||||||
|
return {"kind": "interface", "typeId": hex_id(type_node.interface.typeId)}
|
||||||
Returns:
|
if which == "list":
|
||||||
A new initialized schema instance
|
return {"kind": "list", "element": encode_type(type_node.list.elementType)}
|
||||||
"""
|
if which == "anyPointer":
|
||||||
struct_instance = struct.new_message()
|
return {"kind": "anyPointer"}
|
||||||
field_name, field_metadata = prop
|
return {"kind": which}
|
||||||
|
|
||||||
try:
|
|
||||||
field_type = field_metadata.proto.slot.type.which()
|
|
||||||
|
|
||||||
# Initialize different types of fields
|
|
||||||
if field_type in ('list', 'text', 'data'):
|
|
||||||
struct_instance.init(field_name, 1)
|
|
||||||
print_debug(f"Initialized list/text/data field: {field_name}")
|
|
||||||
elif field_type in ('struct', 'object'):
|
|
||||||
struct_instance.init(field_name)
|
|
||||||
print_debug(f"Initialized struct/object field: {field_name}")
|
|
||||||
|
|
||||||
return struct_instance
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error creating instance for {field_name}: {e}")
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
def get_schema_fields(schema_struct: Any) -> List[Tuple[str, Any]]:
|
def encode_field(name: str, field: Any) -> dict:
|
||||||
"""
|
proto = field.proto
|
||||||
Retrieve all fields from a given schema structure.
|
ordinal = proto.ordinal.explicit if proto.ordinal.which() == "explicit" else None
|
||||||
|
discriminant = proto.discriminantValue if proto.discriminantValue != NO_DISCRIMINANT else None
|
||||||
|
|
||||||
Args:
|
if proto.which() == "group":
|
||||||
schema_struct: The Cap'n Proto schema structure
|
type_desc = {"kind": "group", "typeId": hex_id(proto.group.typeId)}
|
||||||
|
else:
|
||||||
|
type_desc = encode_type(proto.slot.type)
|
||||||
|
|
||||||
Returns:
|
return {
|
||||||
A list of field names and their metadata
|
"name": name,
|
||||||
"""
|
"ordinal": ordinal,
|
||||||
try:
|
"discriminant": discriminant,
|
||||||
# Get all fields from the schema
|
"type": type_desc,
|
||||||
schema_fields = list(schema_struct.schema.fields.items())
|
}
|
||||||
|
|
||||||
print_debug("Discovered schema fields:")
|
|
||||||
for field_name, field_metadata in schema_fields:
|
|
||||||
print_debug(f"- {field_name}")
|
|
||||||
|
|
||||||
return schema_fields
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error retrieving schema fields: {e}")
|
|
||||||
return []
|
|
||||||
|
|
||||||
|
|
||||||
def generate_schema_instances(schema_struct: Any) -> List[Any]:
|
def encode_struct(schema: Any) -> dict:
|
||||||
"""
|
node = schema.node
|
||||||
Generate instances for all fields in a given schema.
|
return {
|
||||||
|
"typeId": hex_id(node.id),
|
||||||
Args:
|
"displayName": node.displayName,
|
||||||
schema_struct: The Cap'n Proto schema structure
|
"hasUnion": node.struct.discriminantCount > 0,
|
||||||
|
"fields": [encode_field(name, field) for name, field in schema.fields.items()],
|
||||||
Returns:
|
}
|
||||||
A list of schema instances
|
|
||||||
"""
|
|
||||||
schema_fields = get_schema_fields(schema_struct)
|
|
||||||
instances = []
|
|
||||||
|
|
||||||
for field_prop in schema_fields:
|
|
||||||
try:
|
|
||||||
instance = create_schema_instance(schema_struct, field_prop)
|
|
||||||
if instance is not None:
|
|
||||||
instances.append(instance)
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Skipping field due to error: {e}")
|
|
||||||
|
|
||||||
print(f"Generated {len(instances)} schema instances")
|
|
||||||
return instances
|
|
||||||
|
|
||||||
|
|
||||||
def persist_instances(instances: List[Any], filename: str) -> None:
|
def _child_struct_schema(field: Any) -> Any:
|
||||||
"""
|
proto = field.proto
|
||||||
Write schema instances to a binary file.
|
if proto.which() == "group":
|
||||||
|
return field.schema
|
||||||
Args:
|
type_node = proto.slot.type
|
||||||
instances: List of schema instances
|
which = type_node.which()
|
||||||
filename: Output file path
|
if which == "struct":
|
||||||
"""
|
return field.schema
|
||||||
try:
|
if which == "list":
|
||||||
with open(filename, 'wb') as f:
|
container = field.schema
|
||||||
for instance in instances:
|
element_type = type_node.list.elementType
|
||||||
f.write(instance.to_bytes())
|
while element_type.which() == "list":
|
||||||
|
container = container.elementType
|
||||||
print(f"Successfully wrote {len(instances)} instances to {filename}")
|
element_type = element_type.list.elementType
|
||||||
|
if element_type.which() == "struct":
|
||||||
except Exception as e:
|
return container.elementType
|
||||||
print(f"Error persisting instances: {e}")
|
return None
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def read_instances(filename: str, schema_type: Any) -> List[Any]:
|
def collect_schema(root: Any) -> dict[str, dict]:
|
||||||
"""
|
structs: dict[str, dict] = {}
|
||||||
Read schema instances from a binary file.
|
stack = [root]
|
||||||
|
while stack:
|
||||||
Args:
|
schema = stack.pop()
|
||||||
filename: Input file path
|
type_id = hex_id(schema.node.id)
|
||||||
schema_type: The schema type to use for reading
|
if type_id in structs:
|
||||||
|
continue
|
||||||
Returns:
|
structs[type_id] = encode_struct(schema)
|
||||||
A list of read schema instances
|
for _name, field in schema.fields.items():
|
||||||
"""
|
try:
|
||||||
try:
|
child = _child_struct_schema(field)
|
||||||
with open(filename, 'rb') as f:
|
except Exception:
|
||||||
data = f.read()
|
child = None
|
||||||
|
if child is not None:
|
||||||
instances = list(schema_type.read_multiple_bytes(data))
|
stack.append(child)
|
||||||
|
return structs
|
||||||
print(f"Read {len(instances)} instances from {filename}")
|
|
||||||
return instances
|
|
||||||
|
|
||||||
except Exception as e:
|
|
||||||
print(f"Error reading instances: {e}")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
def compare_schemas(original_instances: List[Any], read_instances: List[Any]) -> bool:
|
def load_log(cereal_dir: str) -> Any:
|
||||||
"""
|
import capnp
|
||||||
Compare original and read-back instances to detect potential breaking changes.
|
cereal_dir = os.path.abspath(cereal_dir)
|
||||||
|
capnp.remove_import_hook()
|
||||||
|
return capnp.load(os.path.join(cereal_dir, "log.capnp"), imports=[cereal_dir])
|
||||||
|
|
||||||
Args:
|
|
||||||
original_instances: List of originally generated instances
|
|
||||||
read_instances: List of instances read back from file
|
|
||||||
|
|
||||||
Returns:
|
def dump_schema(cereal_dir: str, path: str) -> None:
|
||||||
Boolean indicating whether schemas appear compatible
|
log = load_log(cereal_dir)
|
||||||
"""
|
payload = {
|
||||||
if len(original_instances) != len(read_instances):
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
print("❌ Schema Compatibility Warning: Instance count mismatch")
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
with open(path, "w", encoding="utf-8") as handle:
|
||||||
|
json.dump(payload, handle, indent=2, sort_keys=True)
|
||||||
|
print(f"wrote schema dump with {len(payload['structs'])} structs to {path}")
|
||||||
|
|
||||||
|
|
||||||
|
def types_equal(a: dict, b: dict) -> bool:
|
||||||
|
if a.get("kind") != b.get("kind"):
|
||||||
return False
|
return False
|
||||||
|
kind = a["kind"]
|
||||||
compatible = True
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
for struct in read_instances:
|
return a.get("typeId") == b.get("typeId")
|
||||||
try:
|
if kind == "list":
|
||||||
getattr(struct, struct.which()) # Attempting to access the field to validate readability
|
return types_equal(a["element"], b["element"])
|
||||||
except Exception as e:
|
return True
|
||||||
print(f"❌ Structural change detected: {struct.which()} is not readable.\nFull error: {e}")
|
|
||||||
compatible = False
|
|
||||||
|
|
||||||
return compatible
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def type_repr(t: dict) -> str:
|
||||||
"""
|
kind = t.get("kind", "?")
|
||||||
CLI entry point for schema compatibility testing.
|
if kind in ("struct", "enum", "interface", "group"):
|
||||||
"""
|
return f"{kind}({t.get('typeId')})"
|
||||||
# Setup argument parser
|
if kind == "list":
|
||||||
|
return f"list<{type_repr(t['element'])}>"
|
||||||
|
return kind
|
||||||
|
|
||||||
|
|
||||||
|
def field_is_union_variant(field: dict) -> bool:
|
||||||
|
return field.get("discriminant") is not None
|
||||||
|
|
||||||
|
|
||||||
|
def index_fields_by_ordinal(struct: dict) -> dict[int, dict]:
|
||||||
|
indexed: dict[int, dict] = {}
|
||||||
|
for field in struct["fields"]:
|
||||||
|
ordinal = field.get("ordinal")
|
||||||
|
if ordinal is None:
|
||||||
|
continue
|
||||||
|
indexed[ordinal] = field
|
||||||
|
return indexed
|
||||||
|
|
||||||
|
|
||||||
|
def compare(sunnypilot_dump: dict, upstream_dump: dict) -> list[str]:
|
||||||
|
violations: list[str] = []
|
||||||
|
sunnypilot_structs: dict[str, dict] = sunnypilot_dump["structs"]
|
||||||
|
upstream_structs: dict[str, dict] = upstream_dump["structs"]
|
||||||
|
|
||||||
|
sunnypilot_struct_referenced_from_shared: set[str] = set()
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
upstream_struct = upstream_structs.get(type_id)
|
||||||
|
if upstream_struct is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
sunnypilot_fields = index_fields_by_ordinal(sunnypilot_struct)
|
||||||
|
upstream_fields = index_fields_by_ordinal(upstream_struct)
|
||||||
|
display = sunnypilot_struct["displayName"]
|
||||||
|
|
||||||
|
for ordinal, sunnypilot_field in sunnypilot_fields.items():
|
||||||
|
upstream_field = upstream_fields.get(ordinal)
|
||||||
|
if upstream_field is None:
|
||||||
|
if field_is_union_variant(sunnypilot_field):
|
||||||
|
violations.append(
|
||||||
|
f"[R2] {display} @{ordinal} ('{sunnypilot_field['name']}', {type_repr(sunnypilot_field['type'])}): "
|
||||||
|
f"union variant not present upstream. upstream cannot parse this discriminant."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not types_equal(sunnypilot_field["type"], upstream_field["type"]):
|
||||||
|
violations.append(
|
||||||
|
f"[R1] {display} @{ordinal}: type mismatch. "
|
||||||
|
f"sunnypilot='{sunnypilot_field['name']}' {type_repr(sunnypilot_field['type'])} vs "
|
||||||
|
f"upstream='{upstream_field['name']}' {type_repr(upstream_field['type'])}."
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
cursor = sunnypilot_field["type"]
|
||||||
|
while cursor.get("kind") == "list":
|
||||||
|
cursor = cursor["element"]
|
||||||
|
if cursor.get("kind") in ("struct", "group", "interface") and cursor.get("typeId"):
|
||||||
|
sunnypilot_struct_referenced_from_shared.add(cursor["typeId"])
|
||||||
|
|
||||||
|
for type_id, sunnypilot_struct in sunnypilot_structs.items():
|
||||||
|
if type_id in upstream_structs:
|
||||||
|
continue
|
||||||
|
if type_id in sunnypilot_struct_referenced_from_shared:
|
||||||
|
violations.append(
|
||||||
|
f"[R5] struct {sunnypilot_struct['displayName']} ({type_id}) exists only on sunnypilot "
|
||||||
|
f"but is referenced from an upstream-shared field. upstream cannot resolve this type."
|
||||||
|
)
|
||||||
|
|
||||||
|
return violations
|
||||||
|
|
||||||
|
|
||||||
|
def load_peer(path: str) -> dict:
|
||||||
|
with open(path, "r", encoding="utf-8") as handle:
|
||||||
|
return json.load(handle)
|
||||||
|
|
||||||
|
|
||||||
|
def run_read(cereal_dir: str, peer_path: str) -> int:
|
||||||
|
log = load_log(cereal_dir)
|
||||||
|
peer_dump = load_peer(peer_path)
|
||||||
|
local_dump = {
|
||||||
|
"root": hex_id(log.Event.schema.node.id),
|
||||||
|
"structs": collect_schema(log.Event.schema),
|
||||||
|
}
|
||||||
|
violations = compare(sunnypilot_dump=peer_dump, upstream_dump=local_dump)
|
||||||
|
|
||||||
|
if not violations:
|
||||||
|
print("cereal compat OK: upstream openpilot can parse sunnypilot routes "
|
||||||
|
"(no leaked structs, no ordinal collisions).")
|
||||||
|
return 0
|
||||||
|
|
||||||
|
print(f"cereal compat FAIL: upstream openpilot would misparse sunnypilot routes "
|
||||||
|
f"({len(violations)} violation(s)):")
|
||||||
|
for v in violations:
|
||||||
|
print(f" {v}")
|
||||||
|
return 1
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> int:
|
||||||
parser = argparse.ArgumentParser(
|
parser = argparse.ArgumentParser(
|
||||||
description='Cap\'n Proto Schema Compatibility Testing Tool',
|
description="sunnypilot <-> upstream cereal compatibility validator (schema-level)."
|
||||||
epilog='Test schema compatibility by generating and reading back instances.'
|
|
||||||
)
|
)
|
||||||
|
mode = parser.add_mutually_exclusive_group(required=True)
|
||||||
# Add mutually exclusive group for generation or reading mode
|
mode.add_argument("-g", "--generate", action="store_true", help="dump local schema to JSON")
|
||||||
mode_group = parser.add_mutually_exclusive_group(required=True)
|
mode.add_argument("-r", "--read", action="store_true", help="load peer JSON and diff against local")
|
||||||
mode_group.add_argument('-g', '--generate', action='store_true',
|
parser.add_argument("-f", "--file", default="schema.json", help="JSON file path (default: schema.json)")
|
||||||
help='Generate schema instances')
|
parser.add_argument("--cereal-dir", required=True, help="path to cereal directory containing log.capnp")
|
||||||
mode_group.add_argument('-r', '--read', action='store_true',
|
|
||||||
help='Read and validate schema instances')
|
|
||||||
|
|
||||||
# Common arguments
|
|
||||||
parser.add_argument('-f', '--file',
|
|
||||||
default='schema_instances.bin',
|
|
||||||
help='Output/input binary file (default: schema_instances.bin)')
|
|
||||||
|
|
||||||
# Parse arguments
|
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
# Import the schema dynamically
|
|
||||||
try:
|
|
||||||
from cereal import log
|
|
||||||
schema_type = log.Event
|
|
||||||
except ImportError:
|
|
||||||
print("Error: Unable to import schema. Ensure 'cereal' is installed.")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
# Execute based on mode
|
|
||||||
if args.generate:
|
if args.generate:
|
||||||
print("🔧 Generating Schema Instances")
|
dump_schema(args.cereal_dir, args.file)
|
||||||
instances = generate_schema_instances(schema_type)
|
return 0
|
||||||
persist_instances(instances, args.file)
|
return run_read(args.cereal_dir, args.file)
|
||||||
print("✅ Instance generation complete")
|
|
||||||
|
|
||||||
elif args.read:
|
|
||||||
print("🔍 Reading and Validating Schema Instances")
|
|
||||||
generated_instances = generate_schema_instances(schema_type)
|
|
||||||
read_back_instances = read_instances(args.file, schema_type)
|
|
||||||
|
|
||||||
# Compare schemas
|
|
||||||
if compare_schemas(generated_instances, read_back_instances):
|
|
||||||
print("✅ Schema Compatibility: No breaking changes detected")
|
|
||||||
sys.exit(0)
|
|
||||||
else:
|
|
||||||
print("❌ Potential Schema Breaking Changes Detected")
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
sys.exit(main())
|
||||||
|
|||||||
+3
-12
@@ -24,10 +24,7 @@ _services: dict[str, tuple] = {
|
|||||||
# note: the "EncodeIdx" packets will still be in the log
|
# note: the "EncodeIdx" packets will still be in the log
|
||||||
"gyroscope": (True, 104., 104),
|
"gyroscope": (True, 104., 104),
|
||||||
"accelerometer": (True, 104., 104),
|
"accelerometer": (True, 104., 104),
|
||||||
"magnetometer": (True, 25.),
|
|
||||||
"lightSensor": (True, 100., 100),
|
|
||||||
"temperatureSensor": (True, 2., 200),
|
"temperatureSensor": (True, 2., 200),
|
||||||
"gpsNMEA": (True, 9.),
|
|
||||||
"deviceState": (True, 2., 1),
|
"deviceState": (True, 2., 1),
|
||||||
"touch": (True, 20., 1),
|
"touch": (True, 20., 1),
|
||||||
"can": (True, 100., 2053, QueueSize.BIG), # decimation gives ~3 msgs in a full segment
|
"can": (True, 100., 2053, QueueSize.BIG), # decimation gives ~3 msgs in a full segment
|
||||||
@@ -39,8 +36,8 @@ _services: dict[str, tuple] = {
|
|||||||
"roadEncodeIdx": (False, 20., 1),
|
"roadEncodeIdx": (False, 20., 1),
|
||||||
"liveTracks": (True, 20.),
|
"liveTracks": (True, 20.),
|
||||||
"sendcan": (True, 100., 139, QueueSize.MEDIUM),
|
"sendcan": (True, 100., 139, QueueSize.MEDIUM),
|
||||||
"logMessage": (True, 0.),
|
"logMessage": (True, 0., None, QueueSize.BIG),
|
||||||
"errorLogMessage": (True, 0., 1),
|
"errorLogMessage": (True, 0., 1, QueueSize.BIG),
|
||||||
"liveCalibration": (True, 4., 4),
|
"liveCalibration": (True, 4., 4),
|
||||||
"liveTorqueParameters": (True, 4., 1),
|
"liveTorqueParameters": (True, 4., 1),
|
||||||
"liveDelay": (True, 4., 1),
|
"liveDelay": (True, 4., 1),
|
||||||
@@ -49,13 +46,13 @@ _services: dict[str, tuple] = {
|
|||||||
"carControl": (True, 100., 10),
|
"carControl": (True, 100., 10),
|
||||||
"carOutput": (True, 100., 10),
|
"carOutput": (True, 100., 10),
|
||||||
"longitudinalPlan": (True, 20., 10),
|
"longitudinalPlan": (True, 20., 10),
|
||||||
|
"lateralManeuverPlan": (True, 20.),
|
||||||
"driverAssistance": (True, 20., 20),
|
"driverAssistance": (True, 20., 20),
|
||||||
"procLog": (True, 0.5, 15, QueueSize.BIG),
|
"procLog": (True, 0.5, 15, QueueSize.BIG),
|
||||||
"gpsLocationExternal": (True, 10., 10),
|
"gpsLocationExternal": (True, 10., 10),
|
||||||
"gpsLocation": (True, 1., 1),
|
"gpsLocation": (True, 1., 1),
|
||||||
"ubloxGnss": (True, 10.),
|
"ubloxGnss": (True, 10.),
|
||||||
"qcomGnss": (True, 2.),
|
"qcomGnss": (True, 2.),
|
||||||
"gnssMeasurements": (True, 10., 10),
|
|
||||||
"clocks": (True, 0.1, 1),
|
"clocks": (True, 0.1, 1),
|
||||||
"ubloxRaw": (True, 20.),
|
"ubloxRaw": (True, 20.),
|
||||||
"livePose": (True, 20., 4),
|
"livePose": (True, 20., 4),
|
||||||
@@ -74,10 +71,6 @@ _services: dict[str, tuple] = {
|
|||||||
"drivingModelData": (True, 20., 10),
|
"drivingModelData": (True, 20., 10),
|
||||||
"modelV2": (True, 20., None, QueueSize.BIG),
|
"modelV2": (True, 20., None, QueueSize.BIG),
|
||||||
"managerState": (True, 2., 1),
|
"managerState": (True, 2., 1),
|
||||||
"uploaderState": (True, 0., 1),
|
|
||||||
"navInstruction": (True, 1., 10),
|
|
||||||
"navRoute": (True, 0.),
|
|
||||||
"navThumbnail": (True, 0.),
|
|
||||||
"qRoadEncodeIdx": (False, 20.),
|
"qRoadEncodeIdx": (False, 20.),
|
||||||
"userBookmark": (True, 0., 1),
|
"userBookmark": (True, 0., 1),
|
||||||
"soundPressure": (True, 10., 10),
|
"soundPressure": (True, 10., 10),
|
||||||
@@ -113,8 +106,6 @@ _services: dict[str, tuple] = {
|
|||||||
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
|
||||||
"customReservedRawData0": (True, 0.),
|
"customReservedRawData0": (True, 0.),
|
||||||
"customReservedRawData1": (True, 0.),
|
|
||||||
"customReservedRawData2": (True, 0.),
|
|
||||||
}
|
}
|
||||||
SERVICE_LIST = {name: Service(*vals) for
|
SERVICE_LIST = {name: Service(*vals) for
|
||||||
idx, (name, vals) in enumerate(_services.items())}
|
idx, (name, vals) in enumerate(_services.items())}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
*.cpp
|
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
Import('env', 'envCython', 'arch')
|
Import('env', 'envCython')
|
||||||
|
|
||||||
common_libs = [
|
common_libs = [
|
||||||
'params.cc',
|
'params.cc',
|
||||||
|
|||||||
Regular → Executable
+20
-2
@@ -1,3 +1,5 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
import sys
|
||||||
import math
|
import math
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
@@ -10,10 +12,13 @@ def get_chunk_name(name, idx, num_chunks):
|
|||||||
def get_manifest_path(name):
|
def get_manifest_path(name):
|
||||||
return f"{name}.chunkmanifest"
|
return f"{name}.chunkmanifest"
|
||||||
|
|
||||||
def get_chunk_paths(path, file_size):
|
def _chunk_paths(path, num_chunks):
|
||||||
num_chunks = math.ceil(file_size / CHUNK_SIZE)
|
|
||||||
return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
|
return [get_manifest_path(path)] + [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
|
||||||
|
|
||||||
|
def get_chunk_targets(path, file_size):
|
||||||
|
num_chunks = math.ceil(file_size / CHUNK_SIZE)
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
|
||||||
def chunk_file(path, targets):
|
def chunk_file(path, targets):
|
||||||
manifest_path, *chunk_paths = targets
|
manifest_path, *chunk_paths = targets
|
||||||
with open(path, 'rb') as f:
|
with open(path, 'rb') as f:
|
||||||
@@ -26,6 +31,13 @@ def chunk_file(path, targets):
|
|||||||
Path(manifest_path).write_text(str(len(chunk_paths)))
|
Path(manifest_path).write_text(str(len(chunk_paths)))
|
||||||
os.remove(path)
|
os.remove(path)
|
||||||
|
|
||||||
|
def get_existing_chunks(path):
|
||||||
|
if os.path.isfile(path):
|
||||||
|
return [path]
|
||||||
|
if os.path.isfile(manifest := get_manifest_path(path)):
|
||||||
|
num_chunks = int(Path(manifest).read_text().strip())
|
||||||
|
return _chunk_paths(path, num_chunks)
|
||||||
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
def read_file_chunked(path):
|
def read_file_chunked(path):
|
||||||
manifest_path = get_manifest_path(path)
|
manifest_path = get_manifest_path(path)
|
||||||
@@ -35,3 +47,9 @@ def read_file_chunked(path):
|
|||||||
if os.path.isfile(path):
|
if os.path.isfile(path):
|
||||||
return Path(path).read_bytes()
|
return Path(path).read_bytes()
|
||||||
raise FileNotFoundError(path)
|
raise FileNotFoundError(path)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
path = sys.argv[1]
|
||||||
|
chunk_paths = get_chunk_targets(path, os.path.getsize(path))
|
||||||
|
chunk_file(path, chunk_paths)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ class BounceFilter(FirstOrderFilter):
|
|||||||
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
||||||
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
||||||
self.velocity.update(0.0)
|
self.velocity.update(0.0)
|
||||||
if abs(self.velocity.x) < 1e-5:
|
if abs(self.velocity.x) < 1e-3:
|
||||||
self.velocity.x = 0.0
|
self.velocity.x = 0.0
|
||||||
self.x += self.velocity.x
|
self.x += self.velocity.x
|
||||||
return self.x
|
return self.x
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
#define DEFAULT_MODEL "CD210 (Default)"
|
|
||||||
@@ -1,8 +1,13 @@
|
|||||||
|
import re
|
||||||
import sys
|
import sys
|
||||||
import pytest
|
import pytest
|
||||||
import inspect
|
import inspect
|
||||||
|
|
||||||
|
|
||||||
|
def _to_safe_name(s):
|
||||||
|
return re.sub(r"[^a-zA-Z0-9_]+", "_", str(s)).strip("_")
|
||||||
|
|
||||||
|
|
||||||
class parameterized:
|
class parameterized:
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def expand(cases):
|
def expand(cases):
|
||||||
@@ -34,7 +39,9 @@ def parameterized_class(attrs, input_list=None):
|
|||||||
def decorator(cls):
|
def decorator(cls):
|
||||||
globs = sys._getframe(1).f_globals
|
globs = sys._getframe(1).f_globals
|
||||||
for i, params in enumerate(params_list):
|
for i, params in enumerate(params_list):
|
||||||
name = f"{cls.__name__}_{i}"
|
# append sanitized string param values so pytest -k can filter by them
|
||||||
|
suffix = "_".join(filter(None, (_to_safe_name(v) for v in params.values() if isinstance(v, str))))
|
||||||
|
name = f"{cls.__name__}_{i}" + (f"_{suffix}" if suffix else "")
|
||||||
new_cls = type(name, (cls,), dict(params))
|
new_cls = type(name, (cls,), dict(params))
|
||||||
new_cls.__module__ = cls.__module__
|
new_cls.__module__ = cls.__module__
|
||||||
new_cls.__test__ = True # override inherited False so pytest collects this subclass
|
new_cls.__test__ = True # override inherited False so pytest collects this subclass
|
||||||
|
|||||||
+1
-1
@@ -14,6 +14,6 @@ if __name__ == "__main__":
|
|||||||
if len(sys.argv) == 3:
|
if len(sys.argv) == 3:
|
||||||
val = sys.argv[2]
|
val = sys.argv[2]
|
||||||
print(f"SET: {key} = {val}")
|
print(f"SET: {key} = {val}")
|
||||||
params.put(key, val)
|
params.put(key, val, block=True)
|
||||||
elif len(sys.argv) == 2:
|
elif len(sys.argv) == 2:
|
||||||
print(f"GET: {key} = {params.get(key)}")
|
print(f"GET: {key} = {params.get(key)}")
|
||||||
|
|||||||
@@ -80,8 +80,10 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
||||||
{"LiveParameters", {PERSISTENT, JSON}},
|
{"LiveParameters", {PERSISTENT, JSON}},
|
||||||
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
||||||
|
{"LivestreamEncoderBitrate", {CLEAR_ON_MANAGER_START | DONT_LOG, INT}},
|
||||||
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
||||||
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
||||||
|
{"LateralManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LongitudinalPersonality", {PERSISTENT | BACKUP, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
{"LongitudinalPersonality", {PERSISTENT | BACKUP, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
||||||
{"NetworkMetered", {PERSISTENT | BACKUP, BOOL}},
|
{"NetworkMetered", {PERSISTENT | BACKUP, BOOL}},
|
||||||
@@ -102,8 +104,6 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"OpenpilotEnabledToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
{"OpenpilotEnabledToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
|
||||||
{"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}},
|
|
||||||
{"PrimeType", {PERSISTENT, INT}},
|
{"PrimeType", {PERSISTENT, INT}},
|
||||||
{"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
|
{"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
@@ -131,6 +131,8 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
||||||
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"UsbGpuPresent", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
|
{"UsbGpuCompiled", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"Version", {PERSISTENT, STRING}},
|
{"Version", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
// --- sunnypilot params --- //
|
// --- sunnypilot params --- //
|
||||||
@@ -203,6 +205,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
// sunnylink params
|
// sunnylink params
|
||||||
{"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
|
{"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
{"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
|
{"ParamsVersion", {PERSISTENT, INT}},
|
||||||
{"SunnylinkCache_Roles", {PERSISTENT, STRING}},
|
{"SunnylinkCache_Roles", {PERSISTENT, STRING}},
|
||||||
{"SunnylinkCache_Users", {PERSISTENT, STRING}},
|
{"SunnylinkCache_Users", {PERSISTENT, STRING}},
|
||||||
{"SunnylinkDongleId", {PERSISTENT, STRING}},
|
{"SunnylinkDongleId", {PERSISTENT, STRING}},
|
||||||
@@ -271,7 +274,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
|||||||
{"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
|
{"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
|
{"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
|
{"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"TorqueControlTune", {PERSISTENT | BACKUP, FLOAT}},
|
{"TorqueControlTune", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
|
||||||
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
||||||
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
||||||
|
|||||||
+13
-18
@@ -142,33 +142,28 @@ cdef class Params:
|
|||||||
cdef ParamKeyType t = self.p.getKeyType(k)
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
||||||
|
|
||||||
def put(self, key, dat):
|
def put(self, key, dat, bool block = False):
|
||||||
"""
|
"""
|
||||||
Warning: This function blocks until the param is written to disk!
|
Warning: block=True blocks until the param is written to disk!
|
||||||
In very rare cases this can take over a second, and your code will hang.
|
In very rare cases this can take over a second, and your code will hang.
|
||||||
Use the put_nonblocking, put_bool_nonblocking in time sensitive code, but
|
Use block=False in time sensitive code, but in general try to avoid
|
||||||
in general try to avoid writing params as much as possible.
|
writing params as much as possible.
|
||||||
"""
|
"""
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
cdef string dat_bytes = self._put_cast(key, dat)
|
cdef string dat_bytes = self._put_cast(key, dat)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.put(k, dat_bytes)
|
if block:
|
||||||
|
self.p.put(k, dat_bytes)
|
||||||
|
else:
|
||||||
|
self.p.putNonBlocking(k, dat_bytes)
|
||||||
|
|
||||||
def put_bool(self, key, bool val):
|
def put_bool(self, key, bool val, bool block = False):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.putBool(k, val)
|
if block:
|
||||||
|
self.p.putBool(k, val)
|
||||||
def put_nonblocking(self, key, dat):
|
else:
|
||||||
cdef string k = self.check_key(key)
|
self.p.putBoolNonBlocking(k, val)
|
||||||
cdef string dat_bytes = self._put_cast(key, dat)
|
|
||||||
with nogil:
|
|
||||||
self.p.putNonBlocking(k, dat_bytes)
|
|
||||||
|
|
||||||
def put_bool_nonblocking(self, key, bool val):
|
|
||||||
cdef string k = self.check_key(key)
|
|
||||||
with nogil:
|
|
||||||
self.p.putBoolNonBlocking(k, val)
|
|
||||||
|
|
||||||
def remove(self, key):
|
def remove(self, key):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
|
|||||||
@@ -28,6 +28,11 @@ class Priority:
|
|||||||
CTRL_HIGH = 53
|
CTRL_HIGH = 53
|
||||||
|
|
||||||
|
|
||||||
|
def drop_realtime() -> None:
|
||||||
|
if sys.platform == 'linux' and not PC:
|
||||||
|
os.sched_setscheduler(0, os.SCHED_OTHER, os.sched_param(0))
|
||||||
|
|
||||||
|
|
||||||
def set_core_affinity(cores: list[int]) -> None:
|
def set_core_affinity(cores: list[int]) -> None:
|
||||||
if sys.platform == 'linux' and not PC:
|
if sys.platform == 'linux' and not PC:
|
||||||
os.sched_setaffinity(0, cores)
|
os.sched_setaffinity(0, cores)
|
||||||
|
|||||||
+1
-1
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
#include <zmq.h>
|
#include <zmq.h>
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
|
|
||||||
|
|||||||
+19
-19
@@ -12,17 +12,17 @@ class TestParams:
|
|||||||
self.params = Params()
|
self.params = Params()
|
||||||
|
|
||||||
def test_params_put_and_get(self):
|
def test_params_put_and_get(self):
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("DongleId") == "cb38263377b873ee"
|
assert self.params.get("DongleId") == "cb38263377b873ee"
|
||||||
|
|
||||||
def test_params_non_ascii(self):
|
def test_params_non_ascii(self):
|
||||||
st = b"\xe1\x90\xff"
|
st = b"\xe1\x90\xff"
|
||||||
self.params.put("CarParams", st)
|
self.params.put("CarParams", st, block=True)
|
||||||
assert self.params.get("CarParams") == st
|
assert self.params.get("CarParams") == st
|
||||||
|
|
||||||
def test_params_get_cleared_manager_start(self):
|
def test_params_get_cleared_manager_start(self):
|
||||||
self.params.put("CarParams", b"test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee", block=True)
|
||||||
assert self.params.get("CarParams") == b"test"
|
assert self.params.get("CarParams") == b"test"
|
||||||
|
|
||||||
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
undefined_param = self.params.get_param_path(uuid.uuid4().hex)
|
||||||
@@ -36,15 +36,15 @@ class TestParams:
|
|||||||
assert not os.path.isfile(undefined_param)
|
assert not os.path.isfile(undefined_param)
|
||||||
|
|
||||||
def test_params_two_things(self):
|
def test_params_two_things(self):
|
||||||
self.params.put("DongleId", "bob")
|
self.params.put("DongleId", "bob", block=True)
|
||||||
self.params.put("AthenadPid", 123)
|
self.params.put("AthenadPid", 123, block=True)
|
||||||
assert self.params.get("DongleId") == "bob"
|
assert self.params.get("DongleId") == "bob"
|
||||||
assert self.params.get("AthenadPid") == 123
|
assert self.params.get("AthenadPid") == 123
|
||||||
|
|
||||||
def test_params_get_block(self):
|
def test_params_get_block(self):
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
self.params.put("CarParams", b"test")
|
self.params.put("CarParams", b"test", block=True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
assert self.params.get("CarParams", block=True) == b"test"
|
assert self.params.get("CarParams", block=True) == b"test"
|
||||||
@@ -57,10 +57,10 @@ class TestParams:
|
|||||||
self.params.get_bool("swag")
|
self.params.get_bool("swag")
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put("swag", "abc")
|
self.params.put("swag", "abc", block=True)
|
||||||
|
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
self.params.put_bool("swag", True)
|
self.params.put_bool("swag", True, block=True)
|
||||||
|
|
||||||
def test_remove_not_there(self):
|
def test_remove_not_there(self):
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
@@ -71,23 +71,23 @@ class TestParams:
|
|||||||
self.params.remove("IsMetric")
|
self.params.remove("IsMetric")
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", True)
|
self.params.put_bool("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put_bool("IsMetric", False)
|
self.params.put_bool("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", True)
|
self.params.put("IsMetric", True, block=True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", False)
|
self.params.put("IsMetric", False, block=True)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
def test_put_non_blocking_with_get_block(self):
|
def test_put_non_blocking_with_get_block(self):
|
||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_nonblocking("CarParams", b"test")
|
Params().put("CarParams", b"test")
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"test"
|
assert q.get("CarParams", True) == b"test"
|
||||||
@@ -96,7 +96,7 @@ class TestParams:
|
|||||||
q = Params()
|
q = Params()
|
||||||
def _delayed_writer():
|
def _delayed_writer():
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
Params().put_bool_nonblocking("CarParams", True)
|
Params().put_bool("CarParams", True)
|
||||||
threading.Thread(target=_delayed_writer).start()
|
threading.Thread(target=_delayed_writer).start()
|
||||||
assert q.get("CarParams") is None
|
assert q.get("CarParams") is None
|
||||||
assert q.get("CarParams", True) == b"1"
|
assert q.get("CarParams", True) == b"1"
|
||||||
@@ -123,19 +123,19 @@ class TestParams:
|
|||||||
|
|
||||||
def test_params_get_type(self):
|
def test_params_get_type(self):
|
||||||
# json
|
# json
|
||||||
self.params.put("ApiCache_FirehoseStats", {"a": 0})
|
self.params.put("ApiCache_FirehoseStats", {"a": 0}, block=True)
|
||||||
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
||||||
|
|
||||||
# int
|
# int
|
||||||
self.params.put("BootCount", 1441)
|
self.params.put("BootCount", 1441, block=True)
|
||||||
assert self.params.get("BootCount") == 1441
|
assert self.params.get("BootCount") == 1441
|
||||||
|
|
||||||
# bool
|
# bool
|
||||||
self.params.put("AdbEnabled", True)
|
self.params.put("AdbEnabled", True, block=True)
|
||||||
assert self.params.get("AdbEnabled")
|
assert self.params.get("AdbEnabled")
|
||||||
assert isinstance(self.params.get("AdbEnabled"), bool)
|
assert isinstance(self.params.get("AdbEnabled"), bool)
|
||||||
|
|
||||||
# time
|
# time
|
||||||
now = datetime.datetime.now(datetime.UTC)
|
now = datetime.datetime.now(datetime.UTC)
|
||||||
self.params.put("InstallDate", now)
|
self.params.put("InstallDate", now, block=True)
|
||||||
assert self.params.get("InstallDate") == now
|
assert self.params.get("InstallDate") == now
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "json11/json11.hpp"
|
||||||
|
|
||||||
#include "sunnypilot/common/version.h"
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import datetime
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
MIN_DATE = datetime.datetime(year=2025, month=2, day=21)
|
||||||
|
MAX_DATE = datetime.datetime(year=2035, month=1, day=1)
|
||||||
|
|
||||||
def min_date():
|
def min_date():
|
||||||
# on systemd systems, the default time is the systemd build time
|
# on systemd systems, the default time is the systemd build time
|
||||||
@@ -12,4 +13,4 @@ def min_date():
|
|||||||
return MIN_DATE
|
return MIN_DATE
|
||||||
|
|
||||||
def system_time_valid():
|
def system_time_valid():
|
||||||
return datetime.datetime.now() > min_date()
|
return min_date() < datetime.datetime.now() < MAX_DATE
|
||||||
|
|||||||
@@ -1,2 +0,0 @@
|
|||||||
transformations
|
|
||||||
transformations.cpp
|
|
||||||
+3
-3
@@ -48,7 +48,7 @@ def sudo_write(val: str, path: str) -> None:
|
|||||||
|
|
||||||
def sudo_read(path: str) -> str:
|
def sudo_read(path: str) -> str:
|
||||||
try:
|
try:
|
||||||
return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8').strip()
|
return subprocess.check_output(["sudo", "cat", "--", path], encoding='utf8').strip()
|
||||||
except Exception:
|
except Exception:
|
||||||
return ""
|
return ""
|
||||||
|
|
||||||
@@ -131,11 +131,11 @@ def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.Buffered
|
|||||||
return compressed_stream, compressed_size
|
return compressed_stream, compressed_size
|
||||||
|
|
||||||
|
|
||||||
# remove all keys that end in DEPRECATED
|
# remove all keys that end in DEPRECATED, plus any "deprecated" group
|
||||||
def strip_deprecated_keys(d):
|
def strip_deprecated_keys(d):
|
||||||
for k in list(d.keys()):
|
for k in list(d.keys()):
|
||||||
if isinstance(k, str):
|
if isinstance(k, str):
|
||||||
if k.endswith('DEPRECATED'):
|
if k.endswith('DEPRECATED') or k == 'deprecated':
|
||||||
d.pop(k)
|
d.pop(k)
|
||||||
elif isinstance(d[k], dict):
|
elif isinstance(d[k], dict):
|
||||||
strip_deprecated_keys(d[k])
|
strip_deprecated_keys(d[k])
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define COMMA_VERSION "0.10.4"
|
#define COMMA_VERSION "0.11.2"
|
||||||
|
|||||||
+4
-23
@@ -7,26 +7,19 @@ from openpilot.common.prefix import OpenpilotPrefix
|
|||||||
from openpilot.system.manager import manager
|
from openpilot.system.manager import manager
|
||||||
from openpilot.system.hardware import TICI, HARDWARE
|
from openpilot.system.hardware import TICI, HARDWARE
|
||||||
|
|
||||||
# TODO: pytest-cpp doesn't support FAIL, and we need to create test translations in sessionstart
|
# these are heavy CI-only tests, invoked explicitly in .github/workflows/tests.yaml
|
||||||
# pending https://github.com/pytest-dev/pytest-cpp/pull/147
|
|
||||||
collect_ignore = [
|
collect_ignore = [
|
||||||
"selfdrive/ui/tests/test_translations",
|
|
||||||
"selfdrive/test/process_replay/test_processes.py",
|
"selfdrive/test/process_replay/test_processes.py",
|
||||||
"selfdrive/test/process_replay/test_regen.py",
|
"selfdrive/test/process_replay/test_regen.py",
|
||||||
|
# tinygrad JIT has process-global state. Other test files import modeld → tinygrad,
|
||||||
|
# which corrupts JIT captures for test_warp.py in the same process. Run separately in CI.
|
||||||
|
"sunnypilot/modeld_v2/tests/test_warp.py",
|
||||||
]
|
]
|
||||||
collect_ignore_glob = [
|
collect_ignore_glob = [
|
||||||
"selfdrive/debug/*.py",
|
"selfdrive/debug/*.py",
|
||||||
"selfdrive/modeld/*.py",
|
|
||||||
"sunnypilot/modeld*/*.py",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
def pytest_sessionstart(session):
|
|
||||||
# TODO: fix tests and enable test order randomization
|
|
||||||
if session.config.pluginmanager.hasplugin('randomly'):
|
|
||||||
session.config.option.randomly_reorganize = False
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(hookwrapper=True, trylast=True)
|
@pytest.hookimpl(hookwrapper=True, trylast=True)
|
||||||
def pytest_runtest_call(item):
|
def pytest_runtest_call(item):
|
||||||
# ensure we run as a hook after capturemanager's
|
# ensure we run as a hook after capturemanager's
|
||||||
@@ -98,15 +91,3 @@ def pytest_collection_modifyitems(config, items):
|
|||||||
class_property_name = item.get_closest_marker('xdist_group_class_property').args[0]
|
class_property_name = item.get_closest_marker('xdist_group_class_property').args[0]
|
||||||
class_property_value = getattr(item.cls, class_property_name)
|
class_property_value = getattr(item.cls, class_property_name)
|
||||||
item.add_marker(pytest.mark.xdist_group(class_property_value))
|
item.add_marker(pytest.mark.xdist_group(class_property_value))
|
||||||
|
|
||||||
|
|
||||||
@pytest.hookimpl(trylast=True)
|
|
||||||
def pytest_configure(config):
|
|
||||||
config_line = "xdist_group_class_property: group tests by a property of the class that contains them"
|
|
||||||
config.addinivalue_line("markers", config_line)
|
|
||||||
|
|
||||||
config_line = "nocapture: don't capture test output"
|
|
||||||
config.addinivalue_line("markers", config_line)
|
|
||||||
|
|
||||||
config_line = "shared_download_cache: share download cache between tests"
|
|
||||||
config.addinivalue_line("markers", config_line)
|
|
||||||
|
|||||||
+127
-122
@@ -4,24 +4,25 @@
|
|||||||
|
|
||||||
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
|
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
|
||||||
|
|
||||||
# 336 Supported Cars
|
# 340 Supported Cars
|
||||||
|
|
||||||
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br> |Video|Setup Video|
|
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br> |Video|Setup Video|
|
||||||
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|
||||||
|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2016-18">Buy Here</a></sub></details>|||
|
|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2016-18">Buy Here</a></sub></details>|||
|
||||||
|Acura|ILX 2019|All|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2019">Buy Here</a></sub></details>|||
|
|Acura|ILX 2019|All|openpilot|26 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2019">Buy Here</a></sub></details>|||
|
||||||
|
|Acura|MDX 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|43 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2022-24">Buy Here</a></sub></details>|||
|
||||||
|Acura|MDX 2025-26|All except Type S|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2025-26">Buy Here</a></sub></details>|||
|
|Acura|MDX 2025-26|All except Type S|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2025-26">Buy Here</a></sub></details>|||
|
||||||
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2016-18">Buy Here</a></sub></details>|||
|
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2016-18">Buy Here</a></sub></details>|||
|
||||||
|Acura|RDX 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2019-21">Buy Here</a></sub></details>|||
|
|Acura|RDX 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Acura|TLX 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2021">Buy Here</a></sub></details>|||
|
|Acura|TLX 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2021-22">Buy Here</a></sub></details>|||
|
||||||
|Acura|TLX 2025|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2025">Buy Here</a></sub></details>|||
|
|Acura|TLX 2025|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2025">Buy Here</a></sub></details>|||
|
||||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 2014-19">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 2014-19">Buy Here</a></sub></details>|||
|
||||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q2 2018">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q2 2018">Buy Here</a></sub></details>|||
|
||||||
|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q3 2019-24">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q3 2019-24">Buy Here</a></sub></details>|||
|
||||||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi RS3 2018">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi RS3 2018">Buy Here</a></sub></details>|||
|
||||||
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi S3 2015-17">Buy Here</a></sub></details>|||
|
|Audi[<sup>11</sup>](#footnotes)|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi S3 2015-17">Buy Here</a></sub></details>|||
|
||||||
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim, without Super Cruise Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EUV 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/xvwzGMUA210" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim, without Super Cruise Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EUV 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/xvwzGMUA210" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EV 2022-23">Buy Here</a></sub></details>|||
|
|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EV 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Equinox 2019-22">Buy Here</a></sub></details>|||
|
|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Equinox 2019-22">Buy Here</a></sub></details>|||
|
||||||
|Chevrolet|Silverado 1500 2020-21|Safety Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Silverado 1500 2020-21">Buy Here</a></sub></details>|||
|
|Chevrolet|Silverado 1500 2020-21|Safety Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Silverado 1500 2020-21">Buy Here</a></sub></details>|||
|
||||||
@@ -31,34 +32,34 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2021-23">Buy Here</a></sub></details>|||
|
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2017-18">Buy Here</a></sub></details>|||
|
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Chrysler|Pacifica Hybrid 2019-25|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2019-25">Buy Here</a></sub></details>|||
|
|Chrysler|Pacifica Hybrid 2019-25|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2019-25">Buy Here</a></sub></details>|||
|
||||||
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None|<a href="https://youtu.be/VT-i3yRsX2s?t=2736" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None|<a href="https://youtu.be/VT-i3yRsX2s?t=2736" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=CUPRA Ateca 2018-23">Buy Here</a></sub></details>|||
|
|CUPRA[<sup>11</sup>](#footnotes)|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=CUPRA Ateca 2018-23">Buy Here</a></sub></details>|||
|
||||||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Dodge Durango 2020-21">Buy Here</a></sub></details>|||
|
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Dodge Durango 2020-21">Buy Here</a></sub></details>|||
|
||||||
|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Bronco Sport 2021-24">Buy Here</a></sub></details>|||
|
|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Bronco Sport 2021-24">Buy Here</a></sub></details>|||
|
||||||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2020-22">Buy Here</a></sub></details>|||
|
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Ford|Escape 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Escape 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Expedition 2022-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Expedition 2022-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Explorer 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer 2020-24">Buy Here</a></sub></details>|||
|
|Ford|Explorer 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer 2020-24">Buy Here</a></sub></details>|||
|
||||||
|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer Hybrid 2020-24">Buy Here</a></sub></details>|||
|
|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer Hybrid 2020-24">Buy Here</a></sub></details>|||
|
||||||
|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 Hybrid 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 Hybrid 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Focus 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus 2018">Buy Here</a></sub></details>|||
|
|Ford|Focus 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus 2018">Buy Here</a></sub></details>|||
|
||||||
|Ford|Focus Hybrid 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus Hybrid 2018">Buy Here</a></sub></details>|||
|
|Ford|Focus Hybrid 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus Hybrid 2018">Buy Here</a></sub></details>|||
|
||||||
|Ford|Kuga 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga 2020-23">Buy Here</a></sub></details>|||
|
|Ford|Kuga 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Ford|Kuga Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Ford|Kuga Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Ford|Kuga Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Kuga Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Kuga Plug-in Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Ford|Kuga Plug-in Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Ford|Kuga Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Kuga Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Maverick 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2022">Buy Here</a></sub></details>|||
|
|Ford|Maverick 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2022">Buy Here</a></sub></details>|||
|
||||||
|Ford|Maverick 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2023-24">Buy Here</a></sub></details>|||
|
|Ford|Maverick 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Ford|Maverick Hybrid 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2022">Buy Here</a></sub></details>|||
|
|Ford|Maverick Hybrid 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2022">Buy Here</a></sub></details>|||
|
||||||
|Ford|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2023-24">Buy Here</a></sub></details>|||
|
|Ford|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Ford|Mustang Mach-E 2021-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Mustang Mach-E 2021-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Mustang Mach-E 2021-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Mustang Mach-E 2021-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Ranger 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Ranger 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Genesis|G70 2018|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2018">Buy Here</a></sub></details>|||
|
|Genesis|G70 2018|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2018">Buy Here</a></sub></details>|||
|
||||||
|Genesis|G70 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2019-21">Buy Here</a></sub></details>|||
|
|Genesis|G70 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Genesis|G70 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2022-23">Buy Here</a></sub></details>|||
|
|Genesis|G70 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2022-23">Buy Here</a></sub></details>|||
|
||||||
@@ -73,18 +74,18 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Genesis|GV70 Electrified (Australia Only) 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV70 Electrified (Australia Only) 2022">Buy Here</a></sub></details>|||
|
|Genesis|GV70 Electrified (Australia Only) 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV70 Electrified (Australia Only) 2022">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV70 Electrified (with HDA II) 2023-24|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV70 Electrified (with HDA II) 2023-24">Buy Here</a></sub></details>|||
|
|Genesis|GV70 Electrified (with HDA II) 2023-24|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV70 Electrified (with HDA II) 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV80 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV80 2023">Buy Here</a></sub></details>|||
|
|Genesis|GV80 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis GV80 2023">Buy Here</a></sub></details>|||
|
||||||
|GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=GMC Sierra 1500 2020-21">Buy Here</a></sub></details>|<a href="https://youtu.be/5HbNoBLzRwE" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|GMC|Sierra 1500 2020-21|Driver Alert Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=GMC Sierra 1500 2020-21">Buy Here</a></sub></details>|<a href="https://youtu.be/5HbNoBLzRwE" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Accord 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2018-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=mrUwlj3Mi58" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Honda|Accord 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2018-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=mrUwlj3Mi58" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Accord 2023-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2023-25">Buy Here</a></sub></details>|||
|
|Honda|Accord 2023-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Honda|Accord Hybrid 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2018-22">Buy Here</a></sub></details>|||
|
|Honda|Accord Hybrid 2018-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2018-22">Buy Here</a></sub></details>|||
|
||||||
|Honda|Accord Hybrid 2023-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2023-25">Buy Here</a></sub></details>|||
|
|Honda|Accord Hybrid 2023-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Honda|City (Brazil only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|14 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda City (Brazil only) 2023">Buy Here</a></sub></details>|||
|
|Honda|City (Brazil only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|14 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda City (Brazil only) 2023">Buy Here</a></sub></details>|||
|
||||||
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2016-18">Buy Here</a></sub></details>|<a href="https://youtu.be/-IkImTe1NYE" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2016-18">Buy Here</a></sub></details>|<a href="https://youtu.be/-IkImTe1NYE" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>4</sup>](#footnotes)|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=4Iz1Mz5LGF8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>4</sup>](#footnotes)|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=4Iz1Mz5LGF8" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Civic 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Honda|Civic 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2017-18">Buy Here</a></sub></details>|||
|
|Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Honda|Civic Hatchback 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2019-21">Buy Here</a></sub></details>|||
|
|Honda|Civic Hatchback 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Honda|Civic Hatchback 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Honda|Civic Hatchback 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid 2025-26">Buy Here</a></sub></details>|||
|
|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid 2025-26">Buy Here</a></sub></details>|||
|
||||||
|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid (Europe only) 2023">Buy Here</a></sub></details>|||
|
|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid (Europe only) 2023">Buy Here</a></sub></details>|||
|
||||||
|Honda|Civic Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hybrid 2025-26">Buy Here</a></sub></details>|||
|
|Honda|Civic Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hybrid 2025-26">Buy Here</a></sub></details>|||
|
||||||
@@ -103,6 +104,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Honda|N-Box 2018|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|11 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda N-Box 2018">Buy Here</a></sub></details>|||
|
|Honda|N-Box 2018|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|11 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda N-Box 2018">Buy Here</a></sub></details>|||
|
||||||
|Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2018-20">Buy Here</a></sub></details>|||
|
|Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2018-20">Buy Here</a></sub></details>|||
|
||||||
|Honda|Odyssey 2021-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|43 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2021-26">Buy Here</a></sub></details>|||
|
|Honda|Odyssey 2021-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|43 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2021-26">Buy Here</a></sub></details>|||
|
||||||
|
|Honda|Odyssey (Singapore) 2021|Honda Sensing|openpilot|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey (Singapore) 2021">Buy Here</a></sub></details>|||
|
||||||
|Honda|Odyssey (Taiwan) 2018-19|Honda Sensing|openpilot|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey (Taiwan) 2018-19">Buy Here</a></sub></details>|||
|
|Honda|Odyssey (Taiwan) 2018-19|Honda Sensing|openpilot|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey (Taiwan) 2018-19">Buy Here</a></sub></details>|||
|
||||||
|Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2019-25">Buy Here</a></sub></details>|||
|
|Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2019-25">Buy Here</a></sub></details>|||
|
||||||
|Honda|Passport 2026|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2026">Buy Here</a></sub></details>|||
|
|Honda|Passport 2026|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2026">Buy Here</a></sub></details>|||
|
||||||
@@ -115,9 +117,9 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Hyundai|Custin 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Custin 2023">Buy Here</a></sub></details>|||
|
|Hyundai|Custin 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Custin 2023">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2017-18">Buy Here</a></sub></details>|||
|
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2019">Buy Here</a></sub></details>|||
|
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2019">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra GT 2017-20">Buy Here</a></sub></details>|||
|
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra GT 2017-20">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Genesis 2015-16">Buy Here</a></sub></details>|||
|
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Genesis 2015-16">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai i30 2017-19">Buy Here</a></sub></details>|||
|
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai i30 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24">Buy Here</a></sub></details>|||
|
||||||
@@ -134,17 +136,17 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Kona 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2018-21">Buy Here</a></sub></details>|||
|
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2018-21">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric (with HDA II, Korea only) 2023">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=U2fOCmcQ8hw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric (with HDA II, Korea only) 2023">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=U2fOCmcQ8hw" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Hybrid 2020">Buy Here</a></sub></details>|||
|
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Hybrid 2020">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Nexo 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Nexo 2021">Buy Here</a></sub></details>|||
|
|Hyundai|Nexo 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Nexo 2021">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Palisade 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Palisade 2020-22">Buy Here</a></sub></details>|<a href="https://youtu.be/TAnDqjF4fDY?t=456" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Palisade 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Palisade 2020-22">Buy Here</a></sub></details>|<a href="https://youtu.be/TAnDqjF4fDY?t=456" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Santa Cruz 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Cruz 2022-24">Buy Here</a></sub></details>|||
|
|Hyundai|Santa Cruz 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Cruz 2022-24">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Santa Fe 2019-20|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe 2019-20">Buy Here</a></sub></details>|<a href="https://youtu.be/bjDR0YjM__s" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Santa Fe 2019-20|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe 2019-20">Buy Here</a></sub></details>|<a href="https://youtu.be/bjDR0YjM__s" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Santa Fe 2021-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/VnHzSTygTS4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Santa Fe 2021-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/VnHzSTygTS4" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Santa Fe Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe Hybrid 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Santa Fe Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe Hybrid 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Santa Fe Plug-in Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe Plug-in Hybrid 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Santa Fe Plug-in Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Fe Plug-in Hybrid 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata 2018-19">Buy Here</a></sub></details>|||
|
|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata 2018-19">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Sonata 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata 2020-23">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=ix63r9kE3Fw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Hyundai|Sonata 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata 2020-23">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=ix63r9kE3Fw" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Hyundai|Sonata Hybrid 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Hyundai|Sonata Hybrid 2020-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Sonata Hybrid 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Staria 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Staria 2023">Buy Here</a></sub></details>|||
|
|Hyundai|Staria 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Staria 2023">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson 2021">Buy Here</a></sub></details>|||
|
|Hyundai|Tucson 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson 2021">Buy Here</a></sub></details>|||
|
||||||
@@ -154,8 +156,8 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Hyundai|Tucson Hybrid 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson Hybrid 2022-24">Buy Here</a></sub></details>|||
|
|Hyundai|Tucson Hybrid 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson Hybrid 2022-24">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Tucson Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson Plug-in Hybrid 2024">Buy Here</a></sub></details>|||
|
|Hyundai|Tucson Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Tucson Plug-in Hybrid 2024">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Veloster 2019-20">Buy Here</a></sub></details>|||
|
|Hyundai|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Veloster 2019-20">Buy Here</a></sub></details>|||
|
||||||
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Jeep Grand Cherokee 2016-18">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=eLR9o2JkuRk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Jeep Grand Cherokee 2016-18">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=eLR9o2JkuRk" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Jeep Grand Cherokee 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=jBe4lWnRSu4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Jeep Grand Cherokee 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=jBe4lWnRSu4" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival 2022-24">Buy Here</a></sub></details>|||
|
|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival 2022-24">Buy Here</a></sub></details>|||
|
||||||
|Kia|Carnival (China only) 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival (China only) 2023">Buy Here</a></sub></details>|||
|
|Kia|Carnival (China only) 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival (China only) 2023">Buy Here</a></sub></details>|||
|
||||||
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed 2019-21">Buy Here</a></sub></details>|||
|
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed 2019-21">Buy Here</a></sub></details>|||
|
||||||
@@ -168,16 +170,16 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K5 Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K5 Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Kia|K7 2017|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K7 2017">Buy Here</a></sub></details>|||
|
|Kia|K7 2017|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K7 2017">Buy Here</a></sub></details>|||
|
||||||
|Kia|K8 Hybrid (with HDA II) 2023|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K8 Hybrid (with HDA II) 2023">Buy Here</a></sub></details>|||
|
|Kia|K8 Hybrid (with HDA II) 2023|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K8 Hybrid (with HDA II) 2023">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro EV 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Niro EV 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Niro EV 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2020">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Niro EV 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2020">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Niro EV 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2021">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Niro EV 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2021">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Niro EV 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2022">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Niro EV 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV 2022">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=lT7zcG6ZpGo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Niro EV (with HDA II) 2025|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV (with HDA II) 2025">Buy Here</a></sub></details>|||
|
|Kia|Niro EV (with HDA II) 2024-25|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV (with HDA II) 2024-25">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro EV (without HDA II) 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV (without HDA II) 2023-25">Buy Here</a></sub></details>|||
|
|Kia|Niro EV (without HDA II) 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro EV (without HDA II) 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Hybrid 2018|Smart Cruise Control (SCC)|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2018">Buy Here</a></sub></details>|||
|
|Kia|Niro Hybrid 2018|Smart Cruise Control (SCC)|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2018">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2021">Buy Here</a></sub></details>|||
|
|Kia|Niro Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2021">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2022">Buy Here</a></sub></details>|||
|
|Kia|Niro Hybrid 2022|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2022">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Hybrid 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2023">Buy Here</a></sub></details>|||
|
|Kia|Niro Hybrid 2023-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Hybrid 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2018-19">Buy Here</a></sub></details>|||
|
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2018-19">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Plug-in Hybrid 2020|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2020">Buy Here</a></sub></details>|||
|
|Kia|Niro Plug-in Hybrid 2020|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2020">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro Plug-in Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2021">Buy Here</a></sub></details>|||
|
|Kia|Niro Plug-in Hybrid 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Niro Plug-in Hybrid 2021">Buy Here</a></sub></details>|||
|
||||||
@@ -186,21 +188,21 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Optima 2019-20">Buy Here</a></sub></details>|||
|
|Kia|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Optima 2019-20">Buy Here</a></sub></details>|||
|
||||||
|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Optima Hybrid 2019">Buy Here</a></sub></details>|||
|
|Kia|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Optima Hybrid 2019">Buy Here</a></sub></details>|||
|
||||||
|Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Seltos 2021">Buy Here</a></sub></details>|||
|
|Kia|Seltos 2021|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Seltos 2021">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2018">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Sorento 2018|Advanced Smart Cruise Control & LKAS|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2018">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2019">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Fkh3s6WHJz8" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Sorento 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2021-23">Buy Here</a></sub></details>|||
|
|Kia|Sorento 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento Hybrid 2021-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento Hybrid 2021-23">Buy Here</a></sub></details>|||
|
|Kia|Sorento Hybrid 2021-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento Hybrid 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento Plug-in Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento Plug-in Hybrid 2022-23">Buy Here</a></sub></details>|||
|
|Kia|Sorento Plug-in Hybrid 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sorento Plug-in Hybrid 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sportage 2023-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sportage 2023-24">Buy Here</a></sub></details>|||
|
|Kia|Sportage 2023-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sportage 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sportage Hybrid 2023">Buy Here</a></sub></details>|||
|
|Kia|Sportage Hybrid 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Sportage Hybrid 2023">Buy Here</a></sub></details>|||
|
||||||
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=MJ94qoofYw0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=MJ94qoofYw0" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Kia|Stinger 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2022-23">Buy Here</a></sub></details>|||
|
|Kia|Stinger 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Kia|Telluride 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Telluride 2020-22">Buy Here</a></sub></details>|||
|
|Kia|Telluride 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Telluride 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus CT Hybrid 2017-18">Buy Here</a></sub></details>|||
|
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus CT Hybrid 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Lexus|ES 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2017-18">Buy Here</a></sub></details>|||
|
|Lexus|ES 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Lexus|ES 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2019-25">Buy Here</a></sub></details>|||
|
|Lexus|ES 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2019-25">Buy Here</a></sub></details>|||
|
||||||
|Lexus|ES Hybrid 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2017-18">Buy Here</a></sub></details>|||
|
|Lexus|ES Hybrid 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2019-25">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2019-25">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus GS F 2016">Buy Here</a></sub></details>|||
|
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus GS F 2016">Buy Here</a></sub></details>|||
|
||||||
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2017-19">Buy Here</a></sub></details>|||
|
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Lexus|IS 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2022-24">Buy Here</a></sub></details>|||
|
|Lexus|IS 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2022-24">Buy Here</a></sub></details>|||
|
||||||
@@ -221,23 +223,25 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus UX Hybrid 2019-24">Buy Here</a></sub></details>|||
|
|Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus UX Hybrid 2019-24">Buy Here</a></sub></details>|||
|
||||||
|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator 2020-24">Buy Here</a></sub></details>|||
|
|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator 2020-24">Buy Here</a></sub></details>|||
|
||||||
|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>|||
|
|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>|||
|
||||||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|MAN[<sup>11</sup>](#footnotes)|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|MAN[<sup>11</sup>](#footnotes)|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-5 2022-25">Buy Here</a></sub></details>|||
|
|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-5 2022-25">Buy Here</a></sub></details>|||
|
||||||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Nissan[<sup>5</sup>](#footnotes)|Altima 2019-20, 2024|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Altima 2019-20, 2024">Buy Here</a></sub></details>|||
|
|Nissan[<sup>5</sup>](#footnotes)|Altima 2019-20, 2024|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Altima 2019-20, 2024">Buy Here</a></sub></details>|||
|
||||||
|Nissan[<sup>5</sup>](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Nissan[<sup>5</sup>](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Nissan[<sup>5</sup>](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Rogue 2018-20">Buy Here</a></sub></details>|||
|
|Nissan[<sup>5</sup>](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Rogue 2018-20">Buy Here</a></sub></details>|||
|
||||||
|Nissan[<sup>5</sup>](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan X-Trail 2017">Buy Here</a></sub></details>|||
|
|Nissan[<sup>5</sup>](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan X-Trail 2017">Buy Here</a></sub></details>|||
|
||||||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|32 mph|1 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 1500 2019-24">Buy Here</a></sub></details>|||
|
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|32 mph|1 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 1500 2019-24">Buy Here</a></sub></details>|||
|
||||||
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 2500 2020-24">Buy Here</a></sub></details>|||
|
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 2500 2020-24">Buy Here</a></sub></details>|||
|
||||||
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 3500 2019-22">Buy Here</a></sub></details>|||
|
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 3500 2019-22">Buy Here</a></sub></details>|||
|
||||||
|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1S 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1S 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1T 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
|Rivian|R1S 2025|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1S 2025">Buy Here</a></sub></details>|||
|
||||||
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Ateca 2016-23">Buy Here</a></sub></details>|||
|
|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1T 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>|
|
||||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Leon 2014-20">Buy Here</a></sub></details>|||
|
|Rivian|R1T 2025|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1T 2025">Buy Here</a></sub></details>|||
|
||||||
|
|SEAT[<sup>11</sup>](#footnotes)|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Ateca 2016-23">Buy Here</a></sub></details>|||
|
||||||
|
|SEAT[<sup>11</sup>](#footnotes)|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Leon 2014-20">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Ascent 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Ascent 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|Forester 2017-18|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2017-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Forester 2017-18|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2017-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|Forester 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Forester 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
@@ -248,17 +252,17 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Subaru|Outback 2015-17|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2015-17">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Outback 2015-17|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2015-17">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|Outback 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Outback 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|Outback 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|Outback 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|
||||||
|Škoda|Fabia 2022-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Fabia 2022-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Škoda|Fabia 2022-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Fabia 2022-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Škoda|Kamiq 2021-23[<sup>11,13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kamiq 2021-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Škoda|Kamiq 2021-23[<sup>12,14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kamiq 2021-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Škoda|Karoq 2019-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Karoq 2019-23">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Karoq 2019-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Karoq 2019-23">Buy Here</a></sub></details>|||
|
||||||
|Škoda|Kodiaq 2017-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kodiaq 2017-23">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Kodiaq 2017-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kodiaq 2017-23">Buy Here</a></sub></details>|||
|
||||||
|Škoda|Octavia 2015-19[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia 2015-19">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Octavia 2015-19[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia 2015-19">Buy Here</a></sub></details>|||
|
||||||
|Škoda|Octavia RS 2016[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia RS 2016">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Octavia RS 2016[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia RS 2016">Buy Here</a></sub></details>|||
|
||||||
|Škoda|Octavia Scout 2017-19[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia Scout 2017-19">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Octavia Scout 2017-19[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia Scout 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Škoda|Scala 2020-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Scala 2020-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Škoda|Scala 2020-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Scala 2020-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Škoda|Superb 2015-22[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Superb 2015-22">Buy Here</a></sub></details>|||
|
|Škoda[<sup>11</sup>](#footnotes)|Superb 2015-22[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Superb 2015-22">Buy Here</a></sub></details>|||
|
||||||
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW3) 2019-23">Buy Here</a></sub></details>|||
|
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW3) 2019-23">Buy Here</a></sub></details>|||
|
||||||
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW4) 2024-25">Buy Here</a></sub></details>|||
|
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW4) 2024-25">Buy Here</a></sub></details>|||
|
||||||
|Tesla[<sup>9</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW3) 2020-23">Buy Here</a></sub></details>|||
|
|Tesla[<sup>9</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW3) 2020-23">Buy Here</a></sub></details>|||
|
||||||
@@ -275,75 +279,75 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR 2021">Buy Here</a></sub></details>|||
|
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR 2021">Buy Here</a></sub></details>|||
|
||||||
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2017-20">Buy Here</a></sub></details>|||
|
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2017-20">Buy Here</a></sub></details>|||
|
||||||
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2021-22">Buy Here</a></sub></details>|||
|
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2021-22">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>10</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>10</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>10</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2021-24">Buy Here</a></sub></details>|||
|
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>10</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2021-24">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2021-24">Buy Here</a></sub></details>|||
|
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2021-24">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Corolla 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2017-19">Buy Here</a></sub></details>|||
|
|Toyota|Corolla 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2020-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2020-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>|||
|
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross Hybrid (Non-US only) 2020-22">Buy Here</a></sub></details>|||
|
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross Hybrid (Non-US only) 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hatchback 2019-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hatchback 2019-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid (South America only) 2020-23">Buy Here</a></sub></details>|||
|
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid (South America only) 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Highlander 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2017-19">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0wS0wXSLzoo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Highlander 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2017-19">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0wS0wXSLzoo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2020-23">Buy Here</a></sub></details>|||
|
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Highlander Hybrid 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2017-19">Buy Here</a></sub></details>|||
|
|Toyota|Highlander Hybrid 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2020-23">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Mirai 2021">Buy Here</a></sub></details>|||
|
|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Mirai 2021">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius 2016|Toyota Safety Sense P|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2016">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Prius 2016|Toyota Safety Sense P|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2016">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Prius 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Prius 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Prius Prime 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Prius Prime 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Prius v 2017|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius v 2017">Buy Here</a></sub></details>|||
|
|Toyota|Prius v 2017|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius v 2017">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2016">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2016">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2017-18">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=wJxjDd42gGA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=wJxjDd42gGA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|RAV4 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2022">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2022">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2023-25">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2016">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2016">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|RAV4 Hybrid 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|RAV4 Hybrid 2017-18|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2019-21">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|RAV4 Hybrid 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2023-25">Buy Here</a></sub></details>|<a href="https://youtu.be/4eIsEq4L4Ng" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|RAV4 Hybrid 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2023-25">Buy Here</a></sub></details>|<a href="https://youtu.be/4eIsEq4L4Ng" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Toyota|Sienna 2018-20|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Toyota|Sienna 2018-20|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon Shooting Brake 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon Shooting Brake 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas 2018-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas 2018-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas Cross Sport 2020-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas Cross Sport 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen California 2021-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen California 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Caravelle 2020">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Caravelle 2020">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Crafter 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Crafter 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Crafter 2018-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Crafter 2018-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Golf 2014-20">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Golf 2014-20">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf 2015-20">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf 2015-20">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf Alltrack 2015-19">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf Alltrack 2015-19">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTD 2015-20">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTD 2015-20">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTE 2015-20">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTE 2015-20">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTI 2015-21">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTI 2015-21">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf R 2015-19">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf R 2015-19">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf SportsVan 2015-20">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf SportsVan 2015-20">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Grand California 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Grand California 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg" /></a>||
|
||||||
|Volkswagen|Jetta 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta 2019-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Jetta 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta 2019-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta GLI 2021-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta GLI 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Passat 2015-22[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat 2015-22">Buy Here</a></sub></details>|||
|
|Volkswagen|Passat 2015-22[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat 2015-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat Alltrack 2015-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat Alltrack 2015-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat GTE 2015-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat GTE 2015-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo 2018-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo 2018-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Cross 2021">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Cross 2021">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|
||||||
|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Roc 2018-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Roc 2018-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Taos 2022-24">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Taos 2022-24">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont 2018-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont 2018-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont Cross Sport 2021-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont Cross Sport 2021-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont X 2021-22">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont X 2021-22">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan 2018-24">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan 2018-24">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan eHybrid 2021-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan eHybrid 2021-23">Buy Here</a></sub></details>|||
|
||||||
|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Touran 2016-23">Buy Here</a></sub></details>|||
|
|Volkswagen[<sup>11</sup>](#footnotes)|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Touran 2016-23">Buy Here</a></sub></details>|||
|
||||||
|
|
||||||
### Footnotes
|
### Footnotes
|
||||||
<sup>1</sup>openpilot Longitudinal Control (Alpha) is available behind a toggle; the toggle is only available in non-release branches such as `nightly-dev`. <br />
|
<sup>1</sup>openpilot Longitudinal Control (Alpha) is available behind a toggle; the toggle is only available in non-release branches such as `nightly-dev`. <br />
|
||||||
@@ -356,11 +360,12 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
<sup>8</sup>Some 2023 model years have HW4. To check which hardware type your vehicle has, look for <b>Autopilot computer</b> under <b>Software -> Additional Vehicle Information</b> on your vehicle's touchscreen. See <a href="https://www.notateslaapp.com/news/2173/how-to-check-if-your-tesla-has-hardware-4-ai4-or-hardware-3">this page</a> for more information. <br />
|
<sup>8</sup>Some 2023 model years have HW4. To check which hardware type your vehicle has, look for <b>Autopilot computer</b> under <b>Software -> Additional Vehicle Information</b> on your vehicle's touchscreen. See <a href="https://www.notateslaapp.com/news/2173/how-to-check-if-your-tesla-has-hardware-4-ai4-or-hardware-3">this page</a> for more information. <br />
|
||||||
<sup>9</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
|
<sup>9</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
|
||||||
<sup>10</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
<sup>10</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
||||||
<sup>11</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
<sup>11</sup>The J533 harness plugs in at the CAN gateway under the dashboard, just above the steering column. More information can be found at <a href="https://docs.howtocomma.com/docs/j533-harness-install" target="_blank">this guide</a>. <br />
|
||||||
<sup>12</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
<sup>12</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||||
<sup>13</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma four functionality. <br />
|
<sup>13</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
||||||
<sup>14</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
|
<sup>14</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma four functionality. <br />
|
||||||
<sup>15</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
|
<sup>15</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
|
||||||
|
<sup>16</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
|
||||||
|
|
||||||
## Community Maintained Cars
|
## Community Maintained Cars
|
||||||
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
Although they're not upstream, the community has openpilot running on other makes and models. See the 'Community Supported Models' section of each make [on our wiki](https://wiki.comma.ai/).
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ All of these are examples of good PRs:
|
|||||||
### First contribution
|
### First contribution
|
||||||
|
|
||||||
[Projects / openpilot bounties](https://github.com/orgs/commaai/projects/26/views/1?pane=info) is the best place to get started and goes in-depth on what's expected when working on a bounty.
|
[Projects / openpilot bounties](https://github.com/orgs/commaai/projects/26/views/1?pane=info) is the best place to get started and goes in-depth on what's expected when working on a bounty.
|
||||||
There are a lot of bounties that don't require a comma 3X or a car.
|
There are a lot of bounties that don't require a comma four or a car.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
# Docs development
|
||||||
|
|
||||||
|
The `docs/` tree is the source for [docs.comma.ai](https://docs.comma.ai).
|
||||||
|
The site is updated on pushes to master by this [workflow](../.github/workflows/docs.yaml).
|
||||||
|
|
||||||
|
Those commands must be run in the root directory of openpilot, **not /docs**
|
||||||
|
|
||||||
|
**1. Install the docs dependencies**
|
||||||
|
``` bash
|
||||||
|
uv pip install .[docs]
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. Build the new site**
|
||||||
|
``` bash
|
||||||
|
docs build
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. Run the new site locally**
|
||||||
|
``` bash
|
||||||
|
docs serve
|
||||||
|
```
|
||||||
|
|
||||||
|
References:
|
||||||
|
* https://zensical.org/docs/
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
# openpilot docs
|
|
||||||
|
|
||||||
This is the source for [docs.comma.ai](https://docs.comma.ai).
|
|
||||||
The site is updated on pushes to master by this [workflow](../.github/workflows/docs.yaml).
|
|
||||||
|
|
||||||
## Development
|
|
||||||
NOTE: Those commands must be run in the root directory of openpilot, **not /docs**
|
|
||||||
|
|
||||||
**1. Install the docs dependencies**
|
|
||||||
``` bash
|
|
||||||
uv pip install .[docs]
|
|
||||||
```
|
|
||||||
|
|
||||||
**2. Build the new site**
|
|
||||||
``` bash
|
|
||||||
mkdocs build
|
|
||||||
```
|
|
||||||
|
|
||||||
**3. Run the new site locally**
|
|
||||||
``` bash
|
|
||||||
mkdocs serve
|
|
||||||
```
|
|
||||||
|
|
||||||
References:
|
|
||||||
* https://www.mkdocs.org/getting-started/
|
|
||||||
* https://github.com/ntno/mkdocs-terminal
|
|
||||||
+2
-2
@@ -4,8 +4,8 @@ openpilot is an Adaptive Cruise Control (ACC) and Automated Lane Centering (ALC)
|
|||||||
Like other ACC and ALC systems, openpilot is a failsafe passive system and it requires the
|
Like other ACC and ALC systems, openpilot is a failsafe passive system and it requires the
|
||||||
driver to be alert and to pay attention at all times.
|
driver to be alert and to pay attention at all times.
|
||||||
|
|
||||||
In order to enforce driver alertness, openpilot includes a driver monitoring feature
|
To assist the driver in maintaining alertness, openpilot includes a driver monitoring feature
|
||||||
that alerts the driver when distracted.
|
that alerts when it detects driver distraction.
|
||||||
|
|
||||||
However, even with an attentive driver, we must make further efforts for the system to be
|
However, even with an attentive driver, we must make further efforts for the system to be
|
||||||
safe. We repeat, **driver alertness is necessary, but not sufficient, for openpilot to be
|
safe. We repeat, **driver alertness is necessary, but not sufficient, for openpilot to be
|
||||||
|
|||||||
Symlink
+1
@@ -0,0 +1 @@
|
|||||||
|
../../selfdrive/assets/icons_mici/settings/comma_icon.png
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Developing a car brand port
|
|
||||||
|
|
||||||
A brand port is a port of openpilot to a substantially new car brand or platform within a brand.
|
|
||||||
|
|
||||||
Here's an example of one: https://github.com/commaai/openpilot/pull/23331.
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# CarState signals
|
|
||||||
|
|
||||||
## Required for basic lateral control
|
|
||||||
|
|
||||||
* `brakePressed`
|
|
||||||
* `cruiseState`
|
|
||||||
* `doorOpen`
|
|
||||||
* `espDisabled`
|
|
||||||
* `gasPressed`
|
|
||||||
* `gearShifter`
|
|
||||||
* `leftBlinker` / `rightBlinker`
|
|
||||||
* `seatbeltUnlatched`
|
|
||||||
* `standstill`
|
|
||||||
* `steeringAngleDeg`
|
|
||||||
* `steeringPressed`
|
|
||||||
* `steeringTorque`
|
|
||||||
* `steerFaultPermanent`
|
|
||||||
* `steerFaultTemporary`
|
|
||||||
* `vCruise`
|
|
||||||
* `wheelSpeeds.[fl|fr|rl|rr]`: Speed of each of the car's four wheels, in m/s. The car's CAN bus often broadcasts the
|
|
||||||
speed in kph, so the helper function `parse_wheel_speeds` performs this conversion by default.
|
|
||||||
|
|
||||||
## Recommended / Required for openpilot longitudinal control
|
|
||||||
|
|
||||||
* `accFaulted`
|
|
||||||
* `espActive`
|
|
||||||
* `parkingBrake`
|
|
||||||
|
|
||||||
## Application Dependent
|
|
||||||
|
|
||||||
* `blockPcmEnable`
|
|
||||||
* `buttonEnable`
|
|
||||||
* `brakeHoldActive`
|
|
||||||
* `carFaultedNonCritical`
|
|
||||||
* `invalidLkasSetting`
|
|
||||||
* `lowSpeedAlert`
|
|
||||||
* `regenBraking`
|
|
||||||
* `steeringAngleOffsetDeg`
|
|
||||||
* `steeringDisengage`
|
|
||||||
* `steeringTorqueEps`
|
|
||||||
* `stockLkas`
|
|
||||||
* `vCruiseCluster`
|
|
||||||
* `vEgoCluster`
|
|
||||||
* `vehicleSensorsInvalid`
|
|
||||||
|
|
||||||
## Automatically populated
|
|
||||||
|
|
||||||
* `buttonEvents`
|
|
||||||
|
|
||||||
These values are populated automatically by `parse_wheel_speeds`:
|
|
||||||
|
|
||||||
* `aEgo`: Acceleration of the ego vehicle, Kalman filtered derivative of `vEgo`.
|
|
||||||
* `vEgo`: Speed of the ego vehicle, Kalman filtered from `vEgoRaw`.
|
|
||||||
* `vEgoRaw`: Speed of the ego vehicle, based on the average of all four wheel speeds, unfiltered.
|
|
||||||
|
|
||||||
## Optional
|
|
||||||
|
|
||||||
* `brake`
|
|
||||||
* `charging`
|
|
||||||
* `fuelGauge`
|
|
||||||
* `leftBlindspot` / `rightBlindspot`
|
|
||||||
* `steeringRateDeg`
|
|
||||||
* `stockAeb`
|
|
||||||
* `stockFcw`
|
|
||||||
* `yawRate`
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
# Developing a car model port
|
|
||||||
|
|
||||||
A model port is a port of openpilot to a new car model within an already supported brand. Model ports are easier than brand ports because the car's existing APIs are already known.
|
|
||||||
|
|
||||||
Here's an example of one: https://github.com/commaai/openpilot/pull/30672/.
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
# Stimulus-Response Tests
|
|
||||||
|
|
||||||
These are example test drives that can help identify the CAN bus messaging necessary for ADAS control. Each scripted
|
|
||||||
test should be done in a separate route (ignition cycle). These tests are a guide, not necessarily exhaustive.
|
|
||||||
|
|
||||||
While testing, constant power to the comma device is highly recommended, using [comma power](https://comma.ai/shop/comma-power) if
|
|
||||||
necessary to make sure all test activity is fully captured and for ease of uploading. If constant power isn't
|
|
||||||
available, keep the ignition on for at least one minute after your test to make sure power loss doesn't result
|
|
||||||
in loss of the last minute of testing data.
|
|
||||||
|
|
||||||
## Stationary ignition-only tests, part 1
|
|
||||||
|
|
||||||
1. Ignition on, but don't start engine, remain in Park
|
|
||||||
2. Open and close each door in a defined order: driver, passenger, rear left, rear right
|
|
||||||
3. Re-enter the vehicle, close the driver's door, and fasten the driver's seatbelt
|
|
||||||
4. Slowly press and release the accelerator pedal 3 times
|
|
||||||
5. Slowly press and release the brake pedal 3 times
|
|
||||||
6. Hold the brake and move the gearshift to reverse, then neutral, then drive, then sport/eco/etc if applicable
|
|
||||||
7. Return to Park, ignition off
|
|
||||||
|
|
||||||
Brake-pressed information may show up in several messages and signals, both as on/off states and as a percentage or
|
|
||||||
pressure. It may reflect a switch on the driver's brake pedal, or a pressure-threshold state, or signals to turn on
|
|
||||||
the rear brake lights. Start by identifying all the potential signals, and confirm while driving with ACC later.
|
|
||||||
|
|
||||||
Locate signals for all four door states if possible, but some cars only expose the driver's door state on the ADAS bus.
|
|
||||||
Driver/passenger door signals may or may not change positions for LHD vs RHD cars. For cars where only the driver's
|
|
||||||
door signal is available, the same signal may follow the driver.
|
|
||||||
|
|
||||||
## Stationary ignition-only tests, part 2
|
|
||||||
|
|
||||||
1. Ignition on, but don't start engine, remain in Park
|
|
||||||
2. Press each ACC button in a defined order: main switch on/off, set, resume, cancel, accel, decel, gap adjust
|
|
||||||
3. Set the left turn signal for about five seconds
|
|
||||||
4. Operate the left turn signal one time in its touch-to-pass mode
|
|
||||||
5. Set the right turn signal for about five seconds
|
|
||||||
6. Operate the right turn signal one time in its touch-to-pass mode
|
|
||||||
7. Set the hazard / emergency indicator switch for about five seconds
|
|
||||||
8. Ignition off
|
|
||||||
|
|
||||||
Your vehicle may have a momentary-press main ACC switch or a physical toggle that remains set. Actual ACC engagement
|
|
||||||
isn't necessary for purposes of detecting the ACC button presses.
|
|
||||||
|
|
||||||
## Steering angle and steering torque tests
|
|
||||||
|
|
||||||
Power steering should be available. On ICE cars, engine RPM may be present.
|
|
||||||
|
|
||||||
1. Ignition on, start engine if applicable, remain in Park
|
|
||||||
2. Rotate the steering wheel as follows, with a few seconds pause between each step
|
|
||||||
* Start as close to exact center as possible
|
|
||||||
* Turn to 45 degrees right and hold
|
|
||||||
* Turn to 90 degrees right and hold
|
|
||||||
* Turn to 180 degrees right and hold
|
|
||||||
* Turn to full lock right and hold, with firm pressure against lock
|
|
||||||
* Release the wheel and allow it to bounce back slightly from lock
|
|
||||||
* Turn to 180 degrees left and hold
|
|
||||||
* Return to center and release
|
|
||||||
3. Ignition off
|
|
||||||
|
|
||||||
Performing the full test to the right, followed by an abbreviated test to the left, helps give additional confirmation
|
|
||||||
of signal scale, and sign/direction for both the steering wheel angle and driver input torque signals.
|
|
||||||
|
|
||||||
## Low speed / parking lot driving tests
|
|
||||||
|
|
||||||
Before this test, drive to a place like an empty parking lot where you are free to drive in a series of curves.
|
|
||||||
|
|
||||||
1. Ignition on, start engine if applicable, prepare to drive
|
|
||||||
2. Slowly (10-20mph at most) drive a figure-8 if possible, or at least one sharp left and one sharp right.
|
|
||||||
3. Come to a complete stop
|
|
||||||
4. When and where safe, drive in reverse for a short distance (10-15 feet)
|
|
||||||
5. Park the car in a safe place, ignition off
|
|
||||||
|
|
||||||
## High speed / highway driving tests
|
|
||||||
|
|
||||||
Select a place and time where you can safely set cruise control at normal travel speeds with little interference from
|
|
||||||
traffic ahead, and safely test the response of your factory lane guidance system.
|
|
||||||
|
|
||||||
1. Ignition on, start engine if applicable, prepare to drive
|
|
||||||
2. When safely able, engage adaptive cruise control below 50 mph
|
|
||||||
3. When safely able, use the ACC buttons to accelerate to 50mph, then 55mph, then 60mph
|
|
||||||
4. Disengage adaptive cruise
|
|
||||||
5. When safely able, allow your factory lane guidance to prevent lane departures, 2-3 times on both the left and right
|
|
||||||
|
|
||||||
The series of setpoints can be adjusted to local traffic regulations, and of course metric units. The specific cruise
|
|
||||||
setpoints are useful for locating the ACC HUD signals later, and confirming their precise scaling. When the car reaches
|
|
||||||
and holds the setpoint, that can also provide additional confirmation of wheel speed scaling.
|
|
||||||
@@ -1,9 +1,3 @@
|
|||||||
# openpilot glossary
|
# openpilot glossary
|
||||||
|
|
||||||
* **onroad**: openpilot's system state while ignition is on
|
{{GLOSSARY_DEFINITIONS}}
|
||||||
* **offroad**: openpilot's system state while ignition is off
|
|
||||||
* **route**: a route is a recording of an onroad session
|
|
||||||
* **segment**: routes are split into one minute chunks called segments.
|
|
||||||
* **comma connect**: the web viewer for all your routes; check it out at [connect.comma.ai](https://connect.comma.ai).
|
|
||||||
* **panda**: this is the secondary processor on the device that implements the functional safety and directly talks to the car over CAN. See the [panda repo](https://github.com/commaai/panda).
|
|
||||||
* **comma 3X**: the latest hardware by comma.ai for running openpilot. more info at [comma.ai/shop](https://comma.ai/shop).
|
|
||||||
|
|||||||
@@ -6,9 +6,9 @@ Check out our [Python library](https://github.com/commaai/openpilot/blob/master/
|
|||||||
|
|
||||||
For each segment, openpilot records the following log types:
|
For each segment, openpilot records the following log types:
|
||||||
|
|
||||||
## rlog.bz2
|
## rlog.zst
|
||||||
|
|
||||||
rlogs contain all the messages passed amongst openpilot's processes. See [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for a list of all the logged services. They're a bzip2 archive of the serialized capnproto messages.
|
rlogs contain all the messages passed amongst openpilot's processes. See [cereal/services.py](https://github.com/commaai/openpilot/blob/master/cereal/services.py) for a list of all the logged services. They're a zstd archive of the serialized [Cap’n Proto](https://capnproto.org/) messages.
|
||||||
|
|
||||||
## {f,e,d}camera.hevc
|
## {f,e,d}camera.hevc
|
||||||
|
|
||||||
@@ -18,12 +18,10 @@ Each camera stream is H.265 encoded and written to its respective file.
|
|||||||
* `ecamera.hevc` is the wide road camera
|
* `ecamera.hevc` is the wide road camera
|
||||||
* `dcamera.hevc` is the driver camera
|
* `dcamera.hevc` is the driver camera
|
||||||
|
|
||||||
## qlog.bz2 & qcamera.ts
|
## qlog.zst & qcamera.ts
|
||||||
|
|
||||||
qlogs are a decimated subset of the rlogs. Check out [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for the decimation.
|
qlogs are a decimated subset of the rlogs. Check out [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for the decimation.
|
||||||
|
|
||||||
|
|
||||||
qcameras are H.264 encoded, lower res versions of the fcamera.hevc. The video shown in [comma connect](https://connect.comma.ai/) is from the qcameras.
|
qcameras are H.264 encoded, lower res versions of the fcamera.hevc. The video shown in [comma connect](https://connect.comma.ai/) is from the qcameras.
|
||||||
|
|
||||||
|
qlogs and qcameras are designed to be small enough to upload instantly on slow internet, yet useful enough for most analysis and debugging.
|
||||||
qlogs and qcameras are designed to be small enough to upload instantly on slow internet and store forever, yet useful enough for most analysis and debugging.
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# How to Give Feedback
|
||||||
|
|
||||||
|
Feedback is one of the highest leverage ways to contribute to openpilot as a user.
|
||||||
|
|
||||||
|
## Driving
|
||||||
|
|
||||||
|
Got feedback about how your car drives?
|
||||||
|
Join the community Discord, then use the form in `#submit-feedback`.
|
||||||
|
|
||||||
|
Before posting feedback, please ensure:
|
||||||
|
|
||||||
|
- **openpilot is up to date** you should be on the latest openpilot release or nightly
|
||||||
|
- **both road-facing cameras have a clear view** your windshield is clean, lenses are clean, etc.
|
||||||
|
- **your device is mounted properly** your device must be mounted horizontally center and relatively high on the windshield
|
||||||
|
|
||||||
|
## Driver Monitoring
|
||||||
|
|
||||||
|
If you find DM annoying while being perfectly attentive, these are likely false positives and we want to fix them!
|
||||||
|
In general, driver monitoring feedback is very actionable, and we can fix your complaint within a release cycle.
|
||||||
|
|
||||||
|
To post your feedback:
|
||||||
|
|
||||||
|
1. Join the [community Discord](https://discord.comma.ai).
|
||||||
|
2. If driver camera recording is toggled off, temporarily enable driver camera recording in the settings until you reproduce the issue.
|
||||||
|
3. Using comma connect, identify the relevant segment and upload the segment's logs and driver camera.
|
||||||
|
4. Post the segment in the `#openpilot-experience` channel on Discord with a good description.
|
||||||
|
|
||||||
|
Before posting feedback, please ensure:
|
||||||
|
|
||||||
|
- **openpilot is up to date** you should be on the latest openpilot release or nightly
|
||||||
|
- **the driver camera has a clear view of the driver** ensure nothing blocks view of the driver (e.g. a cable), the lens is clean, etc.
|
||||||
|
- **your device is mounted properly** your device must be mounted horizontally center and relatively high on the windshield
|
||||||
|
|
||||||
|
## Other bugs
|
||||||
|
|
||||||
|
Got an issue with something else? Open an issue on our [GitHub issue tracker](https://github.com/commaai/openpilot/issues/new/choose).
|
||||||
@@ -7,25 +7,11 @@ This is the roadmap for the next major openpilot releases. Also check out
|
|||||||
* [Bounties](https://comma.ai/bounties) for paid individual issues
|
* [Bounties](https://comma.ai/bounties) for paid individual issues
|
||||||
* [#current-projects](https://discord.com/channels/469524606043160576/1249579909739708446) in Discord for discussion on work-in-progress projects
|
* [#current-projects](https://discord.com/channels/469524606043160576/1249579909739708446) in Discord for discussion on work-in-progress projects
|
||||||
|
|
||||||
## openpilot 0.10
|
|
||||||
|
|
||||||
openpilot 0.10 will be the first release with a driving policy trained in
|
|
||||||
a [learned simulator](https://youtu.be/EqQNZXqzFSI).
|
|
||||||
|
|
||||||
* Driving model trained in a learned simulator
|
|
||||||
* Always-on driver monitoring (behind a toggle)
|
|
||||||
* GPS removed from the driving stack
|
|
||||||
* 100KB qlogs
|
|
||||||
* `nightly` pushed after 1000 hours of hardware-in-the-loop testing
|
|
||||||
* Car interface code moved into [opendbc](https://github.com/commaai/opendbc)
|
|
||||||
* openpilot on PC for Linux x86, Linux arm64, and Mac (Apple Silicon)
|
|
||||||
|
|
||||||
## openpilot 1.0
|
## openpilot 1.0
|
||||||
|
|
||||||
openpilot 1.0 will feature a fully end-to-end driving policy.
|
openpilot 1.0 will feature a fully end-to-end driving policy.
|
||||||
|
|
||||||
* End-to-end longitudinal control in Chill mode
|
* End-to-end longitudinal control in Chill mode
|
||||||
* Automatic Emergency Braking (AEB)
|
|
||||||
* Driver monitoring with sleep detection
|
* Driver monitoring with sleep detection
|
||||||
* Rolling updates/releases pushed out by CI
|
* Rolling updates/releases pushed out by CI
|
||||||
* [panda safety 1.0](https://github.com/orgs/commaai/projects/27)
|
* [panda safety 1.0](https://github.com/orgs/commaai/projects/27)
|
||||||
|
|||||||
@@ -1,44 +0,0 @@
|
|||||||
[data-tooltip] {
|
|
||||||
position: relative;
|
|
||||||
display: inline-block;
|
|
||||||
border-bottom: 1px dotted black;
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-tooltip] .tooltip-content {
|
|
||||||
width: max-content;
|
|
||||||
max-width: 25em;
|
|
||||||
position: absolute;
|
|
||||||
top: 100%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translateX(-50%);
|
|
||||||
background-color: white;
|
|
||||||
color: #404040;
|
|
||||||
box-shadow: 0 4px 14px 0 rgba(0,0,0,.2), 0 0 0 1px rgba(0,0,0,.05);
|
|
||||||
padding: 10px;
|
|
||||||
font: 14px/1.5 Lato, proxima-nova, Helvetica Neue, Arial, sans-serif;
|
|
||||||
text-decoration: none;
|
|
||||||
opacity: 0;
|
|
||||||
visibility: hidden;
|
|
||||||
transition: opacity 0.1s, visibility 0s;
|
|
||||||
z-index: 1000;
|
|
||||||
pointer-events: none; /* Prevent accidental interaction */
|
|
||||||
}
|
|
||||||
|
|
||||||
[data-tooltip]:hover .tooltip-content {
|
|
||||||
opacity: 1;
|
|
||||||
visibility: visible;
|
|
||||||
pointer-events: auto; /* Allow interaction when visible */
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-content .tooltip-glossary-link {
|
|
||||||
display: inline-block;
|
|
||||||
margin-top: 8px;
|
|
||||||
font-size: 12px;
|
|
||||||
color: #007bff;
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
.tooltip-content .tooltip-glossary-link:hover {
|
|
||||||
color: #0056b3;
|
|
||||||
text-decoration: underline;
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
import posixpath
|
||||||
|
import re
|
||||||
|
import tomllib
|
||||||
|
import xml.etree.ElementTree as ET
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from markdown.extensions import Extension
|
||||||
|
from markdown.preprocessors import Preprocessor
|
||||||
|
from markdown.treeprocessors import Treeprocessor
|
||||||
|
|
||||||
|
from zensical.extensions.links import LinksTreeprocessor
|
||||||
|
|
||||||
|
GlossaryTerm = tuple[str, re.Pattern[str], str]
|
||||||
|
|
||||||
|
GLOSSARY_FILE = Path(__file__).with_name("glossary.toml")
|
||||||
|
GLOSSARY_PAGE = "concepts/glossary.md"
|
||||||
|
GLOSSARY_PLACEHOLDER = "{{GLOSSARY_DEFINITIONS}}"
|
||||||
|
|
||||||
|
SKIP_TAGS = {
|
||||||
|
"a",
|
||||||
|
"code",
|
||||||
|
"h1",
|
||||||
|
"h2",
|
||||||
|
"h3",
|
||||||
|
"h4",
|
||||||
|
"h5",
|
||||||
|
"h6",
|
||||||
|
"kbd",
|
||||||
|
"pre",
|
||||||
|
"script",
|
||||||
|
"style",
|
||||||
|
}
|
||||||
|
|
||||||
|
def clean_tooltip(description: str) -> str:
|
||||||
|
text = re.sub(r"\[([^\]]+)]\([^)]+\)", r"\1", description)
|
||||||
|
text = re.sub(r"`([^`]+)`", r"\1", text)
|
||||||
|
text = re.sub(r"[*_~]", "", text)
|
||||||
|
return re.sub(r"\s+", " ", text).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def load_glossary() -> tuple[list[GlossaryTerm], str]:
|
||||||
|
with GLOSSARY_FILE.open("rb") as f:
|
||||||
|
glossary_data = tomllib.load(f).get("glossary", {})
|
||||||
|
|
||||||
|
glossary: list[GlossaryTerm] = []
|
||||||
|
rendered = []
|
||||||
|
for key, value in glossary_data.items():
|
||||||
|
label = str(key).strip().replace("_", " ")
|
||||||
|
description = str(value).strip()
|
||||||
|
if not description:
|
||||||
|
continue
|
||||||
|
|
||||||
|
slug = label.replace(" ", "-").replace("_", "-").lower()
|
||||||
|
glossary.append((slug, re.compile(rf"(?<!\w){re.escape(label)}(?!\w)", re.IGNORECASE), clean_tooltip(description)))
|
||||||
|
rendered.append(f'* <span id="{slug}"></span>**{label}**: {description}')
|
||||||
|
|
||||||
|
return glossary, "\n".join(rendered)
|
||||||
|
|
||||||
|
|
||||||
|
class GlossaryPreprocessor(Preprocessor):
|
||||||
|
def __init__(self, md, glossary: str):
|
||||||
|
super().__init__(md)
|
||||||
|
self.glossary = glossary
|
||||||
|
|
||||||
|
def run(self, lines: list[str]) -> list[str]:
|
||||||
|
markdown = "\n".join(lines)
|
||||||
|
if GLOSSARY_PLACEHOLDER not in markdown:
|
||||||
|
return lines
|
||||||
|
return markdown.replace(GLOSSARY_PLACEHOLDER, self.glossary).splitlines()
|
||||||
|
|
||||||
|
|
||||||
|
class GlossaryTreeprocessor(Treeprocessor):
|
||||||
|
def __init__(self, md, glossary: list[GlossaryTerm]):
|
||||||
|
super().__init__(md)
|
||||||
|
self.glossary = glossary
|
||||||
|
self.seen: set[str] = set()
|
||||||
|
|
||||||
|
def run(self, root: ET.Element) -> None:
|
||||||
|
at = self.md.treeprocessors.get_index_for_name("zrelpath")
|
||||||
|
processor = self.md.treeprocessors[at]
|
||||||
|
if not isinstance(processor, LinksTreeprocessor):
|
||||||
|
raise TypeError("Links processor not registered")
|
||||||
|
if processor.path == GLOSSARY_PAGE:
|
||||||
|
return
|
||||||
|
|
||||||
|
self.seen.clear()
|
||||||
|
glossary_href = f"{posixpath.relpath(GLOSSARY_PAGE, posixpath.dirname(processor.path) or '.')}#"
|
||||||
|
self._walk(root, glossary_href)
|
||||||
|
|
||||||
|
def _walk(self, element: ET.Element, glossary_href: str) -> None:
|
||||||
|
if element.tag in SKIP_TAGS or element.attrib.get("data-glossary-skip") is not None:
|
||||||
|
return
|
||||||
|
|
||||||
|
self._replace(element, glossary_href)
|
||||||
|
|
||||||
|
idx = 0
|
||||||
|
while idx < len(element):
|
||||||
|
child = element[idx]
|
||||||
|
self._walk(child, glossary_href)
|
||||||
|
idx = self._replace(element, glossary_href, idx) + 1
|
||||||
|
|
||||||
|
def _replace(self, parent: ET.Element, glossary_href: str, index: int | None = None) -> int:
|
||||||
|
child = None if index is None else parent[index]
|
||||||
|
text = parent.text if child is None else child.tail
|
||||||
|
pieces = self._pieces(text or "", glossary_href)
|
||||||
|
if not pieces:
|
||||||
|
return -1 if index is None else index
|
||||||
|
|
||||||
|
if child is None:
|
||||||
|
parent.text = pieces[0] if isinstance(pieces[0], str) else ""
|
||||||
|
# Insert replacements for parent.text before the first existing child.
|
||||||
|
insert_at = -1
|
||||||
|
else:
|
||||||
|
assert index is not None
|
||||||
|
child.tail = pieces[0] if isinstance(pieces[0], str) else ""
|
||||||
|
insert_at = index
|
||||||
|
|
||||||
|
start = 1 if isinstance(pieces[0], str) else 0
|
||||||
|
previous = child
|
||||||
|
|
||||||
|
for piece in pieces[start:]:
|
||||||
|
if isinstance(piece, str):
|
||||||
|
previous.tail = (previous.tail or "") + piece
|
||||||
|
continue
|
||||||
|
|
||||||
|
insert_at += 1
|
||||||
|
parent.insert(insert_at, piece)
|
||||||
|
previous = piece
|
||||||
|
|
||||||
|
return insert_at
|
||||||
|
|
||||||
|
def _pieces(self, text: str, glossary_href: str) -> list[str | ET.Element]:
|
||||||
|
if not text.strip():
|
||||||
|
return []
|
||||||
|
|
||||||
|
pieces: list[str | ET.Element] = []
|
||||||
|
cursor = 0
|
||||||
|
|
||||||
|
while True:
|
||||||
|
best = None
|
||||||
|
for slug, pattern, tooltip in self.glossary:
|
||||||
|
if slug in self.seen:
|
||||||
|
continue
|
||||||
|
|
||||||
|
found = pattern.search(text, cursor)
|
||||||
|
if found is None:
|
||||||
|
continue
|
||||||
|
|
||||||
|
candidate = (slug, tooltip, found.start(), found.end())
|
||||||
|
if best is None:
|
||||||
|
best = candidate
|
||||||
|
continue
|
||||||
|
|
||||||
|
_, _, best_start, best_end = best
|
||||||
|
_, _, current_start, current_end = candidate
|
||||||
|
if current_start < best_start:
|
||||||
|
best = candidate
|
||||||
|
continue
|
||||||
|
|
||||||
|
if current_start == best_start and current_end - current_start > best_end - best_start:
|
||||||
|
best = candidate
|
||||||
|
|
||||||
|
if best is None:
|
||||||
|
break
|
||||||
|
|
||||||
|
slug, tooltip, start, end = best
|
||||||
|
if start > cursor:
|
||||||
|
pieces.append(text[cursor:start])
|
||||||
|
|
||||||
|
link = ET.Element(
|
||||||
|
"a",
|
||||||
|
{
|
||||||
|
"class": "glossary-term",
|
||||||
|
"data-glossary-term": "",
|
||||||
|
"href": f"{glossary_href}{slug}",
|
||||||
|
},
|
||||||
|
)
|
||||||
|
ET.SubElement(link, "span", {"class": "glossary-term__label"}).text = text[start:end]
|
||||||
|
ET.SubElement(
|
||||||
|
link,
|
||||||
|
"span",
|
||||||
|
{
|
||||||
|
"class": "glossary-term__tooltip",
|
||||||
|
"data-search-exclude": "",
|
||||||
|
},
|
||||||
|
).text = tooltip
|
||||||
|
pieces.append(link)
|
||||||
|
self.seen.add(slug)
|
||||||
|
cursor = end
|
||||||
|
|
||||||
|
if not pieces:
|
||||||
|
return []
|
||||||
|
if cursor < len(text):
|
||||||
|
pieces.append(text[cursor:])
|
||||||
|
return pieces
|
||||||
|
|
||||||
|
|
||||||
|
class GlossaryExtension(Extension):
|
||||||
|
def extendMarkdown(self, md) -> None:
|
||||||
|
md.registerExtension(self)
|
||||||
|
glossary, rendered = load_glossary()
|
||||||
|
|
||||||
|
md.preprocessors.register(
|
||||||
|
GlossaryPreprocessor(md, rendered),
|
||||||
|
"docs-ext-glossary-preprocessor",
|
||||||
|
27,
|
||||||
|
)
|
||||||
|
md.treeprocessors.register(
|
||||||
|
GlossaryTreeprocessor(md, glossary),
|
||||||
|
"docs-ext-glossary-treeprocessor",
|
||||||
|
0,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def makeExtension(**kwargs) -> GlossaryExtension:
|
||||||
|
return GlossaryExtension(**kwargs)
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
[glossary]
|
||||||
|
onroad = "openpilot's system state while ignition is on."
|
||||||
|
offroad = "openpilot's system state while ignition is off."
|
||||||
|
route = "A route is a recording of an onroad session."
|
||||||
|
segment = "Routes are split into one minute chunks called segments."
|
||||||
|
"comma connect" = "The web viewer for all your routes; check it out at [connect.comma.ai](https://connect.comma.ai)."
|
||||||
|
panda = "The secondary processor on the device that implements the functional safety and directly talks to the car over CAN. See the [panda repo](https://github.com/commaai/panda)."
|
||||||
|
"comma four" = "The latest hardware by comma.ai for running openpilot. More info at [comma.ai/shop/comma-four](https://www.comma.ai/shop/comma-four)."
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
# What is openpilot?
|
|
||||||
|
|
||||||
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](https://github.com/commaai/openpilot/blob/master/docs/INTEGRATION.md) and [limitations](https://github.com/commaai/openpilot/blob/master/docs/LIMITATIONS.md).
|
|
||||||
|
|
||||||
|
|
||||||
## How do I use it?
|
|
||||||
|
|
||||||
openpilot is designed to be used on the comma 3X.
|
|
||||||
|
|
||||||
## How does it work?
|
|
||||||
|
|
||||||
In short, openpilot uses the car's existing APIs for the built-in [ADAS](https://en.wikipedia.org/wiki/Advanced_driver-assistance_system) system and simply provides better acceleration, braking, and steering inputs than the stock system.
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
import re
|
|
||||||
import tomllib
|
|
||||||
|
|
||||||
def load_glossary(file_path="docs/glossary.toml"):
|
|
||||||
with open(file_path, "rb") as f:
|
|
||||||
glossary_data = tomllib.load(f)
|
|
||||||
return glossary_data.get("glossary", {})
|
|
||||||
|
|
||||||
def generate_anchor_id(name):
|
|
||||||
return name.replace(" ", "-").replace("_", "-").lower()
|
|
||||||
|
|
||||||
def format_markdown_term(name, definition):
|
|
||||||
anchor_id = generate_anchor_id(name)
|
|
||||||
markdown = f"* [**{name.replace('_', ' ').title()}**](#{anchor_id})"
|
|
||||||
if definition.get("abbreviation"):
|
|
||||||
markdown += f" *({definition['abbreviation']})*"
|
|
||||||
if definition.get("description"):
|
|
||||||
markdown += f": {definition['description']}\n"
|
|
||||||
return markdown
|
|
||||||
|
|
||||||
def glossary_markdown(vocabulary):
|
|
||||||
markdown = ""
|
|
||||||
for category, terms in vocabulary.items():
|
|
||||||
markdown += f"## {category.replace('_', ' ').title()}\n\n"
|
|
||||||
for name, definition in terms.items():
|
|
||||||
markdown += format_markdown_term(name, definition)
|
|
||||||
return markdown
|
|
||||||
|
|
||||||
def format_tooltip_html(term_key, definition, html):
|
|
||||||
display_term = term_key.replace("_", " ").title()
|
|
||||||
clean_description = re.sub(r"\[(.+)]\(.+\)", r"\1", definition["description"])
|
|
||||||
glossary_link = (
|
|
||||||
f"<a href='/concepts/glossary#{term_key}' class='tooltip-glossary-link' title='View in glossary'>Glossary🔗</a>"
|
|
||||||
)
|
|
||||||
return re.sub(
|
|
||||||
re.escape(display_term),
|
|
||||||
lambda
|
|
||||||
match: f"<span data-tooltip>{match.group(0)}<span class='tooltip-content'>{clean_description} {glossary_link}</span></span>",
|
|
||||||
html,
|
|
||||||
flags=re.IGNORECASE,
|
|
||||||
)
|
|
||||||
|
|
||||||
def apply_tooltip(_term_key, _definition, pattern, html):
|
|
||||||
return re.sub(
|
|
||||||
pattern,
|
|
||||||
lambda match: format_tooltip_html(_term_key, _definition, match.group(0)),
|
|
||||||
html,
|
|
||||||
flags=re.IGNORECASE,
|
|
||||||
)
|
|
||||||
|
|
||||||
def tooltip_html(vocabulary, html):
|
|
||||||
for _category, terms in vocabulary.items():
|
|
||||||
for term_key, definition in terms.items():
|
|
||||||
if definition.get("description"):
|
|
||||||
pattern = rf"(?<!\w){re.escape(term_key.replace('_', ' ').title())}(?![^<]*<\/a>)(?!\([^)]*\))"
|
|
||||||
html = apply_tooltip(term_key, definition, pattern, html)
|
|
||||||
return html
|
|
||||||
|
|
||||||
# Page Hooks
|
|
||||||
def on_page_markdown(markdown, **kwargs):
|
|
||||||
glossary = load_glossary()
|
|
||||||
return markdown.replace("{{GLOSSARY_DEFINITIONS}}", glossary_markdown(glossary))
|
|
||||||
|
|
||||||
def on_page_content(html, **kwargs):
|
|
||||||
if kwargs.get("page").title == "Glossary":
|
|
||||||
return html
|
|
||||||
glossary = load_glossary()
|
|
||||||
return tooltip_html(glossary, html)
|
|
||||||
@@ -8,7 +8,7 @@ A car port enables openpilot support on a particular car. Each car model openpil
|
|||||||
|
|
||||||
# Structure of a car port
|
# Structure of a car port
|
||||||
|
|
||||||
Virtually all car-specific code is contained in two other repositories: [opendbc](https://github.com/commaai/opendbc) and [panda](https://github.com/commaai/panda).
|
All car-specific code is contained in the [opendbc](https://github.com/commaai/opendbc) project.
|
||||||
|
|
||||||
## opendbc
|
## opendbc
|
||||||
|
|
||||||
@@ -23,8 +23,8 @@ Each car brand is supported by a standard interface structure in `opendbc/car/[b
|
|||||||
|
|
||||||
## safety
|
## safety
|
||||||
|
|
||||||
* `opendbc_repo/opendbc/safety/modes/[brand].h`: Brand-specific safety logic
|
* `opendbc/safety/modes/[brand].h`: Brand-specific safety logic
|
||||||
* `opendbc_repo/opendbc/safety/tests/test_[brand].py`: Brand-specific safety CI tests
|
* `opendbc/safety/tests/test_[brand].py`: Brand-specific safety CI tests
|
||||||
|
|
||||||
## openpilot
|
## openpilot
|
||||||
|
|
||||||
@@ -32,8 +32,20 @@ For historical reasons, openpilot still contains a small amount of car-specific
|
|||||||
|
|
||||||
* `selfdrive/car/car_specific.py`: Brand-specific event logic
|
* `selfdrive/car/car_specific.py`: Brand-specific event logic
|
||||||
|
|
||||||
# Overview
|
# How do I port car?
|
||||||
|
|
||||||
[Jason Young](https://github.com/jyoung8607) gave a talk at COMMA_CON with an overview of the car porting process. The talk is available on YouTube:
|
[Jason Young](https://github.com/jyoung8607) gave a talk at COMMA_CON with an overview of the car porting process. The talk is available on YouTube:
|
||||||
|
|
||||||
https://www.youtube.com/watch?v=XxPS5TpTUnI
|
https://www.youtube.com/watch?v=XxPS5TpTUnI
|
||||||
|
|
||||||
|
## Brand Port
|
||||||
|
|
||||||
|
A brand port is a port of openpilot to a substantially new car brand or platform within a brand.
|
||||||
|
|
||||||
|
Here's an example of one: https://github.com/commaai/openpilot/pull/23331.
|
||||||
|
|
||||||
|
## Model Port
|
||||||
|
|
||||||
|
A model port is a port of openpilot to a new car model within an already supported brand. Model ports are easier than brand ports because the car's existing APIs are already known.
|
||||||
|
|
||||||
|
Here's an example of one: https://github.com/commaai/openpilot/pull/30672/.
|
||||||
@@ -1,15 +1,15 @@
|
|||||||
# connect to a comma 3X
|
# connect to a comma 3X or comma four
|
||||||
|
|
||||||
A comma 3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console).
|
A comma device is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console).
|
||||||
|
|
||||||
## Serial Console
|
## Serial Console
|
||||||
|
|
||||||
On both the comma three and 3X, the serial console is accessible from the main OBD-C port.
|
On the comma 3X, the serial console is accessible from the main OBD-C port, forwarded through the panda.
|
||||||
Connect the comma 3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power.
|
Access it using `panda/scripts/som_debug.sh`.
|
||||||
|
|
||||||
On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/scripts/serial.sh` can be used to connect.
|
comma four also exposes a serial console, albeit through an internal debug connector. Dedicated debug hardware coming soon to the comma shop.
|
||||||
|
|
||||||
On the comma 3X, the serial console is accessible through the [panda](https://github.com/commaai/panda) using the `panda/tests/som_debug.sh` script.
|
Login to the default user with:
|
||||||
|
|
||||||
* Username: `comma`
|
* Username: `comma`
|
||||||
* Password: `comma`
|
* Password: `comma`
|
||||||
@@ -25,7 +25,7 @@ In order to SSH into your device, you'll need a GitHub account with SSH keys. Se
|
|||||||
* Port: `22`
|
* Port: `22`
|
||||||
|
|
||||||
Here's an example command for connecting to your device using its tethered connection:<br />
|
Here's an example command for connecting to your device using its tethered connection:<br />
|
||||||
`ssh comma@192.168.43.1`
|
`ssh comma@192.168.43.1 -i ~/.ssh/my_github_key`
|
||||||
|
|
||||||
For doing development work on device, it's recommended to use [SSH agent forwarding](https://docs.github.com/en/developers/overview/using-ssh-agent-forwarding).
|
For doing development work on device, it's recommended to use [SSH agent forwarding](https://docs.github.com/en/developers/overview/using-ssh-agent-forwarding).
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ In order to use ADB on your device, you'll need to perform the following steps u
|
|||||||
* Here's an example command for connecting to your device using its tethered connection: `adb connect 192.168.43.1:5555`
|
* Here's an example command for connecting to your device using its tethered connection: `adb connect 192.168.43.1:5555`
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> The default port for ADB is 5555 on the comma 3X.
|
> The default port for ADB is 5555.
|
||||||
|
|
||||||
For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb).
|
For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb).
|
||||||
|
|
||||||
@@ -55,7 +55,7 @@ The public keys are only fetched from your GitHub account once. In order to upda
|
|||||||
|
|
||||||
The `id_rsa` key in this directory only works while your device is in the setup state with no software installed. After installation, that default key will be removed.
|
The `id_rsa` key in this directory only works while your device is in the setup state with no software installed. After installation, that default key will be removed.
|
||||||
|
|
||||||
#### ssh.comma.ai proxy
|
## ssh.comma.ai proxy
|
||||||
|
|
||||||
With a [comma prime subscription](https://comma.ai/connect), you can SSH into your comma device from anywhere.
|
With a [comma prime subscription](https://comma.ai/connect), you can SSH into your comma device from anywhere.
|
||||||
|
|
||||||
@@ -79,6 +79,7 @@ Host ssh.comma.ai
|
|||||||
```
|
```
|
||||||
ssh -i ~/.ssh/my_github_key -o ProxyCommand="ssh -i ~/.ssh/my_github_key -W %h:%p -p %p %h@ssh.comma.ai" comma@ffffffffffffffff
|
ssh -i ~/.ssh/my_github_key -o ProxyCommand="ssh -i ~/.ssh/my_github_key -W %h:%p -p %p %h@ssh.comma.ai" comma@ffffffffffffffff
|
||||||
```
|
```
|
||||||
|
|
||||||
(Replace `ffffffffffffffff` with your dongle_id)
|
(Replace `ffffffffffffffff` with your dongle_id)
|
||||||
|
|
||||||
### ssh.comma.ai host key fingerprint
|
### ssh.comma.ai host key fingerprint
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ Replaying is a critical tool for openpilot development and debugging.
|
|||||||
Just run `tools/replay/replay --demo`.
|
Just run `tools/replay/replay --demo`.
|
||||||
|
|
||||||
## Replaying CAN data
|
## Replaying CAN data
|
||||||
*Hardware required: jungle and comma 3X*
|
*Hardware required: jungle and comma four*
|
||||||
|
|
||||||
1. Connect your PC to a jungle.
|
1. Connect your PC to a jungle.
|
||||||
2.
|
2.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
In 30 minutes, we'll get an openpilot development environment set up on your computer and make some changes to openpilot's UI.
|
In 30 minutes, we'll get an openpilot development environment set up on your computer and make some changes to openpilot's UI.
|
||||||
|
|
||||||
And if you have a comma 3X, we'll deploy the change to your device for testing.
|
And if you have a comma four, we'll deploy the change to your device for testing.
|
||||||
|
|
||||||
## 1. Set up your development environment
|
## 1. Set up your development environment
|
||||||
|
|
||||||
@@ -20,7 +20,7 @@ source .venv/bin/activate
|
|||||||
|
|
||||||
Then, compile openpilot:
|
Then, compile openpilot:
|
||||||
```bash
|
```bash
|
||||||
scons -j$(nproc)
|
scons
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. Run replay
|
## 2. Run replay
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
getting-started/what-is-openpilot.md
|
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
# What is openpilot?
|
||||||
|
|
||||||
|
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](https://github.com/commaai/openpilot/blob/master/docs/INTEGRATION.md) and [limitations](https://github.com/commaai/openpilot/blob/master/docs/LIMITATIONS.md).
|
||||||
|
|
||||||
|
|
||||||
|
## How do I use it?
|
||||||
|
|
||||||
|
openpilot is designed to be used on the comma four.
|
||||||
|
|
||||||
|
## How does it work?
|
||||||
|
|
||||||
|
In short, openpilot uses the car's existing APIs for the built-in [ADAS](https://en.wikipedia.org/wiki/Advanced_driver-assistance_system) system and simply provides better acceleration, braking, and steering inputs than the stock system.
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
.md-logo img {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-term {
|
||||||
|
position: relative;
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-term__label {
|
||||||
|
border-bottom: 1px dotted currentColor;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-term__tooltip {
|
||||||
|
position: absolute;
|
||||||
|
top: calc(100% + 0.4rem);
|
||||||
|
left: 50%;
|
||||||
|
width: max-content;
|
||||||
|
max-width: min(30rem, 80vw);
|
||||||
|
padding: 0.65rem 0.8rem;
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
background: rgb(26 26 26 / 96%);
|
||||||
|
color: white;
|
||||||
|
box-shadow: 0 0.6rem 1.8rem rgb(0 0 0 / 22%);
|
||||||
|
font-size: 0.85rem;
|
||||||
|
line-height: 1.45;
|
||||||
|
opacity: 0;
|
||||||
|
pointer-events: none;
|
||||||
|
transform: translateX(-50%) translateY(-0.15rem);
|
||||||
|
transition: opacity 120ms ease, transform 120ms ease;
|
||||||
|
visibility: hidden;
|
||||||
|
z-index: 20;
|
||||||
|
}
|
||||||
|
|
||||||
|
.glossary-term:hover .glossary-term__tooltip,
|
||||||
|
.glossary-term:focus-visible .glossary-term__tooltip,
|
||||||
|
.glossary-term:focus-within .glossary-term__tooltip {
|
||||||
|
opacity: 1;
|
||||||
|
transform: translateX(-50%) translateY(0);
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@ source "$DIR/launch_env.sh"
|
|||||||
function agnos_init {
|
function agnos_init {
|
||||||
# TODO: move this to agnos
|
# TODO: move this to agnos
|
||||||
sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta
|
sudo rm -f /data/etc/NetworkManager/system-connections/*.nmmeta
|
||||||
|
rm -f /data/scons_cache/config.lock
|
||||||
|
|
||||||
# set success flag for current boot slot
|
# set success flag for current boot slot
|
||||||
sudo abctl --set_success
|
sudo abctl --set_success
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@ export VECLIB_MAXIMUM_THREADS=1
|
|||||||
export QCOM_PRIORITY=12
|
export QCOM_PRIORITY=12
|
||||||
|
|
||||||
if [ -z "$AGNOS_VERSION" ]; then
|
if [ -z "$AGNOS_VERSION" ]; then
|
||||||
export AGNOS_VERSION="16"
|
export AGNOS_VERSION="18.4"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export STAGING_ROOT="/data/safe_staging"
|
export STAGING_ROOT="/data/safe_staging"
|
||||||
|
|||||||
-44
@@ -1,44 +0,0 @@
|
|||||||
site_name: openpilot docs
|
|
||||||
repo_url: https://github.com/commaai/openpilot/
|
|
||||||
site_url: https://docs.comma.ai
|
|
||||||
|
|
||||||
exclude_docs: README.md
|
|
||||||
|
|
||||||
strict: true
|
|
||||||
docs_dir: docs
|
|
||||||
site_dir: docs_site/
|
|
||||||
|
|
||||||
hooks:
|
|
||||||
- docs/hooks/glossary.py
|
|
||||||
extra_css:
|
|
||||||
- css/tooltip.css
|
|
||||||
theme:
|
|
||||||
name: readthedocs
|
|
||||||
navigation_depth: 3
|
|
||||||
|
|
||||||
nav:
|
|
||||||
- Getting Started:
|
|
||||||
- What is openpilot?: getting-started/what-is-openpilot.md
|
|
||||||
- How-to:
|
|
||||||
- Turn the speed blue: how-to/turn-the-speed-blue.md
|
|
||||||
- Connect to a comma 3X: how-to/connect-to-comma.md
|
|
||||||
# - Make your first pull request: how-to/make-first-pr.md
|
|
||||||
#- Replay a drive: how-to/replay-a-drive.md
|
|
||||||
- Concepts:
|
|
||||||
- Logs: concepts/logs.md
|
|
||||||
- Safety: concepts/safety.md
|
|
||||||
- Glossary: concepts/glossary.md
|
|
||||||
- Car Porting:
|
|
||||||
- What is a car port?: car-porting/what-is-a-car-port.md
|
|
||||||
- Porting a car brand: car-porting/brand-port.md
|
|
||||||
- Porting a car model: car-porting/model-port.md
|
|
||||||
- Contributing:
|
|
||||||
- Roadmap: contributing/roadmap.md
|
|
||||||
#- Architecture: contributing/architecture.md
|
|
||||||
- Contributing Guide →: https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md
|
|
||||||
- Links:
|
|
||||||
- Blog →: https://blog.comma.ai
|
|
||||||
- Bounties →: https://comma.ai/bounties
|
|
||||||
- GitHub →: https://github.com/commaai
|
|
||||||
- Discord →: https://discord.comma.ai
|
|
||||||
- X →: https://x.com/comma_ai
|
|
||||||
+1
-1
Submodule msgq_repo updated: ed2777747d...9beb84af67
+1
-1
Submodule opendbc_repo updated: 96a96b80da...10e654bf21
@@ -1 +0,0 @@
|
|||||||
../third_party
|
|
||||||
+1
-1
Submodule panda updated: f5f296c65c...d994e8e800
+42
-49
@@ -20,24 +20,29 @@ dependencies = [
|
|||||||
# core
|
# core
|
||||||
"cffi",
|
"cffi",
|
||||||
"scons",
|
"scons",
|
||||||
"pycapnp",
|
"pycapnp==2.1.0", # 2.2 introduces a memory leak due to cyclic references
|
||||||
"Cython",
|
"Cython",
|
||||||
"setuptools",
|
"setuptools",
|
||||||
"numpy >=2.0",
|
"numpy >=2.0",
|
||||||
|
|
||||||
# vendored native dependencies
|
# vendored native dependencies
|
||||||
"bzip2 @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=bzip2",
|
"bzip2 @ git+https://github.com/commaai/dependencies.git@release-bzip2#subdirectory=bzip2",
|
||||||
"capnproto @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=capnproto",
|
"bootstrap-icons @ git+https://github.com/commaai/dependencies.git@release-bootstrap-icons#subdirectory=bootstrap-icons",
|
||||||
"eigen @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=eigen",
|
"capnproto @ git+https://github.com/commaai/dependencies.git@release-capnproto#subdirectory=capnproto",
|
||||||
"ffmpeg @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=ffmpeg",
|
"catch2 @ git+https://github.com/commaai/dependencies.git@release-catch2#subdirectory=catch2",
|
||||||
"libjpeg @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=libjpeg",
|
"acados @ git+https://github.com/commaai/dependencies.git@release-acados#subdirectory=acados",
|
||||||
"libyuv @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=libyuv",
|
"eigen @ git+https://github.com/commaai/dependencies.git@release-eigen#subdirectory=eigen",
|
||||||
"python3-dev @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=python3-dev",
|
"ffmpeg @ git+https://github.com/commaai/dependencies.git@release-ffmpeg#subdirectory=ffmpeg",
|
||||||
"zstd @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=zstd",
|
"libjpeg @ git+https://github.com/commaai/dependencies.git@release-libjpeg#subdirectory=libjpeg",
|
||||||
"ncurses @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=ncurses",
|
"libyuv @ git+https://github.com/commaai/dependencies.git@release-libyuv#subdirectory=libyuv",
|
||||||
"zeromq @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=zeromq",
|
"zstd @ git+https://github.com/commaai/dependencies.git@release-zstd#subdirectory=zstd",
|
||||||
"git-lfs @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=git-lfs",
|
"ncurses @ git+https://github.com/commaai/dependencies.git@release-ncurses#subdirectory=ncurses",
|
||||||
"gcc-arm-none-eabi @ git+https://github.com/commaai/dependencies.git@releases#subdirectory=gcc-arm-none-eabi",
|
"zeromq @ git+https://github.com/commaai/dependencies.git@release-zeromq#subdirectory=zeromq",
|
||||||
|
"libusb @ git+https://github.com/commaai/dependencies.git@release-libusb#subdirectory=libusb",
|
||||||
|
"json11 @ git+https://github.com/commaai/dependencies.git@release-json11#subdirectory=json11",
|
||||||
|
"git-lfs @ git+https://github.com/commaai/dependencies.git@release-git-lfs#subdirectory=git-lfs",
|
||||||
|
"gcc-arm-none-eabi @ git+https://github.com/commaai/dependencies.git@release-gcc-arm-none-eabi#subdirectory=gcc-arm-none-eabi",
|
||||||
|
"xvfb @ git+https://github.com/commaai/dependencies.git@release-xvfb#subdirectory=xvfb",
|
||||||
|
|
||||||
# body / webrtcd
|
# body / webrtcd
|
||||||
"av",
|
"av",
|
||||||
@@ -58,9 +63,6 @@ dependencies = [
|
|||||||
"json-rpc",
|
"json-rpc",
|
||||||
"websocket_client",
|
"websocket_client",
|
||||||
|
|
||||||
# acados deps
|
|
||||||
"casadi >=3.6.6", # 3.12 fixed in 3.6.6
|
|
||||||
|
|
||||||
# joystickd
|
# joystickd
|
||||||
"inputs",
|
"inputs",
|
||||||
|
|
||||||
@@ -73,7 +75,7 @@ dependencies = [
|
|||||||
"zstandard",
|
"zstandard",
|
||||||
|
|
||||||
# ui
|
# ui
|
||||||
"raylib > 5.5.0.3",
|
"raylib @ git+https://github.com/commaai/dependencies.git@release-raylib#subdirectory=raylib",
|
||||||
"qrcode",
|
"qrcode",
|
||||||
"jeepney",
|
"jeepney",
|
||||||
"pillow",
|
"pillow",
|
||||||
@@ -82,7 +84,7 @@ dependencies = [
|
|||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
docs = [
|
docs = [
|
||||||
"Jinja2",
|
"Jinja2",
|
||||||
"mkdocs",
|
"zensical",
|
||||||
]
|
]
|
||||||
|
|
||||||
testing = [
|
testing = [
|
||||||
@@ -94,7 +96,6 @@ testing = [
|
|||||||
"pytest-subtests",
|
"pytest-subtests",
|
||||||
# https://github.com/pytest-dev/pytest-xdist/pull/1229
|
# https://github.com/pytest-dev/pytest-xdist/pull/1229
|
||||||
"pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da",
|
"pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da",
|
||||||
"pytest-asyncio",
|
|
||||||
"pytest-mock",
|
"pytest-mock",
|
||||||
"ruff",
|
"ruff",
|
||||||
"codespell",
|
"codespell",
|
||||||
@@ -107,6 +108,7 @@ dev = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
|
"imgui @ git+https://github.com/commaai/dependencies.git@release-imgui#subdirectory=imgui",
|
||||||
"metadrive-simulator @ git+https://github.com/commaai/metadrive.git@minimal ; (platform_machine != 'aarch64')",
|
"metadrive-simulator @ git+https://github.com/commaai/metadrive.git@minimal ; (platform_machine != 'aarch64')",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -125,15 +127,17 @@ allow-direct-references = true
|
|||||||
|
|
||||||
[tool.pytest.ini_options]
|
[tool.pytest.ini_options]
|
||||||
minversion = "6.0"
|
minversion = "6.0"
|
||||||
addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
|
addopts = "--ignore=openpilot/ --ignore=opendbc/ --ignore=panda/ --ignore=rednose_repo/ --ignore=tinygrad_repo/ --ignore=teleoprtc_repo/ --ignore=msgq/ -Werror --strict-config --strict-markers --durations=10 -n auto --dist=loadgroup"
|
||||||
cpp_files = "test_*"
|
cpp_files = "test_*"
|
||||||
cpp_harness = "selfdrive/test/cpp_harness.py"
|
cpp_harness = "selfdrive/test/cpp_harness.py"
|
||||||
python_files = "test_*.py"
|
python_files = "test_*.py"
|
||||||
asyncio_default_fixture_loop_scope = "function"
|
|
||||||
markers = [
|
markers = [
|
||||||
"slow: tests that take awhile to run and can be skipped with -m 'not slow'",
|
"slow: tests that take awhile to run and can be skipped with -m 'not slow'",
|
||||||
"tici: tests that are only meant to run on the C3/C3X",
|
"tici: tests that are only meant to run on the C3/C3X",
|
||||||
"skip_tici_setup: mark test to skip tici setup fixture"
|
"skip_tici_setup: mark test to skip tici setup fixture",
|
||||||
|
"nocapture: don't capture test output",
|
||||||
|
"shared_download_cache: share download cache between tests",
|
||||||
|
"xdist_group_class_property: group tests by a property of the class that contains them",
|
||||||
]
|
]
|
||||||
testpaths = [
|
testpaths = [
|
||||||
"common",
|
"common",
|
||||||
@@ -149,7 +153,7 @@ quiet-level = 3
|
|||||||
# if you've got a short variable name that's getting flagged, add it here
|
# if you've got a short variable name that's getting flagged, add it here
|
||||||
ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite,ser"
|
ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite,ser"
|
||||||
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
|
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
|
||||||
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*, selfdrive/assets/offroad/mici_fcc.html"
|
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, *.pem, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*, selfdrive/assets/offroad/mici_fcc.html"
|
||||||
|
|
||||||
# https://docs.astral.sh/ruff/configuration/#using-pyprojecttoml
|
# https://docs.astral.sh/ruff/configuration/#using-pyprojecttoml
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
@@ -174,9 +178,7 @@ lint.ignore = [
|
|||||||
"UP045", "UP007", # these don't play nice with raylib atm
|
"UP045", "UP007", # these don't play nice with raylib atm
|
||||||
]
|
]
|
||||||
line-length = 160
|
line-length = 160
|
||||||
target-version ="py311"
|
|
||||||
exclude = [
|
exclude = [
|
||||||
"body",
|
|
||||||
"cereal",
|
"cereal",
|
||||||
"panda",
|
"panda",
|
||||||
"opendbc",
|
"opendbc",
|
||||||
@@ -185,7 +187,7 @@ exclude = [
|
|||||||
"tinygrad_repo",
|
"tinygrad_repo",
|
||||||
"teleoprtc",
|
"teleoprtc",
|
||||||
"teleoprtc_repo",
|
"teleoprtc_repo",
|
||||||
"third_party",
|
"third_party/copyparty",
|
||||||
"*.ipynb",
|
"*.ipynb",
|
||||||
"generated",
|
"generated",
|
||||||
]
|
]
|
||||||
@@ -195,7 +197,6 @@ lint.flake8-implicit-str-concat.allow-multiline = false
|
|||||||
"selfdrive".msg = "Use openpilot.selfdrive"
|
"selfdrive".msg = "Use openpilot.selfdrive"
|
||||||
"common".msg = "Use openpilot.common"
|
"common".msg = "Use openpilot.common"
|
||||||
"system".msg = "Use openpilot.system"
|
"system".msg = "Use openpilot.system"
|
||||||
"third_party".msg = "Use openpilot.third_party"
|
|
||||||
"tools".msg = "Use openpilot.tools"
|
"tools".msg = "Use openpilot.tools"
|
||||||
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
|
"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!"
|
||||||
"unittest".msg = "Use pytest"
|
"unittest".msg = "Use pytest"
|
||||||
@@ -206,13 +207,13 @@ lint.flake8-implicit-str-concat.allow-multiline = false
|
|||||||
"pyray.is_mouse_button_pressed".msg = "This can miss events. Use Widget._handle_mouse_press"
|
"pyray.is_mouse_button_pressed".msg = "This can miss events. Use Widget._handle_mouse_press"
|
||||||
"pyray.is_mouse_button_released".msg = "This can miss events. Use Widget._handle_mouse_release"
|
"pyray.is_mouse_button_released".msg = "This can miss events. Use Widget._handle_mouse_release"
|
||||||
"pyray.draw_text".msg = "Use a function (such as rl.draw_font_ex) that takes font as an argument"
|
"pyray.draw_text".msg = "Use a function (such as rl.draw_font_ex) that takes font as an argument"
|
||||||
|
"pyray.draw_texture".msg = "Use rl.draw_texture_ex for float position support"
|
||||||
|
|
||||||
[tool.ruff.format]
|
[tool.ruff.format]
|
||||||
quote-style = "preserve"
|
quote-style = "preserve"
|
||||||
|
|
||||||
[tool.ty.src]
|
[tool.ty.src]
|
||||||
exclude = [
|
exclude = [
|
||||||
"cereal/",
|
|
||||||
"msgq/",
|
"msgq/",
|
||||||
"msgq_repo/",
|
"msgq_repo/",
|
||||||
"opendbc/",
|
"opendbc/",
|
||||||
@@ -228,24 +229,16 @@ exclude = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[tool.ty.rules]
|
[tool.ty.rules]
|
||||||
# Ignore unresolved imports for Cython-compiled modules (.pyx)
|
unresolved-import = "ignore" # Cython-compiled modules (.pyx)
|
||||||
unresolved-import = "ignore"
|
unresolved-attribute = "ignore" # many from capnp and Cython modules
|
||||||
# Ignore unresolved attributes - many from capnp and Cython modules
|
invalid-method-override = "ignore" # signature variance issues
|
||||||
unresolved-attribute = "ignore"
|
possibly-missing-attribute = "ignore" # too many false positives
|
||||||
# Ignore invalid method overrides - signature variance issues
|
invalid-assignment = "ignore" # often intentional monkey-patching
|
||||||
invalid-method-override = "ignore"
|
no-matching-overload = "ignore" # numpy/ctypes overload matching issues
|
||||||
# Ignore possibly-missing-attribute - too many false positives
|
invalid-argument-type = "ignore" # many false positives from raylib, ctypes, numpy
|
||||||
possibly-missing-attribute = "ignore"
|
call-non-callable = "ignore" # false positives from dynamic types
|
||||||
# Ignore invalid assignment - often intentional monkey-patching
|
unsupported-operator = "ignore" # false positives from dynamic types
|
||||||
invalid-assignment = "ignore"
|
not-subscriptable = "ignore" # false positives from dynamic types
|
||||||
# Ignore no-matching-overload - numpy/ctypes overload matching issues
|
|
||||||
no-matching-overload = "ignore"
|
[tool.uv]
|
||||||
# Ignore invalid-argument-type - many false positives from raylib, ctypes, numpy
|
python-preference = "only-managed"
|
||||||
invalid-argument-type = "ignore"
|
|
||||||
# Ignore call-non-callable - false positives from dynamic types
|
|
||||||
call-non-callable = "ignore"
|
|
||||||
# Ignore unsupported-operator - false positives from dynamic types
|
|
||||||
unsupported-operator = "ignore"
|
|
||||||
# Ignore not-subscriptable - false positives from dynamic types
|
|
||||||
not-subscriptable = "ignore"
|
|
||||||
# not-iterable errors are now fixed
|
|
||||||
|
|||||||
+1
-1
Submodule rednose_repo updated: 6ccb8d0556...7ffefa3d88
+14
-10
@@ -16,6 +16,8 @@ if [ -z "$RELEASE_BRANCH" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
BUILD_BRANCH=release-mici-staging
|
||||||
|
|
||||||
|
|
||||||
# set git identity
|
# set git identity
|
||||||
source $DIR/identity.sh
|
source $DIR/identity.sh
|
||||||
@@ -26,7 +28,7 @@ mkdir -p $BUILD_DIR
|
|||||||
cd $BUILD_DIR
|
cd $BUILD_DIR
|
||||||
git init
|
git init
|
||||||
git remote add origin git@github.com:commaai/openpilot.git
|
git remote add origin git@github.com:commaai/openpilot.git
|
||||||
git checkout --orphan $RELEASE_BRANCH
|
git checkout --orphan $BUILD_BRANCH
|
||||||
|
|
||||||
# do the files copy
|
# do the files copy
|
||||||
echo "[-] copying files T=$SECONDS"
|
echo "[-] copying files T=$SECONDS"
|
||||||
@@ -46,14 +48,14 @@ git commit -a -m "openpilot v$VERSION release"
|
|||||||
|
|
||||||
# Build
|
# Build
|
||||||
export PYTHONPATH="$BUILD_DIR"
|
export PYTHONPATH="$BUILD_DIR"
|
||||||
scons -j$(nproc) --minimal
|
scons
|
||||||
|
|
||||||
if [ -z "$PANDA_DEBUG_BUILD" ]; then
|
if [ -z "$PANDA_DEBUG_BUILD" ]; then
|
||||||
# release panda fw
|
# release panda fw
|
||||||
CERT=/data/pandaextra/certs/release RELEASE=1 scons -j$(nproc) panda/
|
CERT=/data/pandaextra/certs/release RELEASE=1 scons panda/
|
||||||
else
|
else
|
||||||
# build with ALLOW_DEBUG=1 to enable features like experimental longitudinal
|
# build with ALLOW_DEBUG=1 to enable features like experimental longitudinal
|
||||||
scons -j$(nproc) panda/
|
scons panda/
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Ensure no submodules in release
|
# Ensure no submodules in release
|
||||||
@@ -72,8 +74,8 @@ find . -name '*.pyc' -delete
|
|||||||
find . -name 'moc_*' -delete
|
find . -name 'moc_*' -delete
|
||||||
find . -name '__pycache__' -delete
|
find . -name '__pycache__' -delete
|
||||||
rm -rf .sconsign.dblite Jenkinsfile release/
|
rm -rf .sconsign.dblite Jenkinsfile release/
|
||||||
rm -f selfdrive/modeld/models/*.onnx
|
rm -f selfdrive/modeld/models/*.onnx*
|
||||||
rm -f sunnypilot/modeld*/models/*.onnx
|
rm -f sunnypilot/modeld*/models/*.onnx*
|
||||||
|
|
||||||
find third_party/ -name '*x86*' -exec rm -r {} +
|
find third_party/ -name '*x86*' -exec rm -r {} +
|
||||||
find third_party/ -name '*Darwin*' -exec rm -r {} +
|
find third_party/ -name '*Darwin*' -exec rm -r {} +
|
||||||
@@ -94,9 +96,11 @@ cd $BUILD_DIR
|
|||||||
RELEASE=1 pytest -n0 -s selfdrive/test/test_onroad.py
|
RELEASE=1 pytest -n0 -s selfdrive/test/test_onroad.py
|
||||||
#pytest selfdrive/car/tests/test_car_interfaces.py
|
#pytest selfdrive/car/tests/test_car_interfaces.py
|
||||||
|
|
||||||
if [ ! -z "$RELEASE_BRANCH" ]; then
|
echo "[-] pushing release T=$SECONDS"
|
||||||
echo "[-] pushing release T=$SECONDS"
|
REFS=()
|
||||||
git push -f origin $RELEASE_BRANCH:$RELEASE_BRANCH
|
for branch in ${RELEASE_BRANCH//,/ }; do
|
||||||
fi
|
REFS+=("$BUILD_BRANCH:$branch")
|
||||||
|
done
|
||||||
|
git push -f origin "${REFS[@]}"
|
||||||
|
|
||||||
echo "[-] done T=$SECONDS"
|
echo "[-] done T=$SECONDS"
|
||||||
|
|||||||
@@ -45,6 +45,8 @@ cd $TARGET_DIR
|
|||||||
rm -rf .git/modules/
|
rm -rf .git/modules/
|
||||||
rm -f panda/board/obj/panda.bin.signed
|
rm -f panda/board/obj/panda.bin.signed
|
||||||
|
|
||||||
|
find selfdrive/modeld/models -name '*.onnx' -size +95M -exec ./common/file_chunker.py {} \;
|
||||||
|
|
||||||
# include source commit hash and build date in commit
|
# include source commit hash and build date in commit
|
||||||
GIT_HASH=$(git --git-dir=$SOURCE_DIR/.git rev-parse HEAD)
|
GIT_HASH=$(git --git-dir=$SOURCE_DIR/.git rev-parse HEAD)
|
||||||
GIT_COMMIT_DATE=$(git --git-dir=$SOURCE_DIR/.git show --no-patch --format='%ct %ci' HEAD)
|
GIT_COMMIT_DATE=$(git --git-dir=$SOURCE_DIR/.git show --no-patch --format='%ct %ci' HEAD)
|
||||||
|
|||||||
+85
-108
@@ -1,5 +1,10 @@
|
|||||||
import os
|
"""
|
||||||
import pickle
|
Copyright (c) 2021-, Haibin Wen, sunnypilot, and a number of other contributors.
|
||||||
|
|
||||||
|
This file is part of sunnypilot and is licensed under the MIT License.
|
||||||
|
See the LICENSE.md file in the root directory for more details.
|
||||||
|
"""
|
||||||
|
|
||||||
import sys
|
import sys
|
||||||
import hashlib
|
import hashlib
|
||||||
import json
|
import json
|
||||||
@@ -7,43 +12,8 @@ import re
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from datetime import datetime, UTC
|
from datetime import datetime, UTC
|
||||||
|
|
||||||
REQUIRED_OUTPUT_KEYS = frozenset({
|
|
||||||
"plan",
|
|
||||||
"lane_lines",
|
|
||||||
"road_edges",
|
|
||||||
"lead",
|
|
||||||
"desire_state",
|
|
||||||
"desire_pred",
|
|
||||||
"meta",
|
|
||||||
"lead_prob",
|
|
||||||
"lane_lines_prob",
|
|
||||||
"pose",
|
|
||||||
"wide_from_device_euler",
|
|
||||||
"road_transform",
|
|
||||||
"hidden_state",
|
|
||||||
})
|
|
||||||
OPTIONAL_OUTPUT_KEYS = frozenset({
|
|
||||||
"planplus",
|
|
||||||
"sim_pose",
|
|
||||||
"desired_curvature",
|
|
||||||
})
|
|
||||||
|
|
||||||
|
def create_short_name(full_name: str) -> str:
|
||||||
def validate_model_outputs(metadata_paths: list[Path]) -> None:
|
|
||||||
combined_keys: set[str] = set()
|
|
||||||
for path in metadata_paths:
|
|
||||||
with open(path, "rb") as f:
|
|
||||||
metadata = pickle.load(f)
|
|
||||||
combined_keys.update(metadata.get("output_slices", {}).keys())
|
|
||||||
missing = REQUIRED_OUTPUT_KEYS - combined_keys
|
|
||||||
if missing:
|
|
||||||
raise ValueError(f"Combined model metadata is missing required output keys: {sorted(missing)}")
|
|
||||||
detected_optional = sorted(OPTIONAL_OUTPUT_KEYS & combined_keys)
|
|
||||||
if detected_optional:
|
|
||||||
print(f"Optional output keys detected: {detected_optional}")
|
|
||||||
|
|
||||||
|
|
||||||
def create_short_name(full_name):
|
|
||||||
# Remove parentheses and extract alphanumeric words
|
# Remove parentheses and extract alphanumeric words
|
||||||
clean_name = re.sub(r'\([^)]*\)', '', full_name)
|
clean_name = re.sub(r'\([^)]*\)', '', full_name)
|
||||||
words = [re.sub(r'[^a-zA-Z0-9]', '', word) for word in clean_name.split() if re.sub(r'[^a-zA-Z0-9]', '', word)]
|
words = [re.sub(r'[^a-zA-Z0-9]', '', word) for word in clean_name.split() if re.sub(r'[^a-zA-Z0-9]', '', word)]
|
||||||
@@ -78,58 +48,74 @@ def create_short_name(full_name):
|
|||||||
return result[:8]
|
return result[:8]
|
||||||
|
|
||||||
|
|
||||||
def generate_metadata(model_path: Path, output_dir: Path, short_name: str):
|
def _read_pkl_bytes(pkl_path: Path) -> bytes:
|
||||||
model_path = model_path
|
manifest = Path(f"{pkl_path}.chunkmanifest")
|
||||||
output_path = output_dir
|
if manifest.exists():
|
||||||
base = model_path.stem
|
num_chunks = int(manifest.read_text().strip())
|
||||||
|
parts = []
|
||||||
|
for i in range(num_chunks):
|
||||||
|
chunk = Path(f"{pkl_path}.chunk{i + 1:02d}of{num_chunks:02d}")
|
||||||
|
parts.append(chunk.read_bytes())
|
||||||
|
return b''.join(parts)
|
||||||
|
return pkl_path.read_bytes()
|
||||||
|
|
||||||
# Define output files for tinygrad and metadata
|
|
||||||
tinygrad_file = output_path / f"{base}_tinygrad.pkl"
|
|
||||||
metadata_file = output_path / f"{base}_metadata.pkl"
|
|
||||||
|
|
||||||
if not tinygrad_file.exists() or not metadata_file.exists():
|
def _find_driving_pkl(output_path: Path) -> Path | None:
|
||||||
print(f"Error: Missing files for model {base} ({tinygrad_file} or {metadata_file})", file=sys.stderr)
|
for pattern in ('driving_tinygrad.pkl', 'driving_*_tinygrad.pkl'):
|
||||||
return
|
matches = sorted(output_path.glob(pattern))
|
||||||
|
if matches:
|
||||||
|
return matches[0]
|
||||||
|
for pattern in ('driving_tinygrad.pkl.chunkmanifest', 'driving_*_tinygrad.pkl.chunkmanifest'):
|
||||||
|
matches = sorted(output_path.glob(pattern))
|
||||||
|
if matches:
|
||||||
|
return Path(str(matches[0]).removesuffix('.chunkmanifest'))
|
||||||
|
return None
|
||||||
|
|
||||||
# Calculate the sha256 hashes
|
|
||||||
with open(tinygrad_file, 'rb') as f:
|
|
||||||
tinygrad_hash = hashlib.sha256(f.read()).hexdigest()
|
|
||||||
|
|
||||||
with open(metadata_file, 'rb') as f:
|
def _rename_pkl_with_chunks(old_pkl: Path, new_pkl: Path) -> Path:
|
||||||
metadata_hash = hashlib.sha256(f.read()).hexdigest()
|
manifest = Path(f"{old_pkl}.chunkmanifest")
|
||||||
|
if manifest.exists():
|
||||||
|
for f in sorted(old_pkl.parent.glob(f"{old_pkl.name}.chunk*")):
|
||||||
|
f.rename(old_pkl.parent / f.name.replace(old_pkl.name, new_pkl.name, 1))
|
||||||
|
return new_pkl
|
||||||
|
return old_pkl.rename(new_pkl)
|
||||||
|
|
||||||
# Rename the files if a custom file name is provided
|
|
||||||
if short_name:
|
|
||||||
tinygrad_file = tinygrad_file.rename(output_path / f"{base}_{short_name.lower()}_tinygrad.pkl")
|
|
||||||
metadata_file = metadata_file.rename(output_path / f"{base}_{short_name.lower()}_metadata.pkl")
|
|
||||||
|
|
||||||
# Build the metadata structure
|
def generate_chunked_model(driving_pkl: Path) -> dict:
|
||||||
model_type = "offPolicy" if "off_policy" in base else base.split("_")[-1]
|
tinygrad_hash = hashlib.sha256(_read_pkl_bytes(driving_pkl)).hexdigest()
|
||||||
|
|
||||||
model_metadata = {
|
chunks_config = []
|
||||||
"type": model_type,
|
manifest_file = Path(f"{driving_pkl}.chunkmanifest")
|
||||||
"artifact": {
|
if manifest_file.exists():
|
||||||
"file_name": tinygrad_file.name,
|
num_chunks = int(manifest_file.read_text().strip())
|
||||||
"download_uri": {
|
for i in range(num_chunks):
|
||||||
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/",
|
chunk_path = Path(f"{driving_pkl}.chunk{i + 1:02d}of{num_chunks:02d}")
|
||||||
"sha256": tinygrad_hash
|
if chunk_path.exists():
|
||||||
}
|
chunk_hash = hashlib.sha256(chunk_path.read_bytes()).hexdigest()
|
||||||
},
|
chunks_config.append({
|
||||||
"metadata": {
|
"file_name": chunk_path.name,
|
||||||
"file_name": metadata_file.name,
|
"sha256": chunk_hash
|
||||||
"download_uri": {
|
})
|
||||||
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/",
|
|
||||||
"sha256": metadata_hash
|
artifact_data = {
|
||||||
}
|
"file_name": driving_pkl.name,
|
||||||
|
"download_uri": {
|
||||||
|
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/",
|
||||||
|
"sha256": tinygrad_hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Return model metadata
|
if chunks_config:
|
||||||
return model_metadata
|
artifact_data["chunks"] = chunks_config
|
||||||
|
|
||||||
|
return {
|
||||||
|
"type": "chunked",
|
||||||
|
"artifact": artifact_data,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def create_metadata_json(models: list, output_dir: Path, custom_name=None, short_name=None, is_20hz=False, upstream_branch="unknown"):
|
def create_metadata_json(models: list, output_dir: Path, custom_name=None, short_name=None, is_20hz=False, upstream_branch="unknown") -> None:
|
||||||
metadata_json = {
|
bundle_json = {
|
||||||
"short_name": short_name,
|
"short_name": short_name,
|
||||||
"display_name": custom_name or upstream_branch,
|
"display_name": custom_name or upstream_branch,
|
||||||
"is_20hz": is_20hz,
|
"is_20hz": is_20hz,
|
||||||
@@ -145,50 +131,41 @@ def create_metadata_json(models: list, output_dir: Path, custom_name=None, short
|
|||||||
}
|
}
|
||||||
|
|
||||||
# Write metadata to output_dir
|
# Write metadata to output_dir
|
||||||
|
metadata_json = {
|
||||||
|
"bundles": [bundle_json]
|
||||||
|
}
|
||||||
|
|
||||||
with open(output_dir / "metadata.json", "w") as f:
|
with open(output_dir / "metadata.json", "w") as f:
|
||||||
json.dump(metadata_json, f, indent=2)
|
json.dump(metadata_json, f, indent=2)
|
||||||
|
print("Generated metadata.json")
|
||||||
print(f"Generated metadata.json with {len(models)} models.")
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import argparse
|
import argparse
|
||||||
import glob
|
|
||||||
|
|
||||||
parser = argparse.ArgumentParser(description="Generate metadata for model files")
|
parser = argparse.ArgumentParser(description="Generate metadata JSON for the compiled JIT model")
|
||||||
parser.add_argument("--model-dir", default="./models", help="Directory containing ONNX model files")
|
parser.add_argument("--model-dir", default="./models", help="Directory containing the model files")
|
||||||
parser.add_argument("--output-dir", default="./output", help="Output directory for metadata")
|
parser.add_argument("--output-dir", default="./output", help="Output directory for metadata")
|
||||||
parser.add_argument("--custom-name", help="Custom display name for the model")
|
parser.add_argument("--custom-name", help="Custom display name for the model")
|
||||||
parser.add_argument("--is-20hz", action="store_true", help="Whether this is a 20Hz model")
|
parser.add_argument("--is-20hz", action="store_true", help="Whether this is a 20Hz model")
|
||||||
parser.add_argument("--validate-only", action="store_true")
|
|
||||||
parser.add_argument("--upstream-branch", default="unknown", help="Upstream branch name")
|
parser.add_argument("--upstream-branch", default="unknown", help="Upstream branch name")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
if args.validate_only:
|
|
||||||
metadata_paths = glob.glob(os.path.join(args.model_dir, "*_metadata.pkl"))
|
|
||||||
if not metadata_paths:
|
|
||||||
print(f"No metadata files found in {args.model_dir}", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
validate_model_outputs([Path(p) for p in metadata_paths])
|
|
||||||
print(f"Validated {len(metadata_paths)} metadata files successfully.")
|
|
||||||
sys.exit(0)
|
|
||||||
|
|
||||||
# Find all ONNX files in the given directory
|
|
||||||
model_paths = glob.glob(os.path.join(args.model_dir, "*.onnx"))
|
|
||||||
if not model_paths:
|
|
||||||
print(f"No ONNX files found in {args.model_dir}", file=sys.stderr)
|
|
||||||
sys.exit(1)
|
|
||||||
|
|
||||||
_output_dir = Path(args.output_dir)
|
_output_dir = Path(args.output_dir)
|
||||||
_output_dir.mkdir(exist_ok=True, parents=True)
|
_output_dir.mkdir(exist_ok=True, parents=True)
|
||||||
_models = []
|
_short_name = create_short_name(args.custom_name) if args.custom_name else None
|
||||||
|
|
||||||
for _model_path in model_paths:
|
_driving_pkl = _find_driving_pkl(_output_dir)
|
||||||
_model_metadata = generate_metadata(Path(_model_path), _output_dir, create_short_name(args.custom_name))
|
if not _driving_pkl:
|
||||||
if _model_metadata:
|
print(f"No driving_tinygrad.pkl found in {_output_dir}", file=sys.stderr)
|
||||||
_models.append(_model_metadata)
|
sys.exit(1)
|
||||||
|
|
||||||
if _models:
|
if _short_name:
|
||||||
create_metadata_json(_models, _output_dir, args.custom_name, create_short_name(args.custom_name), args.is_20hz, args.upstream_branch)
|
new_pkl = _output_dir / f"driving_{_short_name.lower()}_tinygrad.pkl"
|
||||||
else:
|
if not new_pkl.exists():
|
||||||
print("No models processed.", file=sys.stderr)
|
_driving_pkl = _rename_pkl_with_chunks(_driving_pkl, new_pkl)
|
||||||
|
else:
|
||||||
|
_driving_pkl = new_pkl
|
||||||
|
|
||||||
|
_model_metadata = generate_chunked_model(_driving_pkl)
|
||||||
|
create_metadata_json([_model_metadata], _output_dir, args.custom_name, _short_name, args.is_20hz, args.upstream_branch)
|
||||||
|
|||||||
+4
-1
@@ -13,11 +13,12 @@ from openpilot.common.basedir import BASEDIR
|
|||||||
|
|
||||||
DIRS = ['cereal', 'openpilot']
|
DIRS = ['cereal', 'openpilot']
|
||||||
EXTS = ['.png', '.py', '.ttf', '.capnp', '.json', '.fnt', '.mo', '.po']
|
EXTS = ['.png', '.py', '.ttf', '.capnp', '.json', '.fnt', '.mo', '.po']
|
||||||
|
EXCLUDE = ['selfdrive/assets/training']
|
||||||
INTERPRETER = '/usr/bin/env python3'
|
INTERPRETER = '/usr/bin/env python3'
|
||||||
|
|
||||||
|
|
||||||
def copy(src, dest):
|
def copy(src, dest):
|
||||||
if any(src.endswith(ext) for ext in EXTS):
|
if any(src.endswith(ext) for ext in EXTS) and not any(exc in src for exc in EXCLUDE):
|
||||||
shutil.copy2(src, dest, follow_symlinks=True)
|
shutil.copy2(src, dest, follow_symlinks=True)
|
||||||
|
|
||||||
|
|
||||||
@@ -28,6 +29,8 @@ if __name__ == '__main__':
|
|||||||
parser.add_argument('module', help="the module to target, e.g. 'openpilot.system.ui.spinner'")
|
parser.add_argument('module', help="the module to target, e.g. 'openpilot.system.ui.spinner'")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
print('WARNING: copying all files! make sure to run scons and git tree is clean')
|
||||||
|
|
||||||
if not args.output:
|
if not args.output:
|
||||||
args.output = args.module
|
args.output = args.module
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,63 @@
|
|||||||
|
"""
|
||||||
|
wrapper that materializes symlinks in docs/ before build
|
||||||
|
|
||||||
|
we can delete this once zensical supports symlinks:
|
||||||
|
https://github.com/zensical/backlog/issues/55
|
||||||
|
"""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import signal
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
REPO_ROOT = Path(__file__).resolve().parent.parent
|
||||||
|
DOCS_DIR = REPO_ROOT / "docs"
|
||||||
|
SITE_DIR = REPO_ROOT / "docs_site"
|
||||||
|
sys.path.insert(0, str(REPO_ROOT))
|
||||||
|
# Local docs build helpers live under docs/ so they stay near the content
|
||||||
|
# source. The wrapper prunes them from docs_site/ after build.
|
||||||
|
sys.path.insert(0, str(DOCS_DIR))
|
||||||
|
|
||||||
|
|
||||||
|
def _materialize(docs: Path) -> dict[Path, str]:
|
||||||
|
originals: dict[Path, str] = {}
|
||||||
|
for link in docs.rglob("*"):
|
||||||
|
if not link.is_symlink():
|
||||||
|
continue
|
||||||
|
target = link.resolve()
|
||||||
|
if not target.is_file():
|
||||||
|
continue
|
||||||
|
originals[link] = os.readlink(link)
|
||||||
|
link.unlink()
|
||||||
|
shutil.copy2(target, link)
|
||||||
|
return originals
|
||||||
|
|
||||||
|
|
||||||
|
def _restore(originals: dict[Path, str]) -> None:
|
||||||
|
for link, target in originals.items():
|
||||||
|
link.unlink(missing_ok=True)
|
||||||
|
os.symlink(target, link)
|
||||||
|
|
||||||
|
|
||||||
|
def _raise_interrupt(*_):
|
||||||
|
raise KeyboardInterrupt
|
||||||
|
|
||||||
|
|
||||||
|
def _prune_site_output() -> None:
|
||||||
|
shutil.rmtree(SITE_DIR / "ext", ignore_errors=True)
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
signal.signal(signal.SIGTERM, _raise_interrupt)
|
||||||
|
originals = _materialize(DOCS_DIR)
|
||||||
|
try:
|
||||||
|
from zensical.main import cli
|
||||||
|
cli(standalone_mode=False)
|
||||||
|
if len(sys.argv) > 1 and sys.argv[1] == "build":
|
||||||
|
_prune_site_output()
|
||||||
|
finally:
|
||||||
|
_restore(originals)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
FAIL=0
|
|
||||||
|
|
||||||
if grep -n '#include "third_party/raylib/include/raylib\.h"' $@ | grep -v '^system/ui/raylib/raylib\.h'; then
|
|
||||||
echo -e "Bad raylib include found! Use '#include \"system/ui/raylib/raylib.h\"' instead\n"
|
|
||||||
FAIL=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
exit $FAIL
|
|
||||||
@@ -14,7 +14,7 @@ cd $ROOT
|
|||||||
FAILED=0
|
FAILED=0
|
||||||
|
|
||||||
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md"
|
IGNORED_FILES="uv\.lock|docs\/CARS.md|LICENSE\.md"
|
||||||
IGNORED_DIRS="^third_party.*|^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*"
|
IGNORED_DIRS="^msgq.*|^msgq_repo.*|^opendbc.*|^opendbc_repo.*|^cereal.*|^panda.*|^rednose.*|^rednose_repo.*|^tinygrad.*|^tinygrad_repo.*|^teleoprtc.*|^teleoprtc_repo.*|^third_party.*"
|
||||||
|
|
||||||
function run() {
|
function run() {
|
||||||
shopt -s extglob
|
shopt -s extglob
|
||||||
|
|||||||
+7
-6
@@ -33,11 +33,12 @@ if __name__ == "__main__":
|
|||||||
print("|-| ----- | --------- |")
|
print("|-| ----- | --------- |")
|
||||||
|
|
||||||
for f in glob.glob(BASEDIR + MODEL_PATH + "/*.onnx"):
|
for f in glob.glob(BASEDIR + MODEL_PATH + "/*.onnx"):
|
||||||
# TODO: add checkpoint to DM
|
|
||||||
if "dmonitoring" in f:
|
|
||||||
continue
|
|
||||||
|
|
||||||
fn = os.path.basename(f)
|
fn = os.path.basename(f)
|
||||||
master = get_checkpoint(MASTER_PATH + MODEL_PATH + fn)
|
master_path = MASTER_PATH + MODEL_PATH + fn
|
||||||
|
if os.path.exists(master_path):
|
||||||
|
master = get_checkpoint(master_path)
|
||||||
|
master_col = f"[{master}](https://reporter.comma.life/experiment/{master})"
|
||||||
|
else:
|
||||||
|
master_col = "N/A (new model)"
|
||||||
pr = get_checkpoint(BASEDIR + MODEL_PATH + fn)
|
pr = get_checkpoint(BASEDIR + MODEL_PATH + fn)
|
||||||
print("|", fn, "|", f"[{master}](https://reporter.comma.life/experiment/{master})", "|", f"[{pr}](https://reporter.comma.life/experiment/{pr})", "|")
|
print("|", fn, "|", master_col, "|", f"[{pr}](https://reporter.comma.life/experiment/{pr})", "|")
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
SConscript(['pandad/SConscript'])
|
|
||||||
SConscript(['controls/lib/lateral_mpc_lib/SConscript'])
|
|
||||||
SConscript(['controls/lib/longitudinal_mpc_lib/SConscript'])
|
|
||||||
SConscript(['locationd/SConscript'])
|
|
||||||
SConscript(['modeld/SConscript'])
|
|
||||||
SConscript(['ui/SConscript'])
|
|
||||||
@@ -1,4 +1,2 @@
|
|||||||
*.cc
|
|
||||||
fonts/*.fnt
|
fonts/*.fnt
|
||||||
fonts/*.png
|
fonts/*.png
|
||||||
translations_assets.qrc
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
<!DOCTYPE RCC><RCC version="1.0">
|
<!DOCTYPE RCC><RCC version="1.0">
|
||||||
<qresource>
|
<qresource>
|
||||||
<file alias="bootstrap-icons.svg">../../third_party/bootstrap/bootstrap-icons.svg</file>
|
<file alias="bootstrap-icons.svg">@BOOTSTRAP_ICONS_SVG@</file>
|
||||||
<file>images/button_continue_triangle.svg</file>
|
<file>images/button_continue_triangle.svg</file>
|
||||||
<file>icons/circled_check.svg</file>
|
<file>icons/circled_check.svg</file>
|
||||||
<file>icons/circled_slash.svg</file>
|
<file>icons/circled_slash.svg</file>
|
||||||
|
|||||||
@@ -37,10 +37,10 @@ def _char_sets():
|
|||||||
return tuple(sorted(ord(c) for c in base)), tuple(sorted(ord(c) for c in unifont))
|
return tuple(sorted(ord(c) for c in base)), tuple(sorted(ord(c) for c in unifont))
|
||||||
|
|
||||||
|
|
||||||
def _glyph_metrics(glyphs, rects, codepoints):
|
def _glyph_metrics(glyphs, rects, glyph_count: int):
|
||||||
entries = []
|
entries = []
|
||||||
min_offset_y, max_extent = None, 0
|
min_offset_y, max_extent = None, 0
|
||||||
for idx, codepoint in enumerate(codepoints):
|
for idx in range(glyph_count):
|
||||||
glyph = glyphs[idx]
|
glyph = glyphs[idx]
|
||||||
rect = rects[idx]
|
rect = rects[idx]
|
||||||
width = int(round(rect.width))
|
width = int(round(rect.width))
|
||||||
@@ -49,7 +49,7 @@ def _glyph_metrics(glyphs, rects, codepoints):
|
|||||||
min_offset_y = offset_y if min_offset_y is None else min(min_offset_y, offset_y)
|
min_offset_y = offset_y if min_offset_y is None else min(min_offset_y, offset_y)
|
||||||
max_extent = max(max_extent, offset_y + height)
|
max_extent = max(max_extent, offset_y + height)
|
||||||
entries.append({
|
entries.append({
|
||||||
"id": codepoint,
|
"id": glyph.value,
|
||||||
"x": int(round(rect.x)),
|
"x": int(round(rect.x)),
|
||||||
"y": int(round(rect.y)),
|
"y": int(round(rect.y)),
|
||||||
"width": width,
|
"width": width,
|
||||||
@@ -97,19 +97,23 @@ def _process_font(font_path: Path, codepoints: tuple[int, ...]):
|
|||||||
file_buf = rl.ffi.new("unsigned char[]", data)
|
file_buf = rl.ffi.new("unsigned char[]", data)
|
||||||
cp_buffer = rl.ffi.new("int[]", codepoints)
|
cp_buffer = rl.ffi.new("int[]", codepoints)
|
||||||
cp_ptr = rl.ffi.cast("int *", cp_buffer)
|
cp_ptr = rl.ffi.cast("int *", cp_buffer)
|
||||||
glyphs = rl.load_font_data(rl.ffi.cast("unsigned char *", file_buf), len(data), font_size, cp_ptr, len(codepoints), rl.FontType.FONT_DEFAULT)
|
glyph_count = rl.ffi.new("int *", len(codepoints))
|
||||||
|
glyphs = rl.load_font_data(
|
||||||
|
rl.ffi.cast("unsigned char *", file_buf), len(data), font_size, cp_ptr, len(codepoints),
|
||||||
|
rl.FontType.FONT_DEFAULT, glyph_count
|
||||||
|
)
|
||||||
if glyphs == rl.ffi.NULL:
|
if glyphs == rl.ffi.NULL:
|
||||||
raise RuntimeError("raylib failed to load font data")
|
raise RuntimeError("raylib failed to load font data")
|
||||||
|
|
||||||
rects_ptr = rl.ffi.new("Rectangle **")
|
rects_ptr = rl.ffi.new("Rectangle **")
|
||||||
image = rl.gen_image_font_atlas(glyphs, rects_ptr, len(codepoints), font_size, GLYPH_PADDING, 0)
|
image = rl.gen_image_font_atlas(glyphs, rects_ptr, glyph_count[0], font_size, GLYPH_PADDING, 0)
|
||||||
if image.width == 0 or image.height == 0:
|
if image.width == 0 or image.height == 0:
|
||||||
raise RuntimeError("raylib returned an empty atlas")
|
raise RuntimeError("raylib returned an empty atlas")
|
||||||
|
|
||||||
rects = rects_ptr[0]
|
rects = rects_ptr[0]
|
||||||
atlas_name = f"{font_path.stem}.png"
|
atlas_name = f"{font_path.stem}.png"
|
||||||
atlas_path = FONT_DIR / atlas_name
|
atlas_path = FONT_DIR / atlas_name
|
||||||
entries, line_height, base = _glyph_metrics(glyphs, rects, codepoints)
|
entries, line_height, base = _glyph_metrics(glyphs, rects, glyph_count[0])
|
||||||
|
|
||||||
if not rl.export_image(image, atlas_path.as_posix()):
|
if not rl.export_image(image, atlas_path.as_posix()):
|
||||||
raise RuntimeError("Failed to export atlas image")
|
raise RuntimeError("Failed to export atlas image")
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4ce1d357acadd798939b398cce1761ceb05564b44f2a5bc6865c7842e60e79f2
|
||||||
|
size 1474
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:b3fe73cd1a24c05346a9b4a02e4f900a314c83a422beb38b0f88f91389582cd4
|
||||||
|
size 3960
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:6b45f88128430fb50ef51c8e08b8e2a1c8fbe0b5c3a08de9f5d9d59bc1edc82e
|
||||||
|
size 4545
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:ec3dcf64cbc34251d8423cb8b3b31d743e93d14002dec43c389a857cb7e8eb17
|
||||||
|
size 10875
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:7409c53d7c72681c24982fd83b56ce70f80797c9c0f936d9296a5c18557ac472
|
||||||
|
size 7279
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:f3f57346a1cf9a66f9fd746f87bcebb23b7a403e9d6e4fd7701b126abcdd47ea
|
|
||||||
size 18476
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
|
||||||
oid sha256:b5aee9f6cec03f1967014cd2ea2a23982b262e7d86dadca602ecfa8875b38101
|
|
||||||
size 5875
|
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:26b3660dbd1e60b0ba98914afa7cb3a67151bb6990d218f55c901f243e38ff3e
|
oid sha256:5f5d4b7bd406114945e53f4d56089102ee83ba7d0a4590a371f7acab90c7ad53
|
||||||
size 3631
|
size 1862
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user