mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-23 07:52:06 +08:00
Compare commits
1048 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 82540646d7 | |||
| 457b6634fd | |||
| d92d2cb683 | |||
| 4f13a0f775 | |||
| 0ba5cbea91 | |||
| 8184cd8a6a | |||
| 4d2ad45be6 | |||
| f43479aac5 | |||
| 04eac60983 | |||
| a45b050b9f | |||
| ceed203de7 | |||
| a49c68806a | |||
| 8bc6becce1 | |||
| 5151bb8bf2 | |||
| f19ff793f5 | |||
| 4378c4b8bb | |||
| 61fffb9578 | |||
| a46af06baa | |||
| b6bfa13b70 | |||
| 6f89473f33 | |||
| be700bc825 | |||
| 38697ac628 | |||
| fa56d539a7 | |||
| 5c10e7f6cf | |||
| a29fdbd024 | |||
| f0d8ebd851 | |||
| 3a001dd71c | |||
| c8effae4eb | |||
| 9d0ab68f3b | |||
| eeddfc058a | |||
| 0d9b4cdaed | |||
| 1398bdb10e | |||
| b89c717643 | |||
| 85301e3a67 | |||
| b0b6bf8702 | |||
| 85b05998ed | |||
| e899f46727 | |||
| 3aaf249236 | |||
| b73be441b3 | |||
| e449ffcc36 | |||
| bca727a3cb | |||
| e1e41be1a9 | |||
| ad7f3d2b24 | |||
| 4ef0d3ee99 | |||
| 67cbeebc7b | |||
| 16abf93be8 | |||
| d3cc32ddca | |||
| 689f884810 | |||
| f653c1c0c5 | |||
| b8a845fe93 | |||
| f3d8b24bf4 | |||
| 880ed98ffc | |||
| a6d2297545 | |||
| f1025f6ee9 | |||
| 08e85808c5 | |||
| cb03d08397 | |||
| d0c6f845da | |||
| 81be78cd4d | |||
| b778da1d7c | |||
| 90cbb09482 | |||
| a1795f80dd | |||
| 9c19ec8409 | |||
| fc253fe1ee | |||
| d72a01d739 | |||
| f93b3f51c9 | |||
| 3d08a5048b | |||
| 9ee66008db | |||
| 6a257fe2de | |||
| dad7bb53a2 | |||
| 47ba86af33 | |||
| 9689de426b | |||
| 124eb42758 | |||
| 85404c184b | |||
| ed42cfe699 | |||
| 3099f4f12d | |||
| 8fceb9d957 | |||
| dcaf84d04c | |||
| 3a82a0797a | |||
| dd074cb6ef | |||
| 2d1f3833e4 | |||
| d4185a5d57 | |||
| 1262fca36b | |||
| e28dd1e1aa | |||
| 890b1cf512 | |||
| 1633641055 | |||
| 2dcb67091f | |||
| fb34601d5a | |||
| c1d3ae427b | |||
| 2ab45b552d | |||
| 8c1d59fecd | |||
| b6bcc8cca3 | |||
| cde88fd8ed | |||
| e5a7deb6ad | |||
| 10100e34e1 | |||
| 2d31b422c8 | |||
| 89919c8832 | |||
| 1a62ae821e | |||
| dc5f5eaf65 | |||
| ee8970dc42 | |||
| 0a44b48e21 | |||
| 36e53c7394 | |||
| 38eb400e41 | |||
| 4b5de0eddb | |||
| 5198b1b079 | |||
| e8a11591a8 | |||
| cbc8f98682 | |||
| ecdcb5d0c6 | |||
| c7494aed0f | |||
| 215ef16803 | |||
| 350b846d3a | |||
| 9ce9920ff7 | |||
| 1c0b087105 | |||
| 137d4b89b4 | |||
| 2cc4885a2e | |||
| 736e1fa7b7 | |||
| 177c7f1cf3 | |||
| 9bf904e8a6 | |||
| 071147baaf | |||
| 5ea5f6f267 | |||
| 18af4d6ad6 | |||
| 525b6e48e9 | |||
| c7b115b68e | |||
| b81d5bca3c | |||
| 682d738ffa | |||
| 1063114408 | |||
| f60c2b6a83 | |||
| f833819143 | |||
| 62aef9cd34 | |||
| f57617c944 | |||
| c4a0e57046 | |||
| 76c5cb6d87 | |||
| fc4e5007fd | |||
| af24fd6842 | |||
| cefb344183 | |||
| 81b37712f1 | |||
| 1a4c48249b | |||
| 002a22a097 | |||
| 9f20eb8ce6 | |||
| 707e2aedae | |||
| 2e636458a6 | |||
| 47d0a95fd6 | |||
| 5d142326f5 | |||
| ef9683ee79 | |||
| 55147d8a55 | |||
| de7acc5466 | |||
| 8a77534d02 | |||
| 73ed45f9d7 | |||
| 2d6df2e125 | |||
| e754b738ad | |||
| 1dadb3fcc9 | |||
| 4e88245745 | |||
| debc9bf7cf | |||
| e03673485b | |||
| 6efe4e1998 | |||
| ff6ed7055d | |||
| e4aada10a4 | |||
| 6c85e2c697 | |||
| 2d0340cefd | |||
| a974deeb59 | |||
| cf5bb4e16e | |||
| 0d4b0ee116 | |||
| 03cb3e9dc0 | |||
| f0dd0b5c8c | |||
| 3d8763b3ce | |||
| b460d5804c | |||
| eecb8e5c19 | |||
| 1a4ea66987 | |||
| b2427a5f20 | |||
| 94ca077e69 | |||
| e92e59ca78 | |||
| e0cabc1174 | |||
| 5e2f142704 | |||
| c1e15e5544 | |||
| 2beb0ffad1 | |||
| fa373af9b5 | |||
| 7909716c1f | |||
| c1cb971bca | |||
| 538ec25ad9 | |||
| 17152484c2 | |||
| 954b567b9b | |||
| 6061476d8e | |||
| ad903aeaa1 | |||
| c8c1b0f781 | |||
| 534f096bb8 | |||
| 7da36b2470 | |||
| f2db7f7665 | |||
| 40a1af97b9 | |||
| 3a45fff1b9 | |||
| ae9bd39883 | |||
| 43e7d87176 | |||
| 432c6050ed | |||
| 4e3b1f1f6b | |||
| 53ff5413cd | |||
| dc889587ce | |||
| cf2b033c79 | |||
| 589e33f665 | |||
| 6486ab6cab | |||
| ab234c72a3 | |||
| 485c7b2725 | |||
| 5d47ffdb8a | |||
| 4861d15056 | |||
| 1c89e2b885 | |||
| 1e73025f86 | |||
| c552567ada | |||
| 378212e5ab | |||
| 4f52f3f3c5 | |||
| a0d48b6c63 | |||
| b14270bd71 | |||
| 8f720a54f6 | |||
| 2c41dbc472 | |||
| a8660b5b4f | |||
| 4ccafff123 | |||
| 856f8d3d47 | |||
| 00e20f1524 | |||
| 215acefbb4 | |||
| c33c9ff22a | |||
| 99fdd59042 | |||
| 5af1099fbf | |||
| f983df0c70 | |||
| 936740201c | |||
| 4489517eeb | |||
| b1b7c505a1 | |||
| a2e7f3788f | |||
| d2bb8fe537 | |||
| 7097e69aa3 | |||
| 5289b08bcf | |||
| 657ff0f8ec | |||
| 399ed08926 | |||
| 641af6d7e7 | |||
| f57de1c5b2 | |||
| cc8f6eadfe | |||
| 6aac50ab56 | |||
| cb5d120136 | |||
| 211c8adcce | |||
| c85b6a0d1c | |||
| 9b2f7341d8 | |||
| 650946cd2a | |||
| 9801e486d9 | |||
| 3381192297 | |||
| b2e3dd17ea | |||
| 01715f6f9a | |||
| 8720e5d712 | |||
| 8752093801 | |||
| 3c957c6e9d | |||
| 3ef5037c16 | |||
| 07b8e7783d | |||
| 53bf5b0d41 | |||
| 8c33592628 | |||
| 3bbb33f6bd | |||
| 7534b2a160 | |||
| 025a930ce8 | |||
| 523c92c6fe | |||
| 72282f2d2e | |||
| 2825c00fcc | |||
| b28425b8c3 | |||
| 1f5e0b6f68 | |||
| 646f6a1006 | |||
| cc683f2040 | |||
| 18e8f648c2 | |||
| 821e4da2c7 | |||
| 13d98fd2d5 | |||
| 92cd656c68 | |||
| 727a750b34 | |||
| 5dabb678ce | |||
| ef988aca28 | |||
| 5bd9549bd1 | |||
| 64f3759fd0 | |||
| 3481702715 | |||
| c9781ee31d | |||
| d71d2bd2d0 | |||
| 702bebf176 | |||
| 25da8e9d44 | |||
| 845f6ec8cf | |||
| e1ad4daf8d | |||
| 783b717af8 | |||
| 65e1fd299e | |||
| b29b1964ba | |||
| 063aa994d2 | |||
| 50462a1d01 | |||
| 80a8df0643 | |||
| d9fc6c0086 | |||
| cb612a4b90 | |||
| 36d77debd0 | |||
| 530ad2925d | |||
| 437726b348 | |||
| 9e6af5ba74 | |||
| 99bd9075d5 | |||
| c438aeb5a5 | |||
| f1ca81debf | |||
| d7e1c42c2b | |||
| 6d51d64285 | |||
| ec33519dc7 | |||
| 2fd4b53aaf | |||
| a2c4fe1c90 | |||
| 3e56612990 | |||
| 75858673c4 | |||
| 57223958b5 | |||
| 3553a754a4 | |||
| f290fb1e05 | |||
| e0ccc175e4 | |||
| 0c64818f52 | |||
| c44548ba0f | |||
| 59bddfba8d | |||
| 8a1fcd8991 | |||
| 734151f59b | |||
| 9a14baac4d | |||
| 3546b625e7 | |||
| d3e3628a95 | |||
| fec6382b96 | |||
| 4bd020e92b | |||
| 87443cd34d | |||
| 5f0e9fce61 | |||
| a2cce7f897 | |||
| f4041dc1f0 | |||
| 7f5342f378 | |||
| 339bc0b8b3 | |||
| 59c64acc29 | |||
| 7229c7541e | |||
| 39e73cc46e | |||
| 285fd97606 | |||
| 8e3757ac87 | |||
| e5f1f86ac2 | |||
| 41fa0cdf82 | |||
| 692f5fdd72 | |||
| de0a1e66d8 | |||
| 7e03277962 | |||
| bd9bb74d03 | |||
| 7d54b58b8d | |||
| 68d059fd5d | |||
| 728108f97f | |||
| cb6fa622ee | |||
| 5b29fd0f2c | |||
| 129445cd1d | |||
| 13d0aefd7c | |||
| 5f7b05e808 | |||
| 32f65bae55 | |||
| 49d9b8bb00 | |||
| 6f42bbab18 | |||
| b89393a5a2 | |||
| 1e5758e712 | |||
| b3eba70b7a | |||
| cec7a5dc98 | |||
| 14993f58e3 | |||
| e8a17b4963 | |||
| fb77212221 | |||
| aa7f6973c0 | |||
| c2af5a82ff | |||
| 348114e5bd | |||
| a6e28ac2ee | |||
| 0e6f78a656 | |||
| 2305fb59a2 | |||
| cc816043c1 | |||
| b6dbb0fd8d | |||
| 974a7a3f7d | |||
| fe6edda23a | |||
| fdcf8b592e | |||
| 17e25f78b4 | |||
| 4ff77a4752 | |||
| f04ee80452 | |||
| ddbbcc6f5d | |||
| 0f40afa357 | |||
| cac8d3f405 | |||
| b521a913ab | |||
| d6651ccd82 | |||
| 9b92cdd2cc | |||
| 2976798852 | |||
| 1b90b42647 | |||
| d6317ffd20 | |||
| de805e4af7 | |||
| 3ba52bc6fe | |||
| d7fd78050b | |||
| 8864b79a6e | |||
| 4d085424f8 | |||
| e9f054b7ee | |||
| f429f3191f | |||
| d07981ea3c | |||
| 3df1b53fab | |||
| 6bb87174b9 | |||
| 22d5cbd0fa | |||
| 4c9ca91b98 | |||
| 0736f325fc | |||
| 6d356d520e | |||
| 73123aa400 | |||
| 7dfe03b7a3 | |||
| dcc5afa8fa | |||
| 12a4b1b561 | |||
| 7aac14e6fc | |||
| 226465e882 | |||
| ae21d40a19 | |||
| 0b62dbe16b | |||
| 41abede7f6 | |||
| f653566803 | |||
| 2deb4e6f65 | |||
| 9f32f217e6 | |||
| e8a39c4a74 | |||
| 517020ffb6 | |||
| a85f3ce11c | |||
| 014baf8e90 | |||
| e62781cccb | |||
| e1912fa5be | |||
| 8050c56a43 | |||
| 0b826002e9 | |||
| 408d52d72a | |||
| aeaac22274 | |||
| a7fe9db773 | |||
| 35296a8692 | |||
| f28cea759d | |||
| de64b99740 | |||
| 0e1de37281 | |||
| 5a309daee6 | |||
| 520649b893 | |||
| 18abe218d9 | |||
| 31801a7312 | |||
| cc7ecd53c7 | |||
| cca3be3a96 | |||
| 586e49cab3 | |||
| ebe47a580c | |||
| 7933c10c97 | |||
| 2bc97ee23f | |||
| c88ab5cd12 | |||
| 943aaef76a | |||
| 3fd9e94a34 | |||
| e423f8f605 | |||
| 0eb90ecb3e | |||
| 282a8b093d | |||
| 703f3d0573 | |||
| 2337704602 | |||
| bd9888a439 | |||
| 12b3d0e08d | |||
| 89d350a791 | |||
| 99a83e5522 | |||
| 4d53a26a06 | |||
| a8328cb5ff | |||
| 844c328625 | |||
| 39b97d4e18 | |||
| 45f497e8f6 | |||
| edc5a0412c | |||
| 9670e3a5eb | |||
| 7b2b10bc9e | |||
| bd357adb8b | |||
| 670b6011da | |||
| 1e7fc15a04 | |||
| e999839a57 | |||
| 150ff72646 | |||
| 1bfecbc9c2 | |||
| dcd382ffb8 | |||
| d567442136 | |||
| 540fff5226 | |||
| 21273c921e | |||
| 75e52427d1 | |||
| 21fd3d0320 | |||
| 1ee798439a | |||
| cc52f980b3 | |||
| 09d165a85b | |||
| 4c4964a740 | |||
| 225ce45d31 | |||
| ec7e3192bb | |||
| 3fd352a7ef | |||
| 49570c11c6 | |||
| 92214b69d8 | |||
| b8ae62a0b1 | |||
| 29a6f0504a | |||
| eadab06f59 | |||
| 9493f2a0eb | |||
| b593b7cc43 | |||
| 5c0c2a17b0 | |||
| 5f33b2fb2d | |||
| 63e0e038fa | |||
| d24a14cb39 | |||
| 3efa52f53b | |||
| f3ed577870 | |||
| 49e58a2532 | |||
| ae901d1562 | |||
| 16a4206720 | |||
| 85d2653fda | |||
| e4784d44f6 | |||
| 0f4828df82 | |||
| dc0fd4ca96 | |||
| aaf2aac050 | |||
| b5ec0e9744 | |||
| 90adc18032 | |||
| 070a13096b | |||
| 7ccab2bdb9 | |||
| e9434befaa | |||
| 56c77fd5fa | |||
| e6bd88371e | |||
| bc30b01eb7 | |||
| ef93981bfa | |||
| 35e2fc7dd9 | |||
| 2feddf32b2 | |||
| ed185e90f6 | |||
| 19fc66f88a | |||
| 5cbfc7705b | |||
| 8de8c3eb00 | |||
| 04365f12ff | |||
| 9297cd2f3e | |||
| 0711160b1c | |||
| 33f01084d1 | |||
| 1fbec6f601 | |||
| cf5b743de6 | |||
| 2c377e534f | |||
| 1ca9fe35c2 | |||
| 56c49b3b42 | |||
| 5429748767 | |||
| 6aecf59536 | |||
| db65937fc7 | |||
| 8ebe9b69af | |||
| 4c40be8b1f | |||
| 082ea8119b | |||
| afc7ff1b7a | |||
| 222e880561 | |||
| 1465e38c7b | |||
| ecee67dd64 | |||
| ea6178e53e | |||
| 01a0ad496d | |||
| 6901e3417b | |||
| cd33562379 | |||
| b64d5a0fa4 | |||
| 005c6aed95 | |||
| 073503a6f2 | |||
| 61d5a50534 | |||
| 2fa66d6f4d | |||
| d5a873ed86 | |||
| 563ae65443 | |||
| b6e0d4807a | |||
| 2efe78a4ef | |||
| 569a9216db | |||
| 629cfd845f | |||
| 2892dc05c8 | |||
| 632b416f2a | |||
| 5f3821c1f9 | |||
| 55b7529ca4 | |||
| c248f307f8 | |||
| bdb83b6be1 | |||
| c55f40e77d | |||
| c7a37c06d8 | |||
| efbd0b9ea0 | |||
| 6ed8f07cb6 | |||
| 5164555c4f | |||
| c5999702ae | |||
| ddf63701e8 | |||
| 28098bb7c4 | |||
| 60e056cc0a | |||
| 2a5de8e0f8 | |||
| d05cb31e2e | |||
| fb743d313e | |||
| 4441671227 | |||
| c7a9ea2bf4 | |||
| b637ad49d9 | |||
| c6a2c99123 | |||
| 852598fa0a | |||
| 3751d9cf51 | |||
| 30c388aea8 | |||
| 1f8941367d | |||
| 784e1d6658 | |||
| b622e3e0a7 | |||
| cb94d3b055 | |||
| 086e33dd6e | |||
| 94f93a9f26 | |||
| 889ce4c4fb | |||
| 96c00271e3 | |||
| 747460363f | |||
| b32c6dafee | |||
| bffb2fb6fa | |||
| 688b694266 | |||
| ec8f036850 | |||
| a6adedf6e0 | |||
| eb821ceb5c | |||
| 98d61982f9 | |||
| 04a26ada69 | |||
| 3e0dd06374 | |||
| f18828228a | |||
| c812c3192d | |||
| 8d3b919ef6 | |||
| 63df46bf22 | |||
| 826c5e96a1 | |||
| 1870d4905b | |||
| 347b23055d | |||
| cbea5f198f | |||
| be379e188b | |||
| 42d9bd0516 | |||
| 3ca9f351a0 | |||
| a1d6a062a9 | |||
| 4f44d6e643 | |||
| 1be13fdc55 | |||
| 810a2d9448 | |||
| c9dbf97649 | |||
| 1bb4ca2547 | |||
| 2c04a27a2a | |||
| b7f8dd11a5 | |||
| 70c0592e84 | |||
| 572c03dbac | |||
| fa498221da | |||
| 67238d5045 | |||
| 994170ddb5 | |||
| 3c28188d7a | |||
| 4ccd17903b | |||
| 0e1b573f89 | |||
| 10580aca92 | |||
| 6b13175338 | |||
| d0171084b5 | |||
| 2bfdd0d61d | |||
| ea53111afc | |||
| 0739d4ac2d | |||
| 698e0ca00f | |||
| 8dca43881a | |||
| a885111c0c | |||
| bd73664f4c | |||
| 608c16007e | |||
| 275abc1eb5 | |||
| ff34b8af76 | |||
| ff4d1923f0 | |||
| 3a91ae08a9 | |||
| b161764b1e | |||
| 03e9777c3f | |||
| 1033d3d80e | |||
| 7057c57419 | |||
| 1f1efec4c9 | |||
| 7d4df73ea5 | |||
| 29fe152bd3 | |||
| 31918c067a | |||
| daf5ea2783 | |||
| f0f04d4b5b | |||
| 2b7707ecf6 | |||
| ef870d5533 | |||
| fd7295c980 | |||
| 220cfff04d | |||
| ee0fb6bf8e | |||
| 0cd2bbf6c0 | |||
| 0871abcf55 | |||
| 8ccb777192 | |||
| 0593667601 | |||
| a5044302a2 | |||
| 6a4f685d04 | |||
| 355499a8de | |||
| 288a5e14da | |||
| 9447aa0e3d | |||
| 67fd6c80dd | |||
| 43c12ae7b3 | |||
| 1894a312d3 | |||
| 3e9545670b | |||
| 45ee58b1f6 | |||
| 3f3c293559 | |||
| 5d110bcee5 | |||
| 62bf9fcc27 | |||
| 205863b71f | |||
| c990515eaf | |||
| ba1da60c25 | |||
| 54174d1ef0 | |||
| 76e91da3ad | |||
| 9fcac06297 | |||
| 3e2549f2b8 | |||
| 63961dec45 | |||
| 7a19a11001 | |||
| 93f7925c4d | |||
| a2c5fca787 | |||
| bb06468ead | |||
| 1d8dc8a69a | |||
| a254a05df0 | |||
| 2aa7648bb8 | |||
| b309bf4173 | |||
| a3fcde2ae8 | |||
| f8ff156869 | |||
| 375dfe16a8 | |||
| b976135d2f | |||
| f40f7f9ece | |||
| ea6677c464 | |||
| 8258257658 | |||
| f5d67b5eee | |||
| 8ee3c7b485 | |||
| 8450f9f333 | |||
| 342ff24510 | |||
| 4cd76f4966 | |||
| ec254074d1 | |||
| 8059106cae | |||
| 23b4aaf2a5 | |||
| 5359f6d354 | |||
| a70e4c3074 | |||
| 7a2f2ddf32 | |||
| 2dc0f97c93 | |||
| 6bbf42c16a | |||
| 73e66c4a0b | |||
| 15fcbf24f1 | |||
| e89c6b3b88 | |||
| c4a7f25b62 | |||
| 1d74a97ba6 | |||
| aea467ff02 | |||
| 9579d331fc | |||
| 7c6d887187 | |||
| f89796033c | |||
| c8249f3657 | |||
| 798e9071d8 | |||
| b501ad4d51 | |||
| d6af554db4 | |||
| 9e50a1b660 | |||
| 2b86cc1373 | |||
| dd7de180ea | |||
| 2b46e1450a | |||
| 7ed8abb66c | |||
| ef2bb7f2fc | |||
| de56b21103 | |||
| 5491a61384 | |||
| ae3b74245f | |||
| c0a74f7a20 | |||
| 7f035bae39 | |||
| cea3572b74 | |||
| cd9ec6b240 | |||
| b4cc4ea8e2 | |||
| 154f655335 | |||
| 638dfb68ba | |||
| 2ff707d82f | |||
| 8320934d91 | |||
| 63441c048c | |||
| d0069c136b | |||
| fa0017fafc | |||
| 870d19f33d | |||
| 60c34a0837 | |||
| 22e79479d2 | |||
| 3570022b9a | |||
| dd5f5fdb98 | |||
| 18b7ddef8f | |||
| 5ec9aee216 | |||
| 927548621b | |||
| 6005b12f94 | |||
| 09aa21390d | |||
| d097a0c201 | |||
| 560c503871 | |||
| 3d24225cc1 | |||
| 51314fa9fe | |||
| 803b54ebdb | |||
| c085b8af19 | |||
| 2cec2587be | |||
| 9e3a35035a | |||
| 2148e2dff2 | |||
| f55f3bb7cd | |||
| 4d55671b17 | |||
| dfc66d7807 | |||
| 31101ecaab | |||
| 80d702c866 | |||
| 3d879dd1ae | |||
| ef9e430992 | |||
| 63fa250f29 | |||
| ceb557058c | |||
| 6a67f9e56f | |||
| 372682d4a9 | |||
| 102ac66fab | |||
| ab44c9a4ff | |||
| 1805a47139 | |||
| 5417efaa1d | |||
| 4536719353 | |||
| 34f4aadca5 | |||
| b54d5997de | |||
| 385ad9e839 | |||
| 7c6bc70312 | |||
| 8ec61991ee | |||
| 1eef956cad | |||
| daef43f620 | |||
| aa91a02db8 | |||
| a6d0a88b1e | |||
| f2c806f8a0 | |||
| 349c0ec662 | |||
| 741ea44aba | |||
| 56a89eb4fb | |||
| 3f830827b2 | |||
| a2a385336e | |||
| be934b3881 | |||
| 3d6dfc864d | |||
| 3cf81c081c | |||
| 8910668e4e | |||
| bed8da06dc | |||
| c490b3ca12 | |||
| 6c4c0c00b4 | |||
| 68625222b6 | |||
| 8deb1bf285 | |||
| 28b17858be | |||
| 91aec49cee | |||
| cd087a561e | |||
| 10cc87b80b | |||
| 13d4c6a167 | |||
| 455a6a586a | |||
| c78b302b93 | |||
| a11a8591e4 | |||
| ec3f044c83 | |||
| 6eaae848c9 | |||
| fc9a79406f | |||
| 0bbceb8539 | |||
| e97ae07589 | |||
| f45ad6bab9 | |||
| b5cbb980fb | |||
| 876738e96a | |||
| 4116b412a3 | |||
| 75509aec16 | |||
| 97c2d7e655 | |||
| 1bc12f1e21 | |||
| 430079113c | |||
| b4f19d4860 | |||
| 1c46640ea6 | |||
| 2d8030de0b | |||
| 80a4ace1ab | |||
| b391708b3d | |||
| 6ef386da3d | |||
| 6ae668e987 | |||
| 72b71d57bc | |||
| 5339a89e81 | |||
| 2f60026c22 | |||
| e0f51bdbb6 | |||
| 63d8c6c7f7 | |||
| 83f6843a48 | |||
| 4bb5986c14 | |||
| e596704644 | |||
| bcc416c7eb | |||
| 38de06232e | |||
| 567c5459db | |||
| fd32fcd20d | |||
| a79a5e5a16 | |||
| 5117a8c3a6 | |||
| 1555c0b5fe | |||
| 0e9de8f1b1 | |||
| 7bfac9d050 | |||
| a800c129b0 | |||
| f13ec6cb27 | |||
| f04bb6b9fa | |||
| ed0346980c | |||
| 6cf710d4cb | |||
| 8b90c210f8 | |||
| 62bbf6db8d | |||
| a51477d40d | |||
| a84089c6e5 | |||
| bb8a2ff65b | |||
| 3a78eee2f9 | |||
| 52a4b52628 | |||
| 839a773345 | |||
| c236f472a9 | |||
| ac3d96d2fd | |||
| eca2f40341 | |||
| 5e6f942234 | |||
| 69ca699773 | |||
| d1e0a60408 | |||
| 999db5b426 | |||
| e8135c5431 | |||
| 978d1c38f1 | |||
| 8c7d53004f | |||
| 7413982f0d | |||
| c95cac3b06 | |||
| fbbb2ef5d0 | |||
| d15d3c73b8 | |||
| 96313fa4c0 | |||
| c35494c19f | |||
| c321fa72e2 | |||
| 2c654500d2 | |||
| bb4f9651ba | |||
| c23537b4d5 | |||
| 865e6fa9d8 | |||
| d7b0a5fa7e | |||
| 112d615ac9 | |||
| fb34e7ccd3 | |||
| f08d95b95a | |||
| 1c9bbb290a | |||
| 2c8415f81c | |||
| bae7a610fa | |||
| aecb6d13e7 | |||
| 1ca8a4ca75 | |||
| c316c400f8 | |||
| 408cef2d46 | |||
| be0626f7e3 | |||
| f06c98018f | |||
| 976dfa3982 | |||
| 623de0e22a | |||
| 86146981c4 | |||
| 56dcf71774 | |||
| a1f073921c | |||
| cccd60a28b | |||
| 181ea39a83 | |||
| a93f1caf1f | |||
| 8cce8cf3f3 | |||
| 0b855a93d7 | |||
| 8c78749846 | |||
| aa2a3b3c8f | |||
| ba2dced54c | |||
| 582671e006 | |||
| 2e15ac5f4f | |||
| c92add1280 | |||
| bab251b287 | |||
| 9dc98b36be | |||
| 313f36712c | |||
| 3ff874d6c2 | |||
| eb751a3804 | |||
| 5a8e3470ff | |||
| 07909906d4 | |||
| 7c87ada8d8 | |||
| 08216c1ea4 | |||
| baa9e91fd7 | |||
| f3c4501db1 | |||
| bdd6ff4f3e | |||
| 1f5096956b | |||
| f2e100b0e1 | |||
| d6474aa0a9 | |||
| 8b0bfd7910 | |||
| db55f1275d | |||
| 8f9ee43d34 | |||
| 37c4ee1532 | |||
| 0ebee55050 | |||
| cb5299be5a | |||
| 5c73681be8 | |||
| dd09c4f341 | |||
| 4d01b7bec8 | |||
| 42ebab1334 | |||
| 9117a414bb | |||
| 1966845fc9 | |||
| 889e386dbc | |||
| 4e97a29e83 | |||
| b695715753 | |||
| f5991caf6f | |||
| 40f298f033 | |||
| c5eb41fe37 | |||
| 2e4de9b7d8 | |||
| f2c17dd688 | |||
| c4298ce287 | |||
| 1de1640689 | |||
| fc58c866c6 | |||
| c4b63cd439 | |||
| e32a2ce164 | |||
| 6e76d0ca86 | |||
| 259e2fd5af | |||
| 713f8bfc21 | |||
| 6d41ce2032 | |||
| 3187631935 | |||
| c47aadee19 | |||
| 72a6c9fd65 | |||
| 825ee01f0b | |||
| 09eccd1aaf | |||
| 44da3da1c4 | |||
| 31c4bf8a4a | |||
| 24699f3e54 | |||
| 3e2325a632 | |||
| 04a20bd349 | |||
| a53746f8df | |||
| b0f32717b7 | |||
| 69f4b4a6b7 | |||
| fd8cebf2c3 | |||
| 5b137d666f | |||
| bbdbb55a2a | |||
| 5cb9f84c4c | |||
| 1cadcf6192 | |||
| 1003498761 | |||
| 64d8be9176 | |||
| 18970781ba | |||
| 66e6b95833 | |||
| 50371637dc | |||
| 5c252ded72 | |||
| 35ed6bc3a9 | |||
| 0c73798049 | |||
| 1123773fbd | |||
| e461d18d54 | |||
| e7b80b78cc | |||
| 26a9760afc | |||
| b4ae64358e | |||
| 5e07636d54 | |||
| b99c73e1fa | |||
| 47f23828d2 | |||
| 938981dce9 | |||
| e4ac9af404 | |||
| 0a2e8dd81b | |||
| 09d8327a14 | |||
| ff223260b2 | |||
| bddeca6998 | |||
| 267acfb73b | |||
| 347cee4b09 | |||
| abd657edfa | |||
| c382245a41 | |||
| b5d5894a2d | |||
| bc5336d805 | |||
| dc1219d13f | |||
| 58d3038241 | |||
| 4d39d50858 | |||
| 7e0d3c22f4 | |||
| a931ed5c15 | |||
| 6fee91ad64 | |||
| 358c0a8747 | |||
| bc7d6f2677 | |||
| 4b73f3b169 | |||
| d02f78a59c | |||
| e0656f9b44 | |||
| 87270952c4 | |||
| 8ca0b82181 | |||
| ad337f8830 | |||
| 103b4df18c | |||
| ffc8ea5a86 | |||
| e1fa04b678 | |||
| 1936c42ee7 | |||
| 48892e339d | |||
| 8ead5db670 | |||
| fbbad834f3 | |||
| 278781e5af | |||
| 43ad1754da | |||
| 4a5385a5b0 | |||
| dbe172f7fd | |||
| 22e54af238 | |||
| 618a25a612 | |||
| b50b351b15 | |||
| 862a816215 | |||
| cbba571845 | |||
| 239646b20b | |||
| 5339a13c34 | |||
| c553c1f872 | |||
| 54da96dbdf | |||
| 632f7594a4 | |||
| 7d400cb00c | |||
| e9d78958c1 | |||
| a8fd55740b | |||
| ddb0d7c1a5 | |||
| 39673deb77 | |||
| aac09d1d92 | |||
| 6c7abc42f6 | |||
| 006c06027b | |||
| 203b2e75d3 | |||
| 97f6dc6e8c | |||
| 3a2c4a855a | |||
| 052ada6a07 | |||
| b1972af6db | |||
| 0b65a04bc1 | |||
| 8142dba137 | |||
| 0aaefdee37 | |||
| d9b5f259ab | |||
| 12f766f8c3 | |||
| 631a067257 | |||
| 45ea4a1f75 | |||
| 55579c8c08 | |||
| db37f4187e | |||
| 41619a0174 | |||
| 6f1a1b3213 | |||
| 9deac8c800 | |||
| 5dc4254619 | |||
| 9d7b18c7e3 | |||
| ce92fd1a0f | |||
| f4b017a75b | |||
| d1922efa4c | |||
| 5751c61de0 | |||
| d913e4d349 | |||
| 67dc69d3db | |||
| be4e995d9b | |||
| bd5586da55 | |||
| 68bc36b1a5 | |||
| 989278dfe7 | |||
| eb41875675 | |||
| 9bd7e3e36d | |||
| fb4d9c542c | |||
| 3c43a000cd |
-19
@@ -1,19 +0,0 @@
|
|||||||
---
|
|
||||||
Checks: '
|
|
||||||
bugprone-*,
|
|
||||||
-bugprone-integer-division,
|
|
||||||
-bugprone-narrowing-conversions,
|
|
||||||
performance-*,
|
|
||||||
clang-analyzer-*,
|
|
||||||
misc-*,
|
|
||||||
-misc-unused-parameters,
|
|
||||||
modernize-*,
|
|
||||||
-modernize-avoid-c-arrays,
|
|
||||||
-modernize-deprecated-headers,
|
|
||||||
-modernize-use-auto,
|
|
||||||
-modernize-use-using,
|
|
||||||
-modernize-use-nullptr,
|
|
||||||
-modernize-use-trailing-return-type,
|
|
||||||
'
|
|
||||||
CheckOptions:
|
|
||||||
...
|
|
||||||
+1
-1
@@ -2,5 +2,5 @@ Wen
|
|||||||
REGIST
|
REGIST
|
||||||
PullRequest
|
PullRequest
|
||||||
cancelled
|
cancelled
|
||||||
indeces
|
|
||||||
FOF
|
FOF
|
||||||
|
NoO
|
||||||
|
|||||||
@@ -13,27 +13,6 @@
|
|||||||
*.o-*
|
*.o-*
|
||||||
*.os
|
*.os
|
||||||
*.os-*
|
*.os-*
|
||||||
*.so
|
|
||||||
*.a
|
|
||||||
|
|
||||||
venv/
|
venv/
|
||||||
.venv/
|
.venv/
|
||||||
|
|
||||||
notebooks
|
|
||||||
phone
|
|
||||||
massivemap
|
|
||||||
neos
|
|
||||||
installer
|
|
||||||
chffr/app2
|
|
||||||
chffr/backend/env
|
|
||||||
selfdrive/nav
|
|
||||||
selfdrive/baseui
|
|
||||||
selfdrive/test/simulator2
|
|
||||||
**/cache_data
|
|
||||||
xx/plus
|
|
||||||
xx/community
|
|
||||||
xx/projects
|
|
||||||
!xx/projects/eon_testing_master
|
|
||||||
!xx/projects/map3d
|
|
||||||
xx/ops
|
|
||||||
xx/junk
|
|
||||||
|
|||||||
+3
-1
@@ -7,10 +7,12 @@
|
|||||||
*.png filter=lfs diff=lfs merge=lfs -text
|
*.png filter=lfs diff=lfs merge=lfs -text
|
||||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||||
*.ttf filter=lfs diff=lfs merge=lfs -text
|
*.ttf filter=lfs diff=lfs merge=lfs -text
|
||||||
|
*.otf filter=lfs diff=lfs merge=lfs -text
|
||||||
*.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 filter=lfs diff=lfs merge=lfs -text
|
system/hardware/tici/updater_weston 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/**/*.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/**/*.so.* filter=lfs diff=lfs merge=lfs -text
|
third_party/**/*.so.* filter=lfs diff=lfs merge=lfs -text
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
ci:
|
ci:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-all-files: "{.github/**,**/test_*,Jenkinsfile}"
|
- any-glob-to-all-files: "{.github/**,**/test_*,**/test/**,Jenkinsfile}"
|
||||||
|
|
||||||
chore:
|
chore:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
@@ -16,7 +16,7 @@ simulation:
|
|||||||
|
|
||||||
ui:
|
ui:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
- any-glob-to-all-files: '{selfdrive/ui/**,system/ui/**}'
|
- any-glob-to-all-files: '{selfdrive/assets/**,selfdrive/ui/**,system/ui/**}'
|
||||||
|
|
||||||
tools:
|
tools:
|
||||||
- changed-files:
|
- changed-files:
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
name: "PR review"
|
name: "PR review"
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened, reopened, synchronize, edited]
|
types: [ opened, reopened, synchronize, edited ]
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
labeler:
|
labeler:
|
||||||
@@ -29,21 +29,21 @@ jobs:
|
|||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
with:
|
with:
|
||||||
target: /^(?!master-new$).*/
|
target: /^(?!master$).*/
|
||||||
exclude: /sunnypilot:.*/
|
exclude: /sunnypilot:.*/
|
||||||
change-to: ${{ github.base_ref }}
|
change-to: ${{ github.base_ref }}
|
||||||
already-exists-action: close_this
|
already-exists-action: close_this
|
||||||
already-exists-comment: "Your PR should be made against the `master-new` branch"
|
already-exists-comment: "Your PR should be made against the `master` branch"
|
||||||
|
|
||||||
update-pr-labels:
|
update-pr-labels:
|
||||||
name: Update fork's PR Labels
|
name: Update fork's PR Labels
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: (github.event.pull_request.head.repo.fork && (contains(github.event_name, 'pull_request') && github.event.action == 'synchronize'))
|
if: (github.event.pull_request.head.repo.fork && (contains(github.event_name, 'pull_request') && github.event.action == 'synchronize'))
|
||||||
env:
|
env:
|
||||||
PR_LABEL: 'dev-c3'
|
PR_LABEL: 'dev'
|
||||||
TRUST_FORK_PR_LABEL: 'trust-fork-pr'
|
TRUST_FORK_PR_LABEL: 'trust-fork-pr'
|
||||||
steps:
|
steps:
|
||||||
- name: Check if PR has dev-c3 label
|
- name: Check if PR has dev label
|
||||||
id: check-labels
|
id: check-labels
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
@@ -62,24 +62,24 @@ jobs:
|
|||||||
console.log(`PR #${prNumber} has ${process.env.PR_LABEL} label: ${hasDevC3Label}`);
|
console.log(`PR #${prNumber} has ${process.env.PR_LABEL} label: ${hasDevC3Label}`);
|
||||||
console.log(`PR #${prNumber} has ${process.env.TRUST_FORK_PR_LABEL} label: ${hasTrustLabel}`);
|
console.log(`PR #${prNumber} has ${process.env.TRUST_FORK_PR_LABEL} label: ${hasTrustLabel}`);
|
||||||
|
|
||||||
core.setOutput('has-dev-c3', hasDevC3Label ? 'true' : 'false');
|
core.setOutput('has-dev', hasDevC3Label ? 'true' : 'false');
|
||||||
core.setOutput('has-trust', hasTrustLabel ? 'true' : 'false');
|
core.setOutput('has-trust', hasTrustLabel ? 'true' : 'false');
|
||||||
|
|
||||||
- name: Remove trust-fork-pr label if present
|
- name: Remove trust-fork-pr label if present
|
||||||
if: steps.check-labels.outputs.has-dev-c3 == 'true' && steps.check-labels.outputs.has-trust == 'true'
|
if: steps.check-labels.outputs.has-dev == 'true' && steps.check-labels.outputs.has-trust == 'true'
|
||||||
uses: actions/github-script@v7
|
uses: actions/github-script@v7
|
||||||
with:
|
with:
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
script: |
|
script: |
|
||||||
const prNumber = context.payload.pull_request.number;
|
const prNumber = context.payload.pull_request.number;
|
||||||
|
|
||||||
await github.rest.issues.removeLabel({
|
await github.rest.issues.removeLabel({
|
||||||
owner: context.repo.owner,
|
owner: context.repo.owner,
|
||||||
repo: context.repo.repo,
|
repo: context.repo.repo,
|
||||||
issue_number: prNumber,
|
issue_number: prNumber,
|
||||||
name: process.env.TRUST_FORK_PR_LABEL
|
name: process.env.TRUST_FORK_PR_LABEL
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log(`Removed '${process.env.TRUST_FORK_PR_LABEL}' label from PR #${prNumber} as it received new commits`);
|
console.log(`Removed '${process.env.TRUST_FORK_PR_LABEL}' label from PR #${prNumber} as it received new commits`);
|
||||||
|
|
||||||
// Add a comment to the PR
|
// Add a comment to the PR
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BASE_IMAGE: openpilot-base
|
BASE_IMAGE: sunnypilot-base
|
||||||
DOCKER_REGISTRY: ghcr.io/commaai
|
DOCKER_REGISTRY: ghcr.io/sunnypilot
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $DOCKER_REGISTRY/$BASE_IMAGE:latest /bin/bash -c
|
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $DOCKER_REGISTRY/$BASE_IMAGE:latest /bin/bash -c
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
@@ -23,7 +23,7 @@ jobs:
|
|||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
- name: Push badges
|
- name: Push badges
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "scons -j$(nproc) && python3 selfdrive/ui/translations/create_badges.py"
|
${{ env.RUN }} "python3 selfdrive/ui/translations/create_badges.py"
|
||||||
|
|
||||||
rm .gitattributes
|
rm .gitattributes
|
||||||
|
|
||||||
|
|||||||
@@ -1,21 +1,40 @@
|
|||||||
name: Build All Tinygrad Models and Push to GitLab
|
name: Build and push all tinygrad models
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
branch:
|
set_min_version:
|
||||||
description: 'Branch to run workflow from'
|
description: 'Minimum selector version required for the models (see helpers.py or readme.md)'
|
||||||
required: false
|
required: true
|
||||||
default: 'master-new'
|
|
||||||
type: string
|
type: string
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
setup:
|
setup:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
outputs:
|
outputs:
|
||||||
|
json_version: ${{ steps.get-json.outputs.json_version }}
|
||||||
|
recompiled_dir: ${{ steps.create-recompiled-dir.outputs.recompiled_dir }}
|
||||||
json_file: ${{ steps.get-json.outputs.json_file }}
|
json_file: ${{ steps.get-json.outputs.json_file }}
|
||||||
|
model_matrix: ${{ steps.set-matrix.outputs.model_matrix }}
|
||||||
|
tinygrad_ref: ${{ steps.get-tinygrad-ref.outputs.tinygrad_ref }}
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout docs repo
|
- name: Checkout sunnypilot repo
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: sunnypilot/sunnypilot
|
||||||
|
path: sunnypilot
|
||||||
|
submodules: recursive
|
||||||
|
|
||||||
|
- name: Get tinygrad_repo ref
|
||||||
|
id: get-tinygrad-ref
|
||||||
|
run: |
|
||||||
|
cd sunnypilot
|
||||||
|
export PYTHONPATH=$(pwd)
|
||||||
|
ref=$(python3 sunnypilot/models/tinygrad_ref.py)
|
||||||
|
echo "tinygrad_ref=$ref" >> $GITHUB_OUTPUT
|
||||||
|
echo "tinygrad_ref is $ref"
|
||||||
|
|
||||||
|
- name: Checkout docs repo (sunnypilot-docs, gh-pages)
|
||||||
uses: actions/checkout@v4
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: sunnypilot/sunnypilot-docs
|
repository: sunnypilot/sunnypilot-docs
|
||||||
@@ -23,7 +42,7 @@ jobs:
|
|||||||
path: docs
|
path: docs
|
||||||
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Get next JSON version to use
|
- name: Get next JSON version to use (from GitHub docs repo)
|
||||||
id: get-json
|
id: get-json
|
||||||
run: |
|
run: |
|
||||||
cd docs/docs
|
cd docs/docs
|
||||||
@@ -31,19 +50,131 @@ jobs:
|
|||||||
next=$((latest+1))
|
next=$((latest+1))
|
||||||
json_file="driving_models_v${next}.json"
|
json_file="driving_models_v${next}.json"
|
||||||
cp "driving_models_v${latest}.json" "$json_file"
|
cp "driving_models_v${latest}.json" "$json_file"
|
||||||
echo "json_file=$json_file" >> $GITHUB_OUTPUT
|
echo "json_file=docs/docs/$json_file" >> $GITHUB_OUTPUT
|
||||||
|
echo "json_version=$((next+0))" >> $GITHUB_OUTPUT
|
||||||
|
echo "SRC_JSON_FILE=docs/docs/driving_models_v${latest}.json" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Upload context for next jobs
|
- name: Extract tinygrad models
|
||||||
uses: actions/upload-artifact@v4
|
id: set-matrix
|
||||||
|
working-directory: docs/docs
|
||||||
|
run: |
|
||||||
|
jq -c '[.bundles[] | select(.runner=="tinygrad") | {ref, display_name: (.display_name | gsub(" \\([^)]*\\)"; "")), is_20hz}]' "$(basename "${SRC_JSON_FILE}")" > matrix.json
|
||||||
|
echo "model_matrix=$(cat matrix.json)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Set up SSH
|
||||||
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
with:
|
with:
|
||||||
name: context
|
ssh-private-key: ${{ secrets.GITLAB_SSH_PRIVATE_KEY }}
|
||||||
path: docs
|
- run: |
|
||||||
|
mkdir -p ~/.ssh
|
||||||
|
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
build-all:
|
- name: Clone GitLab docs repo and create new recompiled dir
|
||||||
|
id: create-recompiled-dir
|
||||||
|
env:
|
||||||
|
GIT_SSH_COMMAND: 'ssh -o UserKnownHostsFile=~/.ssh/known_hosts'
|
||||||
|
run: |
|
||||||
|
git clone --depth 1 --filter=tree:0 --sparse git@gitlab.com:sunnypilot/public/${{ vars.MODELS_GITLAB }} gitlab_docs
|
||||||
|
cd gitlab_docs
|
||||||
|
git checkout main
|
||||||
|
git sparse-checkout set --no-cone models/
|
||||||
|
cd models
|
||||||
|
latest_dir=$(ls -d recompiled* 2>/dev/null | sed -E 's/recompiled([0-9]+)/\1/' | sort -n | tail -1)
|
||||||
|
if [[ -z "$latest_dir" ]]; then
|
||||||
|
next_dir=1
|
||||||
|
else
|
||||||
|
next_dir=$((latest_dir+1))
|
||||||
|
fi
|
||||||
|
recompiled_dir="${next_dir}"
|
||||||
|
mkdir -p "recompiled${recompiled_dir}"
|
||||||
|
touch "recompiled${recompiled_dir}/.gitkeep"
|
||||||
|
cd ../..
|
||||||
|
echo "recompiled_dir=$recompiled_dir" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Push empty recompiled dir to GitLab
|
||||||
|
run: |
|
||||||
|
cd gitlab_docs
|
||||||
|
git add models/recompiled${{ steps.create-recompiled-dir.outputs.recompiled_dir }}
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git config --global user.email "action@github.com"
|
||||||
|
git commit -m "Add recompiled${{ steps.create-recompiled-dir.outputs.recompiled_dir }} for build-all" || echo "No changes to commit"
|
||||||
|
git push origin main
|
||||||
|
|
||||||
|
- name: Push new JSON to GitHub docs repo
|
||||||
|
run: |
|
||||||
|
cd docs
|
||||||
|
git pull origin gh-pages
|
||||||
|
git add docs/"$(basename ${{ steps.get-json.outputs.json_file }})"
|
||||||
|
git config --global user.name "GitHub Action"
|
||||||
|
git config --global user.email "action@github.com"
|
||||||
|
git commit -m "Add new ${{ steps.get-json.outputs.json_file }} for build-all" || echo "No changes to commit"
|
||||||
|
git push origin gh-pages
|
||||||
|
|
||||||
|
get_and_build:
|
||||||
|
needs: [setup]
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
model: ${{ fromJson(needs.setup.outputs.model_matrix) }}
|
||||||
|
fail-fast: false
|
||||||
|
uses: ./.github/workflows/build-single-tinygrad-model.yaml
|
||||||
|
with:
|
||||||
|
upstream_branch: ${{ matrix.model.ref }}
|
||||||
|
custom_name: ${{ matrix.model.display_name }}
|
||||||
|
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
||||||
|
json_version: ${{ needs.setup.outputs.json_version }}
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
retry_failed_models:
|
||||||
|
needs: [setup, get_and_build]
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: setup
|
if: ${{ needs.setup.result != 'failure' && !cancelled() }}
|
||||||
|
outputs:
|
||||||
|
retry_matrix: ${{ steps.set-retry-matrix.outputs.retry_matrix }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
pattern: model-*
|
||||||
|
path: output
|
||||||
|
|
||||||
|
- id: set-retry-matrix
|
||||||
|
run: |
|
||||||
|
echo '${{ needs.setup.outputs.model_matrix }}' > matrix.json
|
||||||
|
built=(); while IFS= read -r line; do built+=("$line"); done < <(
|
||||||
|
ls output | sed -E 's/^model-//' | sed -E 's/-[0-9]+$//' | sed -E 's/ \([^)]*\)//' | awk '{gsub(/^ +| +$/, ""); print}'
|
||||||
|
)
|
||||||
|
jq -c --argjson built "$(printf '%s\n' "${built[@]}" | jq -R . | jq -s .)" \
|
||||||
|
'map(select(.display_name as $n | ($built | index($n | gsub("^ +| +$"; "")) | not)))' matrix.json > retry_matrix.json
|
||||||
|
echo "retry_matrix=$(cat retry_matrix.json)" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
retry_get_and_build:
|
||||||
|
needs: [setup, get_and_build, retry_failed_models]
|
||||||
|
if: ${{ needs.get_and_build.result == 'failure' || (needs.retry_failed_models.outputs.retry_matrix != '[]' && needs.retry_failed_models.outputs.retry_matrix != '') }}
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
model: ${{ fromJson(needs.retry_failed_models.outputs.retry_matrix) }}
|
||||||
|
fail-fast: false
|
||||||
|
uses: ./.github/workflows/build-single-tinygrad-model.yaml
|
||||||
|
with:
|
||||||
|
upstream_branch: ${{ matrix.model.ref }}
|
||||||
|
custom_name: ${{ matrix.model.display_name }}
|
||||||
|
recompiled_dir: ${{ needs.setup.outputs.recompiled_dir }}
|
||||||
|
json_version: ${{ needs.setup.outputs.json_version }}
|
||||||
|
artifact_suffix: -retry
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
publish_models:
|
||||||
|
name: Publish models sequentially
|
||||||
|
needs: [setup, get_and_build, retry_failed_models, retry_get_and_build]
|
||||||
|
if: ${{ !cancelled() && (needs.get_and_build.result != 'failure' || needs.retry_get_and_build.result == 'success' || (needs.retry_failed_models.outputs.retry_matrix != '[]' && needs.retry_failed_models.outputs.retry_matrix != '')) }}
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
strategy:
|
||||||
|
max-parallel: 1
|
||||||
|
matrix:
|
||||||
|
model: ${{ fromJson(needs.setup.outputs.model_matrix) }}
|
||||||
env:
|
env:
|
||||||
JSON_FILE: docs/docs/${{ needs.setup.outputs.json_file }}
|
RECOMPILED_DIR: recompiled${{ needs.setup.outputs.recompiled_dir }}
|
||||||
|
JSON_FILE: ${{ needs.setup.outputs.json_file }}
|
||||||
|
ARTIFACT_NAME_INPUT: ${{ matrix.model.display_name }}
|
||||||
steps:
|
steps:
|
||||||
- name: Set up SSH
|
- name: Set up SSH
|
||||||
uses: webfactory/ssh-agent@v0.9.0
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
@@ -60,140 +191,75 @@ jobs:
|
|||||||
GIT_SSH_COMMAND: 'ssh -o UserKnownHostsFile=~/.ssh/known_hosts'
|
GIT_SSH_COMMAND: 'ssh -o UserKnownHostsFile=~/.ssh/known_hosts'
|
||||||
run: |
|
run: |
|
||||||
echo "Cloning GitLab"
|
echo "Cloning GitLab"
|
||||||
git clone --depth 1 --filter=tree:0 --sparse git@gitlab.com:sunnypilot/public/docs.sunnypilot.ai2.git gitlab_docs
|
git clone --depth 1 --filter=tree:0 --sparse git@gitlab.com:sunnypilot/public/${{ vars.MODELS_GITLAB }} gitlab_docs
|
||||||
cd gitlab_docs
|
cd gitlab_docs
|
||||||
|
echo "checkout models/${RECOMPILED_DIR}"
|
||||||
|
git sparse-checkout set --no-cone models/${RECOMPILED_DIR}
|
||||||
git checkout main
|
git checkout main
|
||||||
cd ..
|
cd ..
|
||||||
|
|
||||||
- name: Set next recompiled dir
|
- name: Checkout docs repo
|
||||||
id: set-recompiled
|
uses: actions/checkout@v4
|
||||||
run: |
|
|
||||||
cd gitlab_docs/models
|
|
||||||
latest_dir=$(ls -d recompiled* 2>/dev/null | sed -E 's/recompiled([0-9]+)/\1/' | sort -n | tail -1)
|
|
||||||
if [[ -z "$latest_dir" ]]; then
|
|
||||||
next_dir=1
|
|
||||||
else
|
|
||||||
next_dir=$((latest_dir+1))
|
|
||||||
fi
|
|
||||||
recompiled_dir="recompiled${next_dir}"
|
|
||||||
mkdir -p "$recompiled_dir"
|
|
||||||
echo "RECOMPILED_DIR=$recompiled_dir" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Download context
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
with:
|
||||||
name: context
|
repository: sunnypilot/sunnypilot-docs
|
||||||
path: .
|
ref: gh-pages
|
||||||
|
path: docs
|
||||||
|
ssh-key: ${{ secrets.CI_SUNNYPILOT_DOCS_PRIVATE_KEY }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Validate recompiled dir and JSON version
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
if [ ! -d "gitlab_docs/models/$RECOMPILED_DIR" ]; then
|
||||||
sudo apt-get install -y jq gh
|
echo "Recompiled dir $RECOMPILED_DIR does not exist in GitLab repo"
|
||||||
|
exit 1
|
||||||
- name: Build all tinygrad models
|
fi
|
||||||
id: trigger-builds
|
if [ ! -f "$JSON_FILE" ]; then
|
||||||
env:
|
echo "JSON file $JSON_FILE does not exist!"
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
> triggered_run_ids.txt
|
|
||||||
BRANCH="${{ github.event.inputs.branch }}"
|
|
||||||
jq -c '.bundles[] | select(.runner=="tinygrad")' "$JSON_FILE" | while read -r bundle; do
|
|
||||||
ref=$(echo "$bundle" | jq -r '.ref')
|
|
||||||
display_name=$(echo "$bundle" | jq -r '.display_name' | sed 's/ ([^)]*)//g')
|
|
||||||
is_20hz=$(echo "$bundle" | jq -r '.is_20hz')
|
|
||||||
echo "Triggering build for: $display_name ($ref) [20Hz: $is_20hz]"
|
|
||||||
START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
gh workflow run sunnypilot-build-model.yaml \
|
|
||||||
--repo sunnypilot/sunnypilot \
|
|
||||||
--ref "$BRANCH" \
|
|
||||||
-f upstream_branch="$ref" \
|
|
||||||
-f custom_name="$display_name" \
|
|
||||||
-f is_20hz="$is_20hz"
|
|
||||||
for i in {1..24}; do
|
|
||||||
RUN_ID=$(gh run list --repo sunnypilot/sunnypilot --workflow=sunnypilot-build-model.yaml --branch="$BRANCH" --created ">$START_TIME" --limit=1 --json databaseId --jq '.[0].databaseId')
|
|
||||||
if [ -n "$RUN_ID" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
if [ -z "$RUN_ID" ]; then
|
|
||||||
echo "ould not find the triggered workflow run for $display_name ($ref)"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
echo "$RUN_ID" >> triggered_run_ids.txt
|
|
||||||
done
|
|
||||||
|
|
||||||
- name: Wait for all model builds to finish
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
set -e
|
|
||||||
SUCCESS_RUNS=()
|
|
||||||
FAILED_RUNS=()
|
|
||||||
declare -A RUN_ID_TO_NAME
|
|
||||||
|
|
||||||
while read -r RUN_ID; do
|
|
||||||
ARTIFACT_NAME=$(gh api repos/sunnypilot/sunnypilot/actions/runs/$RUN_ID/artifacts --jq '.artifacts[] | select(.name | startswith("model-")) | .name' || echo "unknown")
|
|
||||||
RUN_ID_TO_NAME["$RUN_ID"]="$ARTIFACT_NAME"
|
|
||||||
done < triggered_run_ids.txt
|
|
||||||
|
|
||||||
while read -r RUN_ID; do
|
|
||||||
echo "Watching run ID: $RUN_ID"
|
|
||||||
gh run watch "$RUN_ID" --repo sunnypilot/sunnypilot
|
|
||||||
CONCLUSION=$(gh run view "$RUN_ID" --repo sunnypilot/sunnypilot --json conclusion --jq '.conclusion')
|
|
||||||
ARTIFACT_NAME="${RUN_ID_TO_NAME[$RUN_ID]}"
|
|
||||||
echo "Run $RUN_ID ($ARTIFACT_NAME) concluded with: $CONCLUSION"
|
|
||||||
if [[ "$CONCLUSION" == "success" ]]; then
|
|
||||||
SUCCESS_RUNS+=("$RUN_ID")
|
|
||||||
else
|
|
||||||
FAILED_RUNS+=("$RUN_ID")
|
|
||||||
fi
|
|
||||||
done < triggered_run_ids.txt
|
|
||||||
|
|
||||||
if [[ ${#SUCCESS_RUNS[@]} -eq 0 ]]; then
|
|
||||||
echo "All model builds failed. Aborting."
|
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [[ ${#FAILED_RUNS[@]} -gt 0 ]]; then
|
- name: Download artifact name file
|
||||||
echo "WARNING: The following model builds failed:"
|
uses: actions/download-artifact@v4
|
||||||
for RUN_ID in "${FAILED_RUNS[@]}"; do
|
with:
|
||||||
echo "- $RUN_ID (${RUN_ID_TO_NAME[$RUN_ID]})"
|
name: artifact-name-${{ env.ARTIFACT_NAME_INPUT }}
|
||||||
done
|
path: artifact_name
|
||||||
echo "You may want to rerun these models manually."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Download and extract all model artifacts
|
- name: Read artifact name
|
||||||
env:
|
id: read-artifact-name
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
run: |
|
||||||
ARTIFACT_DIR="gitlab_docs/models/$RECOMPILED_DIR"
|
ARTIFACT_NAME=$(cat artifact_name/artifact_name.txt)
|
||||||
SUCCESS_RUNS=()
|
echo "artifact_name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
|
||||||
while read -r RUN_ID; do
|
|
||||||
CONCLUSION=$(gh run view "$RUN_ID" --repo sunnypilot/sunnypilot --json conclusion --jq '.conclusion')
|
|
||||||
if [[ "$CONCLUSION" == "success" ]]; then
|
|
||||||
SUCCESS_RUNS+=("$RUN_ID")
|
|
||||||
fi
|
|
||||||
done < triggered_run_ids.txt
|
|
||||||
|
|
||||||
for RUN_ID in "${SUCCESS_RUNS[@]}"; do
|
- name: Download model artifact
|
||||||
ARTIFACT_NAME=$(gh api repos/sunnypilot/sunnypilot/actions/runs/$RUN_ID/artifacts --jq '.artifacts[] | select(.name | startswith("model-")) | .name')
|
uses: actions/download-artifact@v4
|
||||||
echo "Downloading artifact: $ARTIFACT_NAME from run: $RUN_ID"
|
with:
|
||||||
mkdir -p "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
name: ${{ steps.read-artifact-name.outputs.artifact_name }}
|
||||||
echo "Created directory: $ARTIFACT_DIR/$ARTIFACT_NAME"
|
path: output
|
||||||
gh run download "$RUN_ID" --repo sunnypilot/sunnypilot -n "$ARTIFACT_NAME" --dir "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
|
||||||
echo "Downloaded artifact zip(s) to: $ARTIFACT_DIR/$ARTIFACT_NAME"
|
- name: Remove onnx files bc not needed for recompiled dir since they already exist from single build
|
||||||
ZIP_PATH=$(find "$ARTIFACT_DIR/$ARTIFACT_NAME" -type f -name '*.zip' | head -n1)
|
run: |
|
||||||
if [ -n "$ZIP_PATH" ]; then
|
find output -type f -name '*.onnx' -delete
|
||||||
echo "Unzipping $ZIP_PATH to $ARTIFACT_DIR/$ARTIFACT_NAME"
|
find output -type f -name 'big_*.pkl' -delete
|
||||||
unzip -o "$ZIP_PATH" -d "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
find output -type f -name 'dmonitoring_model_tinygrad.pkl' -delete
|
||||||
rm -f "$ZIP_PATH"
|
|
||||||
echo "Unzipped and removed $ZIP_PATH"
|
- name: Copy model artifacts to gitlab
|
||||||
else
|
env:
|
||||||
echo "No zip file found in $ARTIFACT_DIR/$ARTIFACT_NAME (This is NOT an error)."
|
ARTIFACT_NAME: ${{ steps.read-artifact-name.outputs.artifact_name }}
|
||||||
|
run: |
|
||||||
|
ARTIFACT_DIR="gitlab_docs/models/${RECOMPILED_DIR}/${ARTIFACT_NAME}"
|
||||||
|
mkdir -p "$ARTIFACT_DIR"
|
||||||
|
for path in output/*; do
|
||||||
|
if [ "$(basename "$path")" = "artifact_name.txt" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
name="$(basename "$path")"
|
||||||
|
if [ -d "$path" ]; then
|
||||||
|
mkdir -p "$ARTIFACT_DIR/$name"
|
||||||
|
cp -r "$path"/* "$ARTIFACT_DIR/$name/"
|
||||||
|
echo "Copied dir $name -> $ARTIFACT_DIR/$name"
|
||||||
|
else
|
||||||
|
cp "$path" "$ARTIFACT_DIR/"
|
||||||
|
echo "Copied file $name -> $ARTIFACT_DIR/"
|
||||||
fi
|
fi
|
||||||
echo "Done processing $ARTIFACT_NAME"
|
|
||||||
done
|
done
|
||||||
|
|
||||||
- name: Push recompiled dir to GitLab
|
- name: Push recompiled dir to GitLab
|
||||||
@@ -202,25 +268,36 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd gitlab_docs
|
cd gitlab_docs
|
||||||
git checkout main
|
git checkout main
|
||||||
mkdir -p models/"$(basename $RECOMPILED_DIR)"
|
git pull origin main
|
||||||
git add models/"$(basename $RECOMPILED_DIR)"
|
for d in models/"$RECOMPILED_DIR"/*/; do
|
||||||
|
git sparse-checkout add "$d"
|
||||||
|
done
|
||||||
|
git add models/"$RECOMPILED_DIR"
|
||||||
git config --global user.name "GitHub Action"
|
git config --global user.name "GitHub Action"
|
||||||
git config --global user.email "action@github.com"
|
git config --global user.email "action@github.com"
|
||||||
git commit -m "Add $(basename $RECOMPILED_DIR) from build-all-tinygrad-models"
|
git commit -m "Update $RECOMPILED_DIR with model from build-all-tinygrad-models" || echo "No changes to commit"
|
||||||
git push origin main
|
git push origin main
|
||||||
|
- run: |
|
||||||
|
cd docs
|
||||||
|
git pull origin gh-pages
|
||||||
|
|
||||||
- name: Run json_parser.py to update JSON
|
- name: update json
|
||||||
run: |
|
run: |
|
||||||
python3 docs/json_parser.py \
|
ARGS=""
|
||||||
|
[ -n "${{ inputs.set_min_version }}" ] && ARGS="$ARGS --set-min-version \"${{ inputs.set_min_version }}\""
|
||||||
|
ARGS="$ARGS --sort-by-date"
|
||||||
|
ARGS="$ARGS --tinygrad-ref \"${{ needs.setup.outputs.tinygrad_ref }}\""
|
||||||
|
eval python3 docs/json_parser.py \
|
||||||
--json-path "$JSON_FILE" \
|
--json-path "$JSON_FILE" \
|
||||||
--recompiled-dir "gitlab_docs/models/$RECOMPILED_DIR"
|
--recompiled-dir "gitlab_docs/models/$RECOMPILED_DIR" \
|
||||||
|
$ARGS
|
||||||
|
|
||||||
- name: Push updated JSON to GitHub docs repo
|
- name: Push updated json to GitHub
|
||||||
run: |
|
run: |
|
||||||
cd docs
|
cd docs
|
||||||
git config --global user.name "GitHub Action"
|
git config --global user.name "GitHub Action"
|
||||||
git config --global user.email "action@github.com"
|
git config --global user.email "action@github.com"
|
||||||
git checkout gh-pages
|
git checkout gh-pages
|
||||||
git add docs/"$(basename $JSON_FILE)"
|
git add docs/"$(basename $JSON_FILE)"
|
||||||
git commit -m "Update $(basename $JSON_FILE) after recompiling models" || echo "No changes to commit"
|
git commit -m "Update $(basename $JSON_FILE) after recompiling model" || echo "No changes to commit"
|
||||||
git push origin gh-pages
|
git push origin gh-pages
|
||||||
|
|||||||
@@ -1,13 +1,8 @@
|
|||||||
name: Build Single Tinygrad Model and Push
|
name: Build Single Tinygrad Model and Push
|
||||||
|
|
||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_call:
|
||||||
inputs:
|
inputs:
|
||||||
build_model_ref:
|
|
||||||
description: 'Branch to use for build-model workflow'
|
|
||||||
required: false
|
|
||||||
default: 'master-new'
|
|
||||||
type: string
|
|
||||||
upstream_branch:
|
upstream_branch:
|
||||||
description: 'Upstream commit to build from'
|
description: 'Upstream commit to build from'
|
||||||
required: true
|
required: true
|
||||||
@@ -19,17 +14,47 @@ on:
|
|||||||
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
|
||||||
type: number
|
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. 5 for driving_models_v5.json)'
|
||||||
required: true
|
required: true
|
||||||
type: number
|
type: string
|
||||||
|
artifact_suffix:
|
||||||
|
description: 'Suffix for artifact name'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
|
bypass_push:
|
||||||
|
description: 'Bypass pushing to GitLab for build-all'
|
||||||
|
required: false
|
||||||
|
default: true
|
||||||
|
type: boolean
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
upstream_branch:
|
||||||
|
description: 'Upstream commit to build from'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
custom_name:
|
||||||
|
description: 'Custom name for the model (no date, only name)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
recompiled_dir:
|
||||||
|
description: 'Existing recompiled directory number (e.g. 3 for recompiled3)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
|
json_version:
|
||||||
|
description: 'driving_models version number to update (e.g. 5 for driving_models_v5.json)'
|
||||||
|
required: true
|
||||||
|
type: string
|
||||||
model_folder:
|
model_folder:
|
||||||
description: 'Model folder'
|
description: 'Model folder'
|
||||||
required: true
|
|
||||||
type: choice
|
type: choice
|
||||||
|
default: 'None'
|
||||||
options:
|
options:
|
||||||
|
- None
|
||||||
- Simple Plan Models
|
- Simple Plan Models
|
||||||
|
- Space Lab Models
|
||||||
- TR Models
|
- TR Models
|
||||||
- DTR Models
|
- DTR Models
|
||||||
- Custom Merge Models
|
- Custom Merge Models
|
||||||
@@ -42,18 +67,32 @@ on:
|
|||||||
generation:
|
generation:
|
||||||
description: 'Model generation'
|
description: 'Model generation'
|
||||||
required: false
|
required: false
|
||||||
type: number
|
type: string
|
||||||
version:
|
version:
|
||||||
description: 'Minimum selector version'
|
description: 'Minimum selector version'
|
||||||
required: false
|
required: false
|
||||||
type: number
|
type: string
|
||||||
|
env:
|
||||||
|
RECOMPILED_DIR: recompiled${{ inputs.recompiled_dir }}
|
||||||
|
JSON_FILE: docs/docs/driving_models_v${{ inputs.json_version }}.json
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-single:
|
build_model:
|
||||||
|
uses: ./.github/workflows/sunnypilot-build-model.yaml
|
||||||
|
with:
|
||||||
|
upstream_branch: ${{ inputs.upstream_branch }}
|
||||||
|
custom_name: ${{ inputs.custom_name || inputs.upstream_branch }}
|
||||||
|
is_20hz: true
|
||||||
|
artifact_suffix: ${{ inputs.artifact_suffix }}
|
||||||
|
secrets: inherit
|
||||||
|
|
||||||
|
publish_model:
|
||||||
|
if: ${{ !inputs.bypass_push && !cancelled() }}
|
||||||
|
concurrency:
|
||||||
|
group: gitlab-push-${{ inputs.recompiled_dir }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
needs: build_model
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
env:
|
|
||||||
RECOMPILED_DIR: recompiled${{ github.event.inputs.recompiled_dir }}
|
|
||||||
JSON_FILE: docs/docs/driving_models_v${{ github.event.inputs.json_version }}.json
|
|
||||||
steps:
|
steps:
|
||||||
- name: Set up SSH
|
- name: Set up SSH
|
||||||
uses: webfactory/ssh-agent@v0.9.0
|
uses: webfactory/ssh-agent@v0.9.0
|
||||||
@@ -70,7 +109,7 @@ jobs:
|
|||||||
GIT_SSH_COMMAND: 'ssh -o UserKnownHostsFile=~/.ssh/known_hosts'
|
GIT_SSH_COMMAND: 'ssh -o UserKnownHostsFile=~/.ssh/known_hosts'
|
||||||
run: |
|
run: |
|
||||||
echo "Cloning GitLab"
|
echo "Cloning GitLab"
|
||||||
git clone --depth 1 --filter=tree:0 --sparse git@gitlab.com:sunnypilot/public/docs.sunnypilot.ai2.git gitlab_docs
|
git clone --depth 1 --filter=tree:0 --sparse git@gitlab.com:sunnypilot/public/${{ vars.MODELS_GITLAB }} gitlab_docs
|
||||||
cd gitlab_docs
|
cd gitlab_docs
|
||||||
echo "checkout models/${RECOMPILED_DIR}"
|
echo "checkout models/${RECOMPILED_DIR}"
|
||||||
git sparse-checkout set --no-cone models/${RECOMPILED_DIR}
|
git sparse-checkout set --no-cone models/${RECOMPILED_DIR}
|
||||||
@@ -96,66 +135,49 @@ jobs:
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Download artifact name file
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
name: artifact-name-${{ inputs.custom_name || inputs.upstream_branch }}
|
||||||
|
path: artifact_name
|
||||||
|
|
||||||
|
- name: Read artifact name
|
||||||
|
id: read-artifact-name
|
||||||
run: |
|
run: |
|
||||||
sudo apt-get update
|
ARTIFACT_NAME=$(cat artifact_name/artifact_name.txt)
|
||||||
sudo apt-get install -y jq gh
|
echo "artifact_name=$ARTIFACT_NAME" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
- name: Build model
|
|
||||||
env:
|
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
||||||
run: |
|
|
||||||
START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
gh workflow run sunnypilot-build-model.yaml \
|
|
||||||
--repo sunnypilot/sunnypilot \
|
|
||||||
--ref "${{ github.event.inputs.build_model_ref }}" \
|
|
||||||
-f upstream_branch="${{ github.event.inputs.upstream_branch }}" \
|
|
||||||
-f custom_name="${{ github.event.inputs.custom_name }}"
|
|
||||||
|
|
||||||
for i in {1..24}; do
|
|
||||||
RUN_ID=$(gh run list --repo sunnypilot/sunnypilot --workflow=sunnypilot-build-model.yaml --branch="${{ github.event.inputs.build_model_ref }}" --created ">$START_TIME" --limit=1 --json databaseId --jq '.[0].databaseId')
|
|
||||||
if [ -n "$RUN_ID" ]; then
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
sleep 5
|
|
||||||
done
|
|
||||||
|
|
||||||
if [ -z "$RUN_ID" ]; then
|
|
||||||
echo "Could not find the triggered workflow run."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
echo "Watching run ID: $RUN_ID"
|
|
||||||
gh run watch "$RUN_ID" --repo sunnypilot/sunnypilot
|
|
||||||
CONCLUSION=$(gh run view "$RUN_ID" --repo sunnypilot/sunnypilot --json conclusion --jq '.conclusion')
|
|
||||||
echo "Run concluded with: $CONCLUSION"
|
|
||||||
if [[ "$CONCLUSION" != "success" ]]; then
|
|
||||||
echo "Workflow run failed with conclusion: $CONCLUSION"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Download and extract model artifact
|
- name: Download and extract model artifact
|
||||||
env:
|
uses: actions/download-artifact@v4
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
with:
|
||||||
|
name: ${{ steps.read-artifact-name.outputs.artifact_name }}
|
||||||
|
path: output
|
||||||
|
|
||||||
|
- name: Remove unwanted files
|
||||||
run: |
|
run: |
|
||||||
ARTIFACT_DIR="gitlab_docs/models/$RECOMPILED_DIR"
|
find output -type f -name 'dmonitoring_model_tinygrad.pkl' -delete
|
||||||
RUN_ID=$(gh run list --repo sunnypilot/sunnypilot --workflow=sunnypilot-build-model.yaml --branch="${{ github.event.inputs.build_model_ref }}" --limit=1 --json databaseId --jq '.[0].databaseId')
|
find output -type f -name 'dmonitoring_model.onnx' -delete
|
||||||
ARTIFACT_NAME=$(gh api repos/sunnypilot/sunnypilot/actions/runs/$RUN_ID/artifacts --jq '.artifacts[] | select(.name | startswith("model-")) | .name')
|
|
||||||
echo "Downloading artifact: $ARTIFACT_NAME from run: $RUN_ID"
|
- name: Copy model artifact(s) to GitLab recompiled dir
|
||||||
mkdir -p "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
env:
|
||||||
echo "Created directory: $ARTIFACT_DIR/$ARTIFACT_NAME"
|
ARTIFACT_NAME: ${{ steps.read-artifact-name.outputs.artifact_name }}
|
||||||
gh run download "$RUN_ID" --repo sunnypilot/sunnypilot -n "$ARTIFACT_NAME" --dir "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
run: |
|
||||||
echo "Downloaded artifact zip(s) to: $ARTIFACT_DIR/$ARTIFACT_NAME"
|
ARTIFACT_DIR="gitlab_docs/models/${RECOMPILED_DIR}/${ARTIFACT_NAME}"
|
||||||
ZIP_PATH=$(find "$ARTIFACT_DIR/$ARTIFACT_NAME" -type f -name '*.zip' | head -n1)
|
mkdir -p "$ARTIFACT_DIR"
|
||||||
if [ -n "$ZIP_PATH" ]; then
|
for path in output/*; do
|
||||||
echo "Unzipping $ZIP_PATH to $ARTIFACT_DIR/$ARTIFACT_NAME"
|
if [ "$(basename "$path")" = "artifact_name.txt" ]; then
|
||||||
unzip -o "$ZIP_PATH" -d "$ARTIFACT_DIR/$ARTIFACT_NAME"
|
continue
|
||||||
rm -f "$ZIP_PATH"
|
fi
|
||||||
echo "Unzipped and removed $ZIP_PATH"
|
name="$(basename "$path")"
|
||||||
else
|
if [ -d "$path" ]; then
|
||||||
echo "No zip file found in $ARTIFACT_DIR/$ARTIFACT_NAME"
|
mkdir -p "$ARTIFACT_DIR/$name"
|
||||||
fi
|
cp -r "$path"/* "$ARTIFACT_DIR/$name/"
|
||||||
echo "Done processing $ARTIFACT_NAME"
|
echo "Copied dir $name -> $ARTIFACT_DIR/$name"
|
||||||
|
else
|
||||||
|
cp "$path" "$ARTIFACT_DIR/"
|
||||||
|
echo "Copied file $name -> $ARTIFACT_DIR/"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
- name: Push recompiled dir to GitLab
|
- name: Push recompiled dir to GitLab
|
||||||
env:
|
env:
|
||||||
@@ -163,28 +185,36 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd gitlab_docs
|
cd gitlab_docs
|
||||||
git checkout main
|
git checkout main
|
||||||
|
git pull origin main
|
||||||
for d in models/"$RECOMPILED_DIR"/*/; do
|
for d in models/"$RECOMPILED_DIR"/*/; do
|
||||||
git sparse-checkout add "$d"
|
git sparse-checkout add "$d"
|
||||||
done
|
done
|
||||||
git add models/"$RECOMPILED_DIR"
|
git add models/"$RECOMPILED_DIR"
|
||||||
git config --global user.name "GitHub Action"
|
git config --global user.name "GitHub Action"
|
||||||
git config --global user.email "action@github.com"
|
git config --global user.email "action@github.com"
|
||||||
git commit -m "Update $RECOMPILED_DIR with new/updated model from build-single-tinygrad-model" || echo "No changes to commit"
|
git commit -m "Create/Update $RECOMPILED_DIR with new/updated model from build-single-tinygrad-model" || echo "No changes to commit"
|
||||||
git push origin main
|
git push origin main
|
||||||
|
|
||||||
|
- run: |
|
||||||
|
cd docs
|
||||||
|
git pull origin gh-pages
|
||||||
|
|
||||||
- name: Run json_parser.py to update JSON
|
- name: Run json_parser.py to update JSON
|
||||||
run: |
|
run: |
|
||||||
FOLDER="${{ github.event.inputs.model_folder }}"
|
FOLDER="${{ inputs.model_folder }}"
|
||||||
if [ "$FOLDER" = "Other" ]; then
|
if [ "$FOLDER" = "Other" ]; then
|
||||||
FOLDER="${{ github.event.inputs.custom_model_folder }}"
|
FOLDER="${{ inputs.custom_model_folder }}"
|
||||||
fi
|
fi
|
||||||
ARGS=""
|
ARGS=""
|
||||||
[ -n "$FOLDER" ] && ARGS="$ARGS --model-folder \"$FOLDER\""
|
if [ "$FOLDER" != "None" ] && [ -n "$FOLDER" ]; then
|
||||||
[ -n "${{ github.event.inputs.generation }}" ] && ARGS="$ARGS --generation \"${{ github.event.inputs.generation }}\""
|
ARGS="$ARGS --model-folder \"$FOLDER\""
|
||||||
[ -n "${{ github.event.inputs.version }}" ] && ARGS="$ARGS --version \"${{ github.event.inputs.version }}\""
|
fi
|
||||||
|
[ -n "${{ inputs.generation }}" ] && ARGS="$ARGS --generation \"${{ inputs.generation }}\""
|
||||||
|
[ -n "${{ inputs.version }}" ] && ARGS="$ARGS --version \"${{ inputs.version }}\""
|
||||||
eval python3 docs/json_parser.py \
|
eval python3 docs/json_parser.py \
|
||||||
--json-path "$JSON_FILE" \
|
--json-path "$JSON_FILE" \
|
||||||
--recompiled-dir "gitlab_docs/models/$RECOMPILED_DIR" \
|
--recompiled-dir "gitlab_docs/models/$RECOMPILED_DIR" \
|
||||||
|
--sort-by-date \
|
||||||
$ARGS
|
$ARGS
|
||||||
|
|
||||||
- name: Push updated JSON to GitHub docs repo
|
- name: Push updated JSON to GitHub docs repo
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- master-new
|
|
||||||
pull_request:
|
pull_request:
|
||||||
paths:
|
paths:
|
||||||
- 'cereal/**'
|
- 'cereal/**'
|
||||||
@@ -17,7 +16,7 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: cereal-validation-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
group: cereal-validation-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ concurrency:
|
|||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
selfdrive_tests:
|
tests:
|
||||||
uses: sunnypilot/sunnypilot/.github/workflows/selfdrive_tests.yaml@master
|
uses: sunnypilot/sunnypilot/.github/workflows/tests.yaml@master
|
||||||
with:
|
with:
|
||||||
run_number: ${{ inputs.run_number }}
|
run_number: ${{ inputs.run_number }}
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ runs:
|
|||||||
scons -j$(nproc) --cache-populate"
|
scons -j$(nproc) --cache-populate"
|
||||||
- name: Save scons cache
|
- name: Save scons cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v4
|
||||||
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new')
|
if: github.ref == 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
path: .ci_cache/scons_cache
|
path: .ci_cache/scons_cache
|
||||||
key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
key: scons-${{ runner.arch }}-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||||
|
|||||||
@@ -9,6 +9,9 @@ jobs:
|
|||||||
scan-comments:
|
scan-comments:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: ${{ github.event.issue.pull_request }}
|
if: ${{ github.event.issue.pull_request }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
issues: write
|
||||||
steps:
|
steps:
|
||||||
- name: Check for trigger phrase
|
- name: Check for trigger phrase
|
||||||
id: check_comment
|
id: check_comment
|
||||||
@@ -43,3 +46,14 @@ jobs:
|
|||||||
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
git config --global user.email "github-actions[bot]@users.noreply.github.com"
|
||||||
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
|
git checkout -b tmp-jenkins-${{ github.event.issue.number }}
|
||||||
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}
|
GIT_LFS_SKIP_PUSH=1 git push -f origin tmp-jenkins-${{ github.event.issue.number }}
|
||||||
|
|
||||||
|
- name: Delete trigger comment
|
||||||
|
if: steps.check_comment.outputs.result == 'true' && always()
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
await github.rest.issues.deleteComment({
|
||||||
|
owner: context.repo.owner,
|
||||||
|
repo: context.repo.repo,
|
||||||
|
comment_id: context.payload.comment.id,
|
||||||
|
});
|
||||||
|
|||||||
@@ -9,11 +9,11 @@ on:
|
|||||||
- cron: '0 0 * * *' # Runs at 00:00 UTC every day
|
- cron: '0 0 * * *' # Runs at 00:00 UTC every day
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- 'master-new'
|
- 'master'
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- 'master-new'
|
- 'master'
|
||||||
workflow_dispatch: # enables manual triggering
|
workflow_dispatch: # enables manual triggering
|
||||||
inputs:
|
inputs:
|
||||||
upstream_branch:
|
upstream_branch:
|
||||||
default: 'master'
|
default: 'master'
|
||||||
@@ -30,7 +30,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: 'commaai/openpilot'
|
repository: 'commaai/openpilot'
|
||||||
ref: ${{ inputs.upstream_branch }}
|
ref: ${{ inputs.upstream_branch }}
|
||||||
|
|
||||||
- name: LFS Fetch
|
- name: LFS Fetch
|
||||||
run: |
|
run: |
|
||||||
git lfs fetch
|
git lfs fetch
|
||||||
@@ -48,7 +48,7 @@ jobs:
|
|||||||
- name: Add GitLab public keys
|
- name: Add GitLab public keys
|
||||||
run: |
|
run: |
|
||||||
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
|
ssh-keyscan -H gitlab.com >> ~/.ssh/known_hosts
|
||||||
|
|
||||||
- name: Ensure branch
|
- name: Ensure branch
|
||||||
run: |
|
run: |
|
||||||
if git symbolic-ref -q HEAD >/dev/null; then
|
if git symbolic-ref -q HEAD >/dev/null; then
|
||||||
|
|||||||
@@ -0,0 +1,105 @@
|
|||||||
|
name: 'Post to Discourse'
|
||||||
|
description: 'Posts a message to a Discourse topic (existing or new)'
|
||||||
|
|
||||||
|
inputs:
|
||||||
|
discourse-url:
|
||||||
|
description: 'Discourse instance URL (e.g., https://discourse.example.com)'
|
||||||
|
required: true
|
||||||
|
api-key:
|
||||||
|
description: 'Discourse API key'
|
||||||
|
required: true
|
||||||
|
api-username:
|
||||||
|
description: 'Discourse API username'
|
||||||
|
required: true
|
||||||
|
topic-id:
|
||||||
|
description: 'Discourse topic ID to post to (use this OR category-id + title)'
|
||||||
|
required: false
|
||||||
|
category-id:
|
||||||
|
description: 'Category ID for new topic (required if topic-id not provided)'
|
||||||
|
required: false
|
||||||
|
title:
|
||||||
|
description: 'Title for new topic (required if topic-id not provided)'
|
||||||
|
required: false
|
||||||
|
message:
|
||||||
|
description: 'Message content (markdown supported)'
|
||||||
|
required: true
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
post-number:
|
||||||
|
description: 'The post number in the topic'
|
||||||
|
value: ${{ steps.post.outputs.post_number }}
|
||||||
|
post-url:
|
||||||
|
description: 'Direct URL to the post'
|
||||||
|
value: ${{ steps.post.outputs.post_url }}
|
||||||
|
topic-id:
|
||||||
|
description: 'The topic ID (useful when creating a new topic)'
|
||||||
|
value: ${{ steps.post.outputs.topic_id }}
|
||||||
|
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Post to Discourse
|
||||||
|
id: post
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
# Validate inputs
|
||||||
|
if [ -z "${{ inputs.topic-id }}" ] && ([ -z "${{ inputs.category-id }}" ] || [ -z "${{ inputs.title }}" ]); then
|
||||||
|
echo "❌ Error: Must provide either topic-id OR both category-id and title"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -n "${{ inputs.topic-id }}" ] && ([ -n "${{ inputs.category-id }}" ] || [ -n "${{ inputs.title }}" ]); then
|
||||||
|
echo "⚠️ Warning: Both topic-id and category-id/title provided. Will post to existing topic."
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Determine if creating new topic or posting to existing
|
||||||
|
if [ -n "${{ inputs.topic-id }}" ]; then
|
||||||
|
echo "📝 Posting to existing topic ID: ${{ inputs.topic-id }}"
|
||||||
|
|
||||||
|
# Create JSON payload for posting to existing topic
|
||||||
|
PAYLOAD=$(jq -n \
|
||||||
|
--arg content '${{ inputs.message }}' \
|
||||||
|
--arg topic_id "${{ inputs.topic-id }}" \
|
||||||
|
'{topic_id: $topic_id, raw: $content}')
|
||||||
|
else
|
||||||
|
echo "✨ Creating new topic: ${{ inputs.title }}"
|
||||||
|
|
||||||
|
# Create JSON payload for new topic
|
||||||
|
PAYLOAD=$(jq -n \
|
||||||
|
--arg content '${{ inputs.message }}' \
|
||||||
|
--arg title "${{ inputs.title }}" \
|
||||||
|
--arg category "${{ inputs.category-id }}" \
|
||||||
|
'{title: $title, category: ($category | tonumber), raw: $content}')
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Post to Discourse
|
||||||
|
RESPONSE=$(curl -s -w "\n%{http_code}" \
|
||||||
|
-X POST "${{ inputs.discourse-url }}/posts.json" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
-H "Api-Key: ${{ inputs.api-key }}" \
|
||||||
|
-H "Api-Username: ${{ inputs.api-username }}" \
|
||||||
|
-d "$PAYLOAD")
|
||||||
|
|
||||||
|
HTTP_CODE=$(echo "$RESPONSE" | tail -n1)
|
||||||
|
BODY=$(echo "$RESPONSE" | sed '$d')
|
||||||
|
|
||||||
|
if [ "$HTTP_CODE" -ge 200 ] && [ "$HTTP_CODE" -lt 300 ]; then
|
||||||
|
echo "✅ Successfully posted to Discourse!"
|
||||||
|
|
||||||
|
POST_NUMBER=$(echo "$BODY" | jq -r '.post_number // "unknown"')
|
||||||
|
TOPIC_ID=$(echo "$BODY" | jq -r '.topic_id // "${{ inputs.topic-id }}"')
|
||||||
|
POST_URL="${{ inputs.discourse-url }}/t/${TOPIC_ID}/${POST_NUMBER}"
|
||||||
|
|
||||||
|
echo "post_number=${POST_NUMBER}" >> $GITHUB_OUTPUT
|
||||||
|
echo "post_url=${POST_URL}" >> $GITHUB_OUTPUT
|
||||||
|
echo "topic_id=${TOPIC_ID}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
echo "Topic ID: ${TOPIC_ID}"
|
||||||
|
echo "Post number: ${POST_NUMBER}"
|
||||||
|
echo "URL: ${POST_URL}"
|
||||||
|
else
|
||||||
|
echo "❌ Failed to post to Discourse"
|
||||||
|
echo "HTTP Code: ${HTTP_CODE}"
|
||||||
|
echo "Response: ${BODY}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -6,7 +6,7 @@ on:
|
|||||||
|
|
||||||
env:
|
env:
|
||||||
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
BUILD: selfdrive/test/docker_build.sh prebuilt
|
BUILD: release/ci/docker_build_sp.sh prebuilt
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_prebuilt:
|
build_prebuilt:
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
name: "ui preview"
|
name: "raylib ui preview"
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- master-new
|
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [assigned, opened, synchronize, reopened, edited]
|
types: [assigned, opened, synchronize, reopened, edited]
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
- 'master-new'
|
|
||||||
paths:
|
paths:
|
||||||
|
- 'selfdrive/assets/**'
|
||||||
- 'selfdrive/ui/**'
|
- 'selfdrive/ui/**'
|
||||||
|
- 'system/ui/**'
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
UI_JOB_NAME: "Create UI Report"
|
UI_JOB_NAME: "Create raylib UI Report"
|
||||||
REPORT_NAME: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && 'master' || github.event.number }}
|
REPORT_NAME: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
|
||||||
SHA: ${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && github.sha || github.event.pull_request.head.sha }}
|
SHA: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.sha || github.event.pull_request.head.sha }}
|
||||||
BRANCH_NAME: "openpilot/pr-${{ github.event.number }}"
|
BRANCH_NAME: "openpilot/pr-${{ github.event.number }}-raylib-ui"
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
preview:
|
preview:
|
||||||
@@ -54,7 +54,7 @@ jobs:
|
|||||||
github_token: ${{ secrets.GITHUB_TOKEN }}
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
run_id: ${{ steps.get_run_id.outputs.run_id }}
|
run_id: ${{ steps.get_run_id.outputs.run_id }}
|
||||||
search_artifacts: true
|
search_artifacts: true
|
||||||
name: report-1-${{ env.REPORT_NAME }}
|
name: raylib-report-1-${{ env.REPORT_NAME }}
|
||||||
path: ${{ github.workspace }}/pr_ui
|
path: ${{ github.workspace }}/pr_ui
|
||||||
|
|
||||||
- name: Getting master ui
|
- name: Getting master ui
|
||||||
@@ -62,23 +62,23 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
repository: sunnypilot/ci-artifacts
|
repository: sunnypilot/ci-artifacts
|
||||||
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
||||||
path: ${{ github.workspace }}/master_ui
|
path: ${{ github.workspace }}/master_ui_raylib
|
||||||
ref: openpilot_master_ui
|
ref: openpilot_master_ui_raylib
|
||||||
|
|
||||||
- name: Saving new master ui
|
- name: Saving new master ui
|
||||||
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && github.event_name == 'push'
|
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
|
||||||
working-directory: ${{ github.workspace }}/master_ui
|
working-directory: ${{ github.workspace }}/master_ui_raylib
|
||||||
run: |
|
run: |
|
||||||
git checkout --orphan=new_master_ui
|
git checkout --orphan=new_master_ui_raylib
|
||||||
git rm -rf *
|
git rm -rf *
|
||||||
git branch -D openpilot_master_ui
|
git branch -D openpilot_master_ui_raylib
|
||||||
git branch -m openpilot_master_ui
|
git branch -m openpilot_master_ui_raylib
|
||||||
git config user.name "GitHub Actions Bot"
|
git config user.name "GitHub Actions Bot"
|
||||||
git config user.email "<>"
|
git config user.email "<>"
|
||||||
mv ${{ github.workspace }}/pr_ui/*.png .
|
mv ${{ github.workspace }}/pr_ui/*.png .
|
||||||
git add .
|
git add .
|
||||||
git commit -m "screenshots for commit ${{ env.SHA }}"
|
git commit -m "raylib screenshots for commit ${{ env.SHA }}"
|
||||||
git push origin openpilot_master_ui --force
|
git push origin openpilot_master_ui_raylib --force
|
||||||
|
|
||||||
- name: Finding diff
|
- name: Finding diff
|
||||||
if: github.event_name == 'pull_request_target'
|
if: github.event_name == 'pull_request_target'
|
||||||
@@ -96,7 +96,7 @@ jobs:
|
|||||||
for ((i=0; i<${#A[*]}; i=i+1));
|
for ((i=0; i<${#A[*]}; i=i+1));
|
||||||
do
|
do
|
||||||
# Check if the master file exists
|
# Check if the master file exists
|
||||||
if [ ! -f "${{ github.workspace }}/master_ui/${A[$i]}.png" ]; then
|
if [ ! -f "${{ github.workspace }}/master_ui_raylib/${A[$i]}.png" ]; then
|
||||||
# This is a new file in PR UI that doesn't exist in master
|
# This is a new file in PR UI that doesn't exist in master
|
||||||
DIFF="${DIFF}<details open>"
|
DIFF="${DIFF}<details open>"
|
||||||
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{cyan}\\text{NEW}}\$\$</summary>"
|
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{cyan}\\text{NEW}}\$\$</summary>"
|
||||||
@@ -108,12 +108,12 @@ jobs:
|
|||||||
|
|
||||||
DIFF="${DIFF}</table>"
|
DIFF="${DIFF}</table>"
|
||||||
DIFF="${DIFF}</details>"
|
DIFF="${DIFF}</details>"
|
||||||
elif ! compare -fuzz 2% -highlight-color DeepSkyBlue1 -lowlight-color Black -compose Src ${{ github.workspace }}/master_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png; then
|
elif ! compare -fuzz 2% -highlight-color DeepSkyBlue1 -lowlight-color Black -compose Src ${{ github.workspace }}/master_ui_raylib/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png; then
|
||||||
convert ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png -transparent black mask.png
|
convert ${{ github.workspace }}/pr_ui/${A[$i]}_diff.png -transparent black mask.png
|
||||||
composite mask.png ${{ github.workspace }}/master_ui/${A[$i]}.png composite_diff.png
|
composite mask.png ${{ github.workspace }}/master_ui_raylib/${A[$i]}.png composite_diff.png
|
||||||
convert -delay 100 ${{ github.workspace }}/master_ui/${A[$i]}.png composite_diff.png -loop 0 ${{ github.workspace }}/pr_ui/${A[$i]}_diff.gif
|
convert -delay 100 ${{ github.workspace }}/master_ui_raylib/${A[$i]}.png composite_diff.png -loop 0 ${{ github.workspace }}/pr_ui/${A[$i]}_diff.gif
|
||||||
|
|
||||||
mv ${{ github.workspace }}/master_ui/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_master_ref.png
|
mv ${{ github.workspace }}/master_ui_raylib/${A[$i]}.png ${{ github.workspace }}/pr_ui/${A[$i]}_master_ref.png
|
||||||
|
|
||||||
DIFF="${DIFF}<details open>"
|
DIFF="${DIFF}<details open>"
|
||||||
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{red}\\text{DIFFERENT}}\$\$</summary>"
|
DIFF="${DIFF}<summary>${A[$i]} : \$\${\\color{red}\\text{DIFFERENT}}\$\$</summary>"
|
||||||
@@ -151,7 +151,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Saving proposed ui
|
- name: Saving proposed ui
|
||||||
if: github.event_name == 'pull_request_target'
|
if: github.event_name == 'pull_request_target'
|
||||||
working-directory: ${{ github.workspace }}/master_ui
|
working-directory: ${{ github.workspace }}/master_ui_raylib
|
||||||
run: |
|
run: |
|
||||||
git config user.name "GitHub Actions Bot"
|
git config user.name "GitHub Actions Bot"
|
||||||
git config user.email "<>"
|
git config user.email "<>"
|
||||||
@@ -159,7 +159,7 @@ jobs:
|
|||||||
git rm -rf *
|
git rm -rf *
|
||||||
mv ${{ github.workspace }}/pr_ui/* .
|
mv ${{ github.workspace }}/pr_ui/* .
|
||||||
git add .
|
git add .
|
||||||
git commit -m "screenshots for PR #${{ github.event.number }}"
|
git commit -m "raylib screenshots for PR #${{ github.event.number }}"
|
||||||
git push origin ${{ env.BRANCH_NAME }} --force
|
git push origin ${{ env.BRANCH_NAME }} --force
|
||||||
|
|
||||||
- name: Comment Screenshots on PR
|
- name: Comment Screenshots on PR
|
||||||
@@ -167,9 +167,9 @@ jobs:
|
|||||||
uses: thollander/actions-comment-pull-request@v2
|
uses: thollander/actions-comment-pull-request@v2
|
||||||
with:
|
with:
|
||||||
message: |
|
message: |
|
||||||
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
|
<!-- _(run_id_screenshots_raylib **${{ github.run_id }}**)_ -->
|
||||||
## UI Preview
|
## raylib UI Preview
|
||||||
${{ steps.find_diff.outputs.DIFF }}
|
${{ steps.find_diff.outputs.DIFF }}
|
||||||
comment_tag: run_id_screenshots
|
comment_tag: run_id_screenshots_raylib
|
||||||
pr_number: ${{ github.event.number }}
|
pr_number: ${{ github.event.number }}
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -3,7 +3,6 @@ name: Release Drafter
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master-new
|
|
||||||
- master
|
- master
|
||||||
tags:
|
tags:
|
||||||
- 'v*'
|
- 'v*'
|
||||||
|
|||||||
@@ -5,12 +5,12 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_masterci:
|
build___nightly:
|
||||||
name: build master-ci
|
name: build __nightly
|
||||||
env:
|
env:
|
||||||
ImageOS: ubuntu24
|
ImageOS: ubuntu24
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/commaai/openpilot-base:latest
|
image: ghcr.io/sunnypilot/sunnypilot-base:latest
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'sunnypilot/sunnypilot'
|
if: github.repository == 'sunnypilot/sunnypilot'
|
||||||
permissions:
|
permissions:
|
||||||
@@ -27,7 +27,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
ref: master
|
ref: master
|
||||||
wait-interval: 30
|
wait-interval: 30
|
||||||
running-workflow-name: 'build master-ci'
|
running-workflow-name: 'build __nightly'
|
||||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
check-regexp: ^((?!.*(build prebuilt).*).)*$
|
check-regexp: ^((?!.*(build prebuilt).*).)*$
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
@@ -38,5 +38,5 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory '*'
|
git config --global --add safe.directory '*'
|
||||||
git lfs pull
|
git lfs pull
|
||||||
- name: Push master-ci
|
- name: Push __nightly
|
||||||
run: BRANCH=__nightly release/build_devel.sh
|
run: BRANCH=__nightly release/build_stripped.sh
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
BASE_IMAGE: openpilot-base
|
BASE_IMAGE: sunnypilot-base
|
||||||
BUILD: selfdrive/test/docker_build.sh base
|
BUILD: release/ci/docker_build_sp.sh base
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
update_translations:
|
update_translations:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: github.repository == 'commaai/openpilot'
|
if: github.repository == 'sunnypilot/sunnypilot'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
@@ -23,7 +23,7 @@ jobs:
|
|||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
||||||
with:
|
with:
|
||||||
author: Vehicle Researcher <user@comma.ai>
|
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
|
||||||
commit-message: "Update translations"
|
commit-message: "Update translations"
|
||||||
title: "[bot] Update translations"
|
title: "[bot] Update translations"
|
||||||
body: "Automatic PR from repo-maintenance -> update_translations"
|
body: "Automatic PR from repo-maintenance -> update_translations"
|
||||||
@@ -36,13 +36,14 @@ jobs:
|
|||||||
name: package_updates
|
name: package_updates
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
container:
|
container:
|
||||||
image: ghcr.io/commaai/openpilot-base:latest
|
image: ghcr.io/sunnypilot/sunnypilot-base:latest
|
||||||
if: github.repository == 'sunnypilot/sunnypilot'
|
if: github.repository == 'sunnypilot/sunnypilot'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: uv lock
|
- name: uv lock
|
||||||
|
if: github.repository == 'commaai/openpilot'
|
||||||
run: |
|
run: |
|
||||||
python3 -m ensurepip --upgrade
|
python3 -m ensurepip --upgrade
|
||||||
pip3 install uv
|
pip3 install uv
|
||||||
@@ -50,6 +51,7 @@ jobs:
|
|||||||
- name: bump submodules
|
- name: bump submodules
|
||||||
run: |
|
run: |
|
||||||
git config --global --add safe.directory '*'
|
git config --global --add safe.directory '*'
|
||||||
|
git config submodule.tinygrad.update none
|
||||||
git submodule update --remote
|
git submodule update --remote
|
||||||
git add .
|
git add .
|
||||||
- name: update car docs
|
- name: update car docs
|
||||||
@@ -61,8 +63,8 @@ jobs:
|
|||||||
- name: Create Pull Request
|
- name: Create Pull Request
|
||||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
||||||
with:
|
with:
|
||||||
author: Vehicle Researcher <user@comma.ai>
|
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
|
||||||
token: ${{ secrets.ACTIONS_CREATE_PR_PAT }}
|
token: ${{ github.repository == 'commaai/openpilot' && secrets.ACTIONS_CREATE_PR_PAT || secrets.GITHUB_TOKEN }}
|
||||||
commit-message: Update Python packages
|
commit-message: Update Python packages
|
||||||
title: '[bot] Update Python packages'
|
title: '[bot] Update Python packages'
|
||||||
branch: auto-package-updates
|
branch: auto-package-updates
|
||||||
|
|||||||
@@ -10,9 +10,17 @@ inputs:
|
|||||||
required: false
|
required: false
|
||||||
default: 30
|
default: 30
|
||||||
|
|
||||||
|
outputs:
|
||||||
|
duration:
|
||||||
|
description: 'Duration of the setup process in seconds'
|
||||||
|
value: ${{ steps.get_duration.outputs.duration }}
|
||||||
|
|
||||||
runs:
|
runs:
|
||||||
using: "composite"
|
using: "composite"
|
||||||
steps:
|
steps:
|
||||||
|
- id: start_time
|
||||||
|
shell: bash
|
||||||
|
run: echo "START_TIME=$(date +%s)" >> $GITHUB_ENV
|
||||||
- id: setup1
|
- id: setup1
|
||||||
uses: ./.github/workflows/setup
|
uses: ./.github/workflows/setup
|
||||||
continue-on-error: true
|
continue-on-error: true
|
||||||
@@ -35,3 +43,10 @@ runs:
|
|||||||
uses: ./.github/workflows/setup
|
uses: ./.github/workflows/setup
|
||||||
with:
|
with:
|
||||||
is_retried: true
|
is_retried: true
|
||||||
|
- id: get_duration
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
END_TIME=$(date +%s)
|
||||||
|
DURATION=$((END_TIME - START_TIME))
|
||||||
|
echo "Total duration: $DURATION seconds"
|
||||||
|
echo "duration=$DURATION" >> $GITHUB_OUTPUT
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ on:
|
|||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DAYS_BEFORE_PR_CLOSE: 2
|
DAYS_BEFORE_PR_CLOSE: 7
|
||||||
DAYS_BEFORE_PR_STALE: 9
|
DAYS_BEFORE_PR_STALE: 24
|
||||||
DAYS_BEFORE_PR_STALE_DRAFT: 30
|
DAYS_BEFORE_PR_STALE_DRAFT: 30
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
|||||||
@@ -9,6 +9,27 @@ env:
|
|||||||
MODELS_DIR: ${{ github.workspace }}/selfdrive/modeld/models
|
MODELS_DIR: ${{ github.workspace }}/selfdrive/modeld/models
|
||||||
|
|
||||||
on:
|
on:
|
||||||
|
workflow_call:
|
||||||
|
inputs:
|
||||||
|
upstream_branch:
|
||||||
|
description: 'Upstream branch to build from'
|
||||||
|
required: true
|
||||||
|
default: 'master'
|
||||||
|
type: string
|
||||||
|
custom_name:
|
||||||
|
description: 'Custom name for the model (no date, only name)'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
is_20hz:
|
||||||
|
description: 'Is this a 20Hz model'
|
||||||
|
required: false
|
||||||
|
type: boolean
|
||||||
|
default: true
|
||||||
|
artifact_suffix:
|
||||||
|
description: 'Suffix for artifact name'
|
||||||
|
required: false
|
||||||
|
type: string
|
||||||
|
default: ''
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
upstream_branch:
|
upstream_branch:
|
||||||
@@ -32,34 +53,53 @@ run-name: Build model [${{ inputs.custom_name || inputs.upstream_branch }}] from
|
|||||||
jobs:
|
jobs:
|
||||||
get_model:
|
get_model:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
REF: ${{ inputs.upstream_branch }}
|
||||||
outputs:
|
outputs:
|
||||||
model_date: ${{ steps.commit-date.outputs.model_date }}
|
model_date: ${{ steps.commit-date.outputs.model_date }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
# Note: To allow dynamic models from both openpilot and sunnypilot (merges/mashups), we try commaai as default,
|
||||||
|
# and fallback to sunnypilot if the ref checkout fails.
|
||||||
|
- name: Checkout commaai/openpilot
|
||||||
|
id: checkout_upstream
|
||||||
|
continue-on-error: true
|
||||||
|
uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
repository: ${{ env.UPSTREAM_REPO }}
|
repository: commaai/openpilot
|
||||||
ref: ${{ github.event.inputs.upstream_branch }}
|
ref: ${{ inputs.upstream_branch }}
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
|
path: openpilot
|
||||||
|
|
||||||
|
- name: Fallback to sunnypilot/sunnypilot
|
||||||
|
if: steps.checkout_upstream.outcome == 'failure'
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
repository: sunnypilot/sunnypilot
|
||||||
|
ref: ${{ inputs.upstream_branch }}
|
||||||
|
submodules: recursive
|
||||||
|
path: openpilot
|
||||||
- name: Get commit date
|
- name: Get commit date
|
||||||
id: commit-date
|
id: commit-date
|
||||||
run: |
|
run: |
|
||||||
# Get the commit date in YYYY-MM-DD format
|
cd ${{ github.workspace }}/openpilot
|
||||||
commit_date=$(git log -1 --format=%cd --date=format:'%B %d, %Y')
|
commit_date=$(git log -1 --format=%cd --date=format:'%B %d, %Y')
|
||||||
echo "model_date=${commit_date}" >> $GITHUB_OUTPUT
|
echo "model_date=${commit_date}" >> $GITHUB_OUTPUT
|
||||||
cat $GITHUB_OUTPUT
|
cat $GITHUB_OUTPUT
|
||||||
- run: git lfs pull
|
- run: |
|
||||||
|
cd ${{ github.workspace }}/openpilot
|
||||||
|
git lfs pull
|
||||||
- name: 'Upload Artifact'
|
- name: 'Upload Artifact'
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: models
|
name: models-${{ env.REF }}${{ inputs.artifact_suffix }}
|
||||||
path: ${{ github.workspace }}/selfdrive/modeld/models/*.onnx
|
path: ${{ github.workspace }}/openpilot/selfdrive/modeld/models/*.onnx
|
||||||
|
|
||||||
build_model:
|
build_model:
|
||||||
runs-on: self-hosted
|
runs-on: [self-hosted, tici]
|
||||||
needs: get_model
|
needs: get_model
|
||||||
env:
|
env:
|
||||||
MODEL_NAME: ${{ inputs.custom_name || inputs.upstream_branch }} (${{ needs.get_model.outputs.model_date }})
|
MODEL_NAME: ${{ inputs.custom_name || inputs.upstream_branch }} (${{ needs.get_model.outputs.model_date }})
|
||||||
|
REF: ${{ inputs.upstream_branch }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -71,7 +111,7 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
path: ${{env.SCONS_CACHE_DIR}}
|
path: ${{env.SCONS_CACHE_DIR}}
|
||||||
key: scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}-model-${{ github.sha }}
|
key: scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}-model-${{ github.sha }}
|
||||||
# Note: GitHub Actions enforces cache isolation between different build sources (PR builds, workflow dispatches, etc.)
|
# Note: GitHub Actions enforces cache isolation between different build sources (PR builds, workflow dispatches, etc.)
|
||||||
# for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden.
|
# for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden.
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}-model
|
scons-${{ runner.os }}-${{ runner.arch }}-${{ github.head_ref || github.ref_name }}-model
|
||||||
@@ -114,8 +154,10 @@ jobs:
|
|||||||
- name: Download model artifacts
|
- name: Download model artifacts
|
||||||
uses: actions/download-artifact@v4
|
uses: actions/download-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: models
|
name: models-${{ env.REF }}${{ inputs.artifact_suffix }}
|
||||||
path: ${{ github.workspace }}/selfdrive/modeld/models
|
path: ${{ github.workspace }}/selfdrive/modeld/models
|
||||||
|
- run: |
|
||||||
|
rm -f ${{ github.workspace }}/selfdrive/modeld/models/{dmonitoring_model,big_driving_policy,big_driving_vision}.onnx
|
||||||
|
|
||||||
- name: Build Model
|
- name: Build Model
|
||||||
run: |
|
run: |
|
||||||
@@ -157,12 +199,22 @@ jobs:
|
|||||||
--upstream-branch "${{ inputs.upstream_branch }}" \
|
--upstream-branch "${{ inputs.upstream_branch }}" \
|
||||||
${{ inputs.is_20hz && '--is-20hz' || '' }}
|
${{ inputs.is_20hz && '--is-20hz' || '' }}
|
||||||
|
|
||||||
|
- name: Write artifact name to file
|
||||||
|
run: echo "model-${{ env.MODEL_NAME }}${{ inputs.artifact_suffix }}-${{ github.run_number }}" > ${{ env.OUTPUT_DIR }}/artifact_name.txt
|
||||||
|
|
||||||
- name: Upload Build Artifacts
|
- name: Upload Build Artifacts
|
||||||
|
id: upload-artifact
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: model-${{ env.MODEL_NAME }}-${{ github.run_number }}
|
name: model-${{ env.MODEL_NAME }}${{ inputs.artifact_suffix }}-${{ github.run_number }}
|
||||||
path: ${{ env.OUTPUT_DIR }}
|
path: ${{ env.OUTPUT_DIR }}
|
||||||
|
|
||||||
|
- name: Upload artifact name file
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: artifact-name-${{ inputs.custom_name || inputs.upstream_branch }}
|
||||||
|
path: ${{ env.OUTPUT_DIR }}/artifact_name.txt
|
||||||
|
|
||||||
- name: Re-enable powersave
|
- name: Re-enable powersave
|
||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
@@ -8,55 +8,119 @@ env:
|
|||||||
PUBLIC_REPO_URL: "https://github.com/sunnypilot/sunnypilot"
|
PUBLIC_REPO_URL: "https://github.com/sunnypilot/sunnypilot"
|
||||||
|
|
||||||
# Branch configurations
|
# Branch configurations
|
||||||
STAGING_C3_SOURCE_BRANCH: ${{ vars.STAGING_C3_SOURCE_BRANCH || 'master-new' }} # vars are set on repo settings.
|
STAGING_SOURCE_BRANCH: 'master'
|
||||||
DEV_C3_SOURCE_BRANCH: ${{ vars.DEV_C3_SOURCE_BRANCH || 'master-dev-c3-new' }} # vars are set on repo settings.
|
|
||||||
|
|
||||||
# Target branch configurations
|
|
||||||
STAGING_TARGET_BRANCH: ${{ vars.STAGING_TARGET_BRANCH || 'staging-c3-new' }} # vars are set on repo settings.
|
|
||||||
DEV_TARGET_BRANCH: ${{ vars.DEV_TARGET_BRANCH || 'dev-c3-new' }} # vars are set on repo settings.
|
|
||||||
RELEASE_TARGET_BRANCH: ${{ vars.RELEASE_TARGET_BRANCH || 'release-c3-new' }} # vars are set on repo settings.
|
|
||||||
|
|
||||||
# Runtime configuration
|
# Runtime configuration
|
||||||
SOURCE_BRANCH: "${{ github.head_ref || github.ref_name }}"
|
SOURCE_BRANCH: "${{ github.head_ref || github.ref_name }}"
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: [ master, master-new, master-dev-c3-new ]
|
branches: [ master, master-dev ]
|
||||||
tags: [ '*' ]
|
tags: [ 'release/*' ]
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [ labeled ]
|
types: [ labeled ]
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
wait_for_tests:
|
wait_for_tests:
|
||||||
description: 'Wait for selfdrive_tests to finish'
|
description: 'Wait for tests to finish'
|
||||||
required: false
|
required: false
|
||||||
type: boolean
|
type: boolean
|
||||||
default: false
|
default: false
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
|
prepare_strategy:
|
||||||
|
runs-on: ubuntu-24.04
|
||||||
|
if: (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||||||
|
outputs:
|
||||||
|
environment: ${{ steps.strategy.outputs.environment }}
|
||||||
|
new_branch: ${{ steps.strategy.outputs.new_branch }}
|
||||||
|
extra_version_identifier: ${{ steps.strategy.outputs.extra_version_identifier }}
|
||||||
|
version: ${{ steps.strategy.outputs.version }}
|
||||||
|
cancel_publish_in_progress: ${{ steps.strategy.outputs.cancel_publish_in_progress }}
|
||||||
|
publish_concurrency_group: ${{ steps.strategy.outputs.publish_concurrency_group }}
|
||||||
|
is_stable_branch: ${{ steps.strategy.outputs.is_stable_branch }}
|
||||||
|
build: ${{ steps.strategy.outputs.build }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Extract deploy strategy
|
||||||
|
id: strategy
|
||||||
|
run: |
|
||||||
|
echo '::group::Strategy Extraction'
|
||||||
|
BRANCH="${{ github.head_ref || github.ref_name }}"
|
||||||
|
echo "Current branch: $BRANCH"
|
||||||
|
|
||||||
|
STRATEGY_JSON='${{ vars.DEPLOY_STRATEGY }}'
|
||||||
|
CONFIG=$(echo "$STRATEGY_JSON" | jq -r --arg branch "$BRANCH" '
|
||||||
|
.configs[] | select(.branch == $branch)
|
||||||
|
')
|
||||||
|
|
||||||
|
BUILD="$(date '+%Y.%m.%d')-${{ github.run_number }}"
|
||||||
|
if [[ -z "$CONFIG" || "$CONFIG" == "null" ]]; then
|
||||||
|
echo "No exact strategy match found. Falling back to feature/fork logic."
|
||||||
|
IS_FORK="${{ github.event.pull_request.head.repo.fork && 'true' || 'false' }}"
|
||||||
|
FORK_SUFFIX=$( [[ "$IS_FORK" == "true" ]] && echo "-fork" || echo "" )
|
||||||
|
NEW_BRANCH="${BRANCH}${FORK_SUFFIX}-prebuilt"
|
||||||
|
|
||||||
|
echo "new_branch=$NEW_BRANCH" >> $GITHUB_OUTPUT
|
||||||
|
echo "version=$BUILD" >> $GITHUB_OUTPUT
|
||||||
|
echo "cancel_publish_in_progress=true" >> $GITHUB_OUTPUT
|
||||||
|
echo "publish_concurrency_group=publish-${BRANCH}" >> $GITHUB_OUTPUT
|
||||||
|
echo "environment=feature-branch" >> $GITHUB_OUTPUT
|
||||||
|
echo "extra_version_identifier=feature-branch" >> $GITHUB_OUTPUT
|
||||||
|
else
|
||||||
|
echo "Matched config: $CONFIG"
|
||||||
|
environment=$(echo "$CONFIG" | jq -r '.environment')
|
||||||
|
echo "environment=$environment" >> $GITHUB_OUTPUT
|
||||||
|
echo "new_branch=$(echo "$CONFIG" | jq -r '.target_branch')" >> $GITHUB_OUTPUT
|
||||||
|
cancel="$(echo "$CONFIG" | jq -r '.cancel_publish_in_progress')";
|
||||||
|
echo "cancel_publish_in_progress=$( [ "$cancel" = "null" ] && echo "true" || echo $cancel)" >> $GITHUB_OUTPUT
|
||||||
|
echo "publish_concurrency_group=publish-${BRANCH}$( [ "$cancel" = "null" ] || [ "$cancel" = "true" ] || echo "${{ github.sha }}" )" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
is_stable_branch="$(echo "$CONFIG" | jq -r '.stable_branch // false')";
|
||||||
|
echo "is_stable_branch=$is_stable_branch" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
stable_version=$(cat sunnypilot/common/version.h | grep SUNNYPILOT_VERSION | sed -e 's/[^0-9|.]//g');
|
||||||
|
echo "version=$([ "$is_stable_branch" = "true" ] && echo "$stable_version" || echo "$BUILD")" >> $GITHUB_OUTPUT
|
||||||
|
echo "extra_version_identifier=${environment}" >> $GITHUB_OUTPUT
|
||||||
|
fi
|
||||||
|
echo "build=$BUILD" >> $GITHUB_OUTPUT
|
||||||
|
cat $GITHUB_OUTPUT
|
||||||
|
|
||||||
validate_tests:
|
validate_tests:
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ((github.event_name == 'workflow_dispatch' && inputs.wait_for_tests) || contains(github.event_name, 'pull_request') && (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
needs: [ prepare_strategy ]
|
||||||
|
if: ${{
|
||||||
|
((github.event_name == 'workflow_dispatch' && inputs.wait_for_tests) ||
|
||||||
|
(github.event_name == 'push' && needs.prepare_strategy.outputs.is_stable_branch == 'true') ||
|
||||||
|
contains(github.event_name, 'pull_request') && (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||||||
|
}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Wait for Tests
|
- name: Wait for Tests
|
||||||
uses: ./.github/workflows/wait-for-action # Path to where you place the action
|
uses: ./.github/workflows/wait-for-action # Path to where you place the action
|
||||||
with:
|
with:
|
||||||
workflow: selfdrive_tests.yaml # The workflow file to monitor
|
workflow: tests.yaml # The workflow file to monitor
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
should-wait-for-start: ${{ github.event_name == 'push' && 'true' || 'false' }}
|
||||||
|
|
||||||
build:
|
build:
|
||||||
needs: [ validate_tests ]
|
needs: [ validate_tests, prepare_strategy ]
|
||||||
concurrency:
|
concurrency:
|
||||||
group: build-${{ github.head_ref || github.ref_name }}
|
group: build-${{ github.head_ref || github.ref_name }}
|
||||||
cancel-in-progress: false
|
cancel-in-progress: false
|
||||||
runs-on: self-hosted
|
runs-on: [self-hosted, tici]
|
||||||
outputs:
|
outputs:
|
||||||
new_branch: ${{ steps.set-env.outputs.new_branch }}
|
new_branch: ${{ needs.prepare_strategy.outputs.new_branch }}
|
||||||
version: ${{ steps.set-env.outputs.version }}
|
version: ${{ needs.prepare_strategy.outputs.version }}
|
||||||
extra_version_identifier: ${{ steps.set-env.outputs.extra_version_identifier }}
|
extra_version_identifier: ${{ needs.prepare_strategy.outputs.extra_version_identifier }}
|
||||||
commit_sha: ${{ steps.set-env.outputs.commit_sha }}
|
commit_sha: ${{ github.sha }}
|
||||||
if: ${{ (always() && !failure() && !cancelled()) && (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt')) }}
|
if: ${{
|
||||||
|
(always() && !cancelled() && !failure()) &&
|
||||||
|
needs.prepare_strategy.result == 'success' &&
|
||||||
|
(needs.validate_tests.result == 'success' || needs.validate_tests.result == 'skipped') &&
|
||||||
|
(!contains(github.event_name, 'pull_request') ||
|
||||||
|
(github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||||||
|
}}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -74,64 +138,15 @@ jobs:
|
|||||||
# for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden.
|
# for security. Only caches from the default branch are shared across all builds. This is by design and cannot be overridden.
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.SOURCE_BRANCH }}
|
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.SOURCE_BRANCH }}
|
||||||
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.STAGING_C3_SOURCE_BRANCH }}
|
scons-${{ runner.os }}-${{ runner.arch }}-${{ env.STAGING_SOURCE_BRANCH }}
|
||||||
scons-${{ runner.os }}-${{ runner.arch }}
|
scons-${{ runner.os }}-${{ runner.arch }}
|
||||||
|
|
||||||
- name: Set Feature Branch Prebuilt Configuration
|
|
||||||
id: set_feature_configuration
|
|
||||||
if: (
|
|
||||||
!(env.SOURCE_BRANCH == env.DEV_C3_SOURCE_BRANCH) &&
|
|
||||||
!(env.SOURCE_BRANCH == env.STAGING_C3_SOURCE_BRANCH) &&
|
|
||||||
!(startsWith(github.ref, 'refs/tags/'))
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "NEW_BRANCH=${{ env.SOURCE_BRANCH }}${{ github.event.pull_request.head.repo.fork && '-fork' || '' }}-prebuilt" >> $GITHUB_ENV
|
|
||||||
echo "VERSION=$(date '+%Y.%m.%d')-${{ github.run_number }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set dev-c3-new prebuilt Configuration
|
|
||||||
id: set_dev_configuration
|
|
||||||
if: (
|
|
||||||
steps.set_feature_configuration.outcome == 'skipped' &&
|
|
||||||
env.SOURCE_BRANCH == env.DEV_C3_SOURCE_BRANCH
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "NEW_BRANCH=${{ env.DEV_TARGET_BRANCH }}" >> $GITHUB_ENV
|
|
||||||
echo "VERSION=$(date '+%Y.%m.%d')-${{ github.run_number }}" >> $GITHUB_ENV
|
|
||||||
echo "EXTRA_VERSION_IDENTIFIER=${{ github.run_number }}" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set staging-c3-new prebuilt Configuration
|
|
||||||
id: set_staging_configuration
|
|
||||||
if: (
|
|
||||||
steps.set_feature_configuration.outcome == 'skipped' &&
|
|
||||||
!contains(github.event_name, 'pull_request') &&
|
|
||||||
steps.set_dev_configuration.outcome == 'skipped' &&
|
|
||||||
(env.SOURCE_BRANCH == env.STAGING_C3_SOURCE_BRANCH)
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "NEW_BRANCH=${{ env.STAGING_TARGET_BRANCH }}" >> $GITHUB_ENV
|
|
||||||
echo "EXTRA_VERSION_IDENTIFIER=staging" >> $GITHUB_ENV
|
|
||||||
echo "VERSION=$(cat common/version.h | grep COMMA_VERSION | sed -e 's/[^0-9|.]//g')-staging" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set release-c3-new prebuilt Configuration
|
|
||||||
id: set_tag_configuration
|
|
||||||
if: (
|
|
||||||
steps.set_feature_configuration.outcome == 'skipped' &&
|
|
||||||
!contains(github.event_name, 'pull_request') &&
|
|
||||||
steps.set_staging_configuration.outcome == 'skipped' &&
|
|
||||||
startsWith(github.ref, 'refs/tags/')
|
|
||||||
)
|
|
||||||
run: |
|
|
||||||
echo "NEW_BRANCH=${{ env.RELEASE_TARGET_BRANCH }}" >> $GITHUB_ENV
|
|
||||||
echo "EXTRA_VERSION_IDENTIFIER=release" >> $GITHUB_ENV
|
|
||||||
echo "VERSION=$(cat common/version.h | grep COMMA_VERSION | sed -e 's/[^0-9|.]//g')-release" >> $GITHUB_ENV
|
|
||||||
|
|
||||||
- name: Set environment variables
|
- name: Set environment variables
|
||||||
id: set-env
|
id: set-env
|
||||||
run: |
|
run: |
|
||||||
# Write to GITHUB_OUTPUT from environment variables
|
echo "new_branch=${{ needs.prepare_strategy.outputs.new_branch }}" >> $GITHUB_OUTPUT
|
||||||
echo "new_branch=$NEW_BRANCH" >> $GITHUB_OUTPUT
|
echo "version=${{ needs.prepare_strategy.outputs.version }}" >> $GITHUB_OUTPUT
|
||||||
[[ ! -z "$EXTRA_VERSION_IDENTIFIER" ]] && echo "extra_version_identifier=$EXTRA_VERSION_IDENTIFIER" >> $GITHUB_OUTPUT
|
echo "extra_version_identifier=${{ needs.prepare_strategy.outputs.extra_version_identifier }}" >> $GITHUB_OUTPUT
|
||||||
[[ ! -z "$VERSION" ]] && echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
||||||
echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
|
echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
# Set up common environment
|
# Set up common environment
|
||||||
@@ -226,16 +241,19 @@ jobs:
|
|||||||
if: always()
|
if: always()
|
||||||
run: |
|
run: |
|
||||||
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable
|
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable
|
||||||
|
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
concurrency:
|
concurrency:
|
||||||
group: publish-${{ github.head_ref || github.ref_name }}
|
# We do a bit of a hack here to avoid canceling the publishing job if a new commit comes in while we're publishing by adding the sha to the group name.
|
||||||
cancel-in-progress: true
|
# This means that if multiple commits come in while we're publishing, they will be queued up and publish one after the other.
|
||||||
if: ${{ (always() && !failure() && !cancelled()) && (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt')) }}
|
# Otherwise, if a job is waiting to be published due to environment wait time, it would be canceled by a new commit and restart the wait time.
|
||||||
needs: [ build ]
|
group: ${{ needs.prepare_strategy.outputs.publish_concurrency_group }}
|
||||||
|
cancel-in-progress: ${{ needs.prepare_strategy.outputs.cancel_publish_in_progress == 'true' }}
|
||||||
|
if: ${{ (always() && !cancelled() && !failure()) && needs.build.result == 'success' && needs.prepare_strategy.result == 'success' && (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt')) }}
|
||||||
|
needs: [ build, prepare_strategy ]
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
environment: ${{ (contains(fromJSON(vars.AUTO_DEPLOY_PREBUILT_BRANCHES), github.head_ref || github.ref_name) || contains(github.event.pull_request.labels.*.name, 'prebuilt')) && 'auto-deploy' || 'feature-branch' }}
|
environment: ${{ needs.prepare_strategy.outputs.environment }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -267,47 +285,69 @@ jobs:
|
|||||||
"${{ needs.build.outputs.new_branch }}" \
|
"${{ needs.build.outputs.new_branch }}" \
|
||||||
"${{ needs.build.outputs.version }}" \
|
"${{ needs.build.outputs.version }}" \
|
||||||
"https://x-access-token:${{github.token}}@github.com/sunnypilot/sunnypilot.git" \
|
"https://x-access-token:${{github.token}}@github.com/sunnypilot/sunnypilot.git" \
|
||||||
"-${{ needs.build.outputs.extra_version_identifier }}"
|
"${{ needs.build.outputs.extra_version_identifier }}"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo "---- ℹ️ To update the list of branches that auto deploy prebuilts -----"
|
echo "---- ℹ️ To update the list of branches that auto deploy prebuilts -----"
|
||||||
echo ""
|
echo ""
|
||||||
echo "1. Go to: ${{ github.server_url }}/${{ github.repository }}/settings/variables/actions/AUTO_DEPLOY_PREBUILT_BRANCHES"
|
echo "1. Go to: ${{ github.server_url }}/${{ github.repository }}/settings/variables/actions/AUTO_DEPLOY_PREBUILT_BRANCHES"
|
||||||
echo "2. Current value: ${{ vars.AUTO_DEPLOY_PREBUILT_BRANCHES }}"
|
echo "2. Current value: ${{ vars.AUTO_DEPLOY_PREBUILT_BRANCHES }}"
|
||||||
echo "3. Update as needed (JSON array with no spaces)"
|
echo "3. Update as needed (JSON array with no spaces)"
|
||||||
|
|
||||||
|
- name: Tag ${{ needs.prepare_strategy.outputs.environment }}
|
||||||
|
if: ${{ needs.prepare_strategy.outputs.is_stable_branch == 'true' && (github.event_name != 'push' || !startsWith(github.ref, 'refs/tags/')) }}
|
||||||
|
run: |
|
||||||
|
TAG="${{ needs.prepare_strategy.outputs.environment }}/${{ needs.prepare_strategy.outputs.version }}/${{ needs.prepare_strategy.outputs.build }}"
|
||||||
|
git tag -f -a ${TAG} -m "${{ needs.prepare_strategy.outputs.environment }} @ ${{ needs.prepare_strategy.outputs.version }} of build ${{ needs.build.outputs.build }}."
|
||||||
|
git push -f origin ${TAG}
|
||||||
|
|
||||||
notify:
|
notify:
|
||||||
needs: [ build, publish ]
|
needs:
|
||||||
|
- prepare_strategy
|
||||||
|
- build
|
||||||
|
- publish
|
||||||
runs-on: ubuntu-24.04
|
runs-on: ubuntu-24.04
|
||||||
if: ${{ (always() && !failure() && !cancelled()) && (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt')) }}
|
if: ${{ (always() && !cancelled() && !failure())
|
||||||
|
&& needs.publish.result == 'success'
|
||||||
|
&& (!contains(github.event_name, 'pull_request') || (github.event.action == 'labeled' && github.event.label.name == 'prebuilt'))
|
||||||
|
&& (fromJSON(vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES_V2)[github.head_ref || github.ref_name] != null) }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Setup Alpine Linux environment
|
|
||||||
uses: jirutka/setup-alpine@v1.2.0
|
|
||||||
with:
|
|
||||||
packages: 'jq gettext curl'
|
|
||||||
|
|
||||||
- name: Send Discord Notification
|
- name: Prepare notification message
|
||||||
env:
|
id: message
|
||||||
DISCORD_WEBHOOK: ${{ contains(fromJSON(vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES), env.SOURCE_BRANCH) && secrets.DISCORD_DEV_FEEDBACK_CHANNEL_WEBHOOK || secrets.DISCORD_DEV_PRIVATE_CHANNEL_WEBHOOK }}
|
|
||||||
run: |
|
run: |
|
||||||
TEMPLATE='${{ vars.DISCORD_GENERAL_UPDATE_NOTICE }}'
|
TEMPLATE='${{ vars.DISCOURSE_GENERAL_UPDATE_NOTICE }}'
|
||||||
export EXTRA_VERSION_IDENTIFIER="${{ needs.build.outputs.extra_version_identifier }}"
|
export VERSION="${{ needs.prepare_strategy.outputs.version }}"
|
||||||
export VERSION="${{ needs.build.outputs.version }}"
|
export branch_name="${{ env.SOURCE_BRANCH }}"
|
||||||
export branch_name=${{ env.SOURCE_BRANCH }}
|
export new_branch="${{ needs.prepare_strategy.outputs.new_branch }}"
|
||||||
export new_branch=${{ needs.build.outputs.new_branch }}
|
export commit_sha="${{ github.sha }}"
|
||||||
export extra_version_identifier=${{ needs.build.outputs.extra_version_identifier || github.run_number}}
|
export commit_short_sha="${{ github.sha }}"
|
||||||
echo ${TEMPLATE} | envsubst | jq -c '.' | tee payload.json
|
export commit_short_sha="${commit_short_sha:0:7}"
|
||||||
curl -X POST -H "Content-Type: application/json" -d @payload.json $DISCORD_WEBHOOK
|
export extra_version_identifier="${{ needs.prepare_strategy.outputs.extra_version_identifier || github.run_number }}"
|
||||||
|
export PUBLIC_REPO_URL="${{ env.PUBLIC_REPO_URL }}"
|
||||||
|
|
||||||
|
MESSAGE=$(cat << 'EOF' | envsubst
|
||||||
|
${{ vars.DISCOURSE_GENERAL_UPDATE_NOTICE }}
|
||||||
|
EOF
|
||||||
|
)
|
||||||
|
|
||||||
echo ""
|
{
|
||||||
echo "---- ℹ️ To update the list of branches that notify to dev-feedback -----"
|
echo 'content<<EOFMARKER'
|
||||||
echo ""
|
echo "$MESSAGE"
|
||||||
echo "1. Go to: ${{ github.server_url }}/${{ github.repository }}/settings/variables/actions/DEV_FEEDBACK_NOTIFICATION_BRANCHES"
|
echo 'EOFMARKER'
|
||||||
echo "2. Current value: ${{ vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES }}"
|
} >> $GITHUB_OUTPUT
|
||||||
echo "3. Update as needed (JSON array with no spaces)"
|
shell: bash
|
||||||
shell: alpine.sh {0}
|
|
||||||
|
- name: Post to Discourse
|
||||||
|
uses: ./.github/workflows/post-to-discourse
|
||||||
|
with:
|
||||||
|
discourse-url: ${{ vars.DISCOURSE_URL }}
|
||||||
|
api-key: ${{ secrets.DISCOURSE_API_KEY }}
|
||||||
|
api-username: "system"
|
||||||
|
topic-id: ${{ fromJSON(vars.DEV_FEEDBACK_NOTIFICATION_BRANCHES_V2)[github.head_ref || github.ref_name].topic_id }}
|
||||||
|
message: ${{ steps.message.outputs.content }}
|
||||||
|
|
||||||
manage-pr-labels:
|
manage-pr-labels:
|
||||||
name: Remove prebuilt label
|
name: Remove prebuilt label
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|||||||
+22
-24
@@ -1,9 +1,8 @@
|
|||||||
name: Build dev-c3-new
|
name: Build dev
|
||||||
|
|
||||||
env:
|
env:
|
||||||
DEFAULT_SOURCE_BRANCH: "master-new"
|
DEFAULT_SOURCE_BRANCH: "master"
|
||||||
DEFAULT_TARGET_BRANCH: "master-dev-c3-new"
|
DEFAULT_TARGET_BRANCH: "master-dev"
|
||||||
PR_LABEL: "dev-c3"
|
|
||||||
LFS_URL: 'https://gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git/info/lfs'
|
LFS_URL: 'https://gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git/info/lfs'
|
||||||
LFS_PUSH_URL: 'ssh://git@gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git'
|
LFS_PUSH_URL: 'ssh://git@gitlab.com/sunnypilot/public/sunnypilot-new-lfs.git'
|
||||||
|
|
||||||
@@ -11,23 +10,21 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- master-new
|
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [ labeled ]
|
types: [ labeled ]
|
||||||
branches:
|
branches:
|
||||||
- 'master'
|
- 'master'
|
||||||
- 'master-new'
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
inputs:
|
inputs:
|
||||||
source_branch:
|
source_branch:
|
||||||
description: 'Source branch to reset from'
|
description: 'Source branch to reset from'
|
||||||
required: true
|
required: true
|
||||||
default: 'master-new'
|
default: 'master'
|
||||||
type: string
|
type: string
|
||||||
target_branch:
|
target_branch:
|
||||||
description: 'Target branch to reset and squash into'
|
description: 'Target branch to reset and squash into'
|
||||||
required: true
|
required: true
|
||||||
default: 'master-dev-c3-new'
|
default: 'master-dev'
|
||||||
type: string
|
type: string
|
||||||
cancel_in_progress:
|
cancel_in_progress:
|
||||||
description: 'Cancel any in-progress runs of this workflow'
|
description: 'Cancel any in-progress runs of this workflow'
|
||||||
@@ -43,10 +40,10 @@ jobs:
|
|||||||
reset-and-squash:
|
reset-and-squash:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
if: (
|
if: (
|
||||||
(github.event_name == 'workflow_dispatch')
|
(github.event_name == 'workflow_dispatch')
|
||||||
|| (github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch))
|
|| (github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch))
|
||||||
|| (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev-c3' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev-c3'))))
|
|| (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == vars.PREBUILT_PR_LABEL || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, vars.PREBUILT_PR_LABEL))))
|
||||||
)
|
)
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
@@ -56,11 +53,11 @@ jobs:
|
|||||||
- name: Wait for Tests
|
- name: Wait for Tests
|
||||||
uses: ./.github/workflows/wait-for-action # Path to where you place the action
|
uses: ./.github/workflows/wait-for-action # Path to where you place the action
|
||||||
if: (
|
if: (
|
||||||
(github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch))
|
(github.event_name == 'push' && github.ref == format('refs/heads/{0}', github.event.repository.default_branch))
|
||||||
|| (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == 'dev-c3' || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, 'dev-c3'))))
|
|| (contains(github.event_name, 'pull_request') && ((github.event.action == 'labeled' && (github.event.label.name == vars.PREBUILT_PR_LABEL || github.event.label.name == 'trust-fork-pr') && contains(github.event.pull_request.labels.*.name, vars.PREBUILT_PR_LABEL))))
|
||||||
)
|
)
|
||||||
with:
|
with:
|
||||||
workflow: selfdrive_tests.yaml # The workflow file to monitor
|
workflow: tests.yaml # The workflow file to monitor
|
||||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
- name: Configure Git
|
- name: Configure Git
|
||||||
@@ -120,8 +117,8 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
# Use GitHub API to get PRs with specific label, ordered by creation date
|
# Use GitHub API to get PRs with specific label, ordered by creation date
|
||||||
PR_LIST=$(gh api graphql -f query='
|
PR_LIST=$(gh api graphql -f query='
|
||||||
query($label:String!) {
|
query($search_query:String!) {
|
||||||
search(query: $label, type:ISSUE, first:100) {
|
search(query: $search_query, type:ISSUE, first:40) {
|
||||||
nodes {
|
nodes {
|
||||||
... on PullRequest {
|
... on PullRequest {
|
||||||
number
|
number
|
||||||
@@ -151,8 +148,9 @@ jobs:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}' -F label="is:pr is:open label:${PR_LABEL} draft:false sort:created-asc")
|
}' -F search_query="repo:${{ github.repository }} is:pr is:open label:${{ vars.PREBUILT_PR_LABEL }},${{ vars.PREBUILT_PR_LABEL }}-c3 draft:false sort:created-asc")
|
||||||
|
|
||||||
|
PR_LIST=${PR_LIST//\'/}
|
||||||
echo "PR_LIST=${PR_LIST}" >> $GITHUB_OUTPUT
|
echo "PR_LIST=${PR_LIST}" >> $GITHUB_OUTPUT
|
||||||
env:
|
env:
|
||||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
@@ -203,13 +201,13 @@ jobs:
|
|||||||
if: steps.push-changes.outputs.has_changes == 'true'
|
if: steps.push-changes.outputs.has_changes == 'true'
|
||||||
run: |
|
run: |
|
||||||
echo "Triggering selfdrive tests..."
|
echo "Triggering selfdrive tests..."
|
||||||
gh workflow run selfdrive_tests.yaml --ref "${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}"
|
gh workflow run tests.yaml --ref "${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}"
|
||||||
|
|
||||||
echo "Sleeping for 120s to give plenty of time for the action to start and then we wait"
|
echo "Sleeping for 120s to give plenty of time for the action to start and then we wait"
|
||||||
sleep 120
|
sleep 120
|
||||||
|
|
||||||
echo "Getting latest run ID..."
|
echo "Getting latest run ID..."
|
||||||
RUN_ID=$(gh run list --workflow=selfdrive_tests.yaml --branch="${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}" --limit=1 --json databaseId --jq '.[0].databaseId')
|
RUN_ID=$(gh run list --workflow=tests.yaml --branch="${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}" --limit=1 --json databaseId --jq '.[0].databaseId')
|
||||||
|
|
||||||
echo "Watching run ID: $RUN_ID"
|
echo "Watching run ID: $RUN_ID"
|
||||||
gh run watch "$RUN_ID"
|
gh run watch "$RUN_ID"
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
name: Debug Discourse Posting
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test-discourse-post:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Post test message to Discourse
|
||||||
|
uses: ./.github/workflows/post-to-discourse
|
||||||
|
with:
|
||||||
|
discourse-url: ${{ vars.DISCOURSE_URL }}
|
||||||
|
api-key: ${{ secrets.DISCOURSE_API_KEY }}
|
||||||
|
api-username: ${{ secrets.DISCOURSE_API_USERNAME }}
|
||||||
|
topic-id: ${{ vars.DISCOURSE_UPDATES_TOPIC_ID }}
|
||||||
|
message: |
|
||||||
|
## 🧪 Test Post from GitHub Actions
|
||||||
|
|
||||||
|
**This is a test post to verify Discourse integration**
|
||||||
|
|
||||||
|
- **Workflow**: ${{ github.workflow }}
|
||||||
|
- **Run Number**: #${{ github.run_number }}
|
||||||
|
- **Branch**: `${{ github.ref_name }}`
|
||||||
|
- **Commit**: ${{ github.sha }}
|
||||||
|
- **Actor**: @${{ github.actor }}
|
||||||
|
- **Timestamp**: ${{ github.event.head_commit.timestamp }}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Fake Build Info (for testing)
|
||||||
|
- **Version**: 0.9.8-test
|
||||||
|
- **Build**: #42
|
||||||
|
- **Branch**: release-test
|
||||||
|
|
||||||
|
[View workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
||||||
|
|
||||||
|
*This is an automated test message. Drive safe! 🚗💨*
|
||||||
|
|
||||||
|
|
||||||
|
- name: Create topic on Discourse
|
||||||
|
uses: ./.github/workflows/post-to-discourse
|
||||||
|
with:
|
||||||
|
discourse-url: ${{ vars.DISCOURSE_URL }}
|
||||||
|
api-key: ${{ secrets.DISCOURSE_API_KEY }}
|
||||||
|
api-username: ${{ secrets.DISCOURSE_API_USERNAME }}
|
||||||
|
#topic-id: ${{ vars.DISCOURSE_UPDATES_TOPIC_ID }}
|
||||||
|
category-id: 4
|
||||||
|
title: "This is a test of a new topic instead of a reply"
|
||||||
|
message: |
|
||||||
|
## 🧪 Test Post from GitHub Actions
|
||||||
|
|
||||||
|
**This is a test post to verify Discourse integration**
|
||||||
|
|
||||||
|
- **Workflow**: ${{ github.workflow }}
|
||||||
|
- **Run Number**: #${{ github.run_number }}
|
||||||
|
- **Branch**: `${{ github.ref_name }}`
|
||||||
|
- **Commit**: ${{ github.sha }}
|
||||||
|
- **Actor**: @${{ github.actor }}
|
||||||
|
- **Timestamp**: ${{ github.event.head_commit.timestamp }}
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Fake Build Info (for testing)
|
||||||
|
- **Version**: 0.9.8-test
|
||||||
|
- **Build**: #42
|
||||||
|
- **Branch**: release-test
|
||||||
|
|
||||||
|
[View workflow run](${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }})
|
||||||
|
|
||||||
|
*This is an automated test message. Drive safe! 🚗💨*
|
||||||
|
- name: Display results
|
||||||
|
if: always()
|
||||||
|
run: |
|
||||||
|
echo "::notice::Discourse post test completed"
|
||||||
|
echo "Check your Discourse topic to verify the post appeared correctly"
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
name: selfdrive
|
name: tests
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- master
|
- master
|
||||||
- master-new
|
|
||||||
pull_request:
|
pull_request:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
workflow_call:
|
workflow_call:
|
||||||
@@ -15,28 +14,31 @@ on:
|
|||||||
type: string
|
type: string
|
||||||
|
|
||||||
concurrency:
|
concurrency:
|
||||||
group: selfdrive-tests-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
group: tests-ci-run-${{ inputs.run_number }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
||||||
cancel-in-progress: true
|
cancel-in-progress: true
|
||||||
|
|
||||||
env:
|
env:
|
||||||
REPORT_NAME: report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new') && 'master' || github.event.number }}
|
|
||||||
PYTHONWARNINGS: error
|
PYTHONWARNINGS: error
|
||||||
BASE_IMAGE: openpilot-base
|
BASE_IMAGE: sunnypilot-base
|
||||||
AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }}
|
AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }}
|
||||||
|
MAPBOX_TOKEN_CI: ${{ secrets.MAPBOX_TOKEN_CI }}
|
||||||
|
|
||||||
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
|
||||||
BUILD: selfdrive/test/docker_build.sh base
|
BUILD: release/ci/docker_build_sp.sh base
|
||||||
|
|
||||||
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -e MAPBOX_TOKEN_CI=$MAPBOX_TOKEN_CI -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
|
||||||
|
|
||||||
PYTEST: pytest --continue-on-collection-errors --durations=0 --durations-min=5 -n logical
|
PYTEST: pytest --continue-on-collection-errors --durations=0 -n logical
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build_release:
|
build_release:
|
||||||
if: github.repository == 'commaai/openpilot' # build_release blocked for the time being to only comma as we may have a different process.
|
|
||||||
name: build release
|
name: build release
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-24.04'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
env:
|
env:
|
||||||
STRIPPED_DIR: /tmp/releasepilot
|
STRIPPED_DIR: /tmp/releasepilot
|
||||||
steps:
|
steps:
|
||||||
@@ -51,7 +53,7 @@ jobs:
|
|||||||
command: git lfs pull
|
command: git lfs pull
|
||||||
- name: Build devel
|
- name: Build devel
|
||||||
timeout-minutes: 1
|
timeout-minutes: 1
|
||||||
run: TARGET_DIR=$STRIPPED_DIR release/build_devel.sh
|
run: TARGET_DIR=$STRIPPED_DIR release/build_stripped.sh
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
- name: Build openpilot and run checks
|
- name: Build openpilot and run checks
|
||||||
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
|
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
|
||||||
@@ -66,17 +68,37 @@ jobs:
|
|||||||
- name: Check submodules
|
- name: Check submodules
|
||||||
if: github.repository == 'sunnypilot/sunnypilot'
|
if: github.repository == 'sunnypilot/sunnypilot'
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
run: release/check-submodules.sh
|
run: |
|
||||||
|
if [ "${{ github.ref }}" != "refs/heads/master" ]; then
|
||||||
|
git fetch origin master:refs/remotes/origin/master
|
||||||
|
|
||||||
|
SUBMODULE_PATHS=$(git diff origin/master HEAD --name-only | grep -E '^[^/]+$' | while read path; do
|
||||||
|
if git ls-files --stage "$path" | grep -q "^160000"; then
|
||||||
|
echo "$path"
|
||||||
|
fi
|
||||||
|
done | tr '\n' ' ')
|
||||||
|
|
||||||
|
if [ -n "$SUBMODULE_PATHS" ]; then
|
||||||
|
echo "Changed submodule paths: $SUBMODULE_PATHS"
|
||||||
|
export SUBMODULE_PATHS="$SUBMODULE_PATHS"
|
||||||
|
export CHECK_PR_REFS=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
release/check-submodules.sh
|
||||||
|
|
||||||
build:
|
build:
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-24.04'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- name: Setup docker push
|
- name: Setup docker push
|
||||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'sunnypilot/sunnypilot'
|
||||||
run: |
|
run: |
|
||||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||||
$DOCKER_LOGIN
|
$DOCKER_LOGIN
|
||||||
@@ -94,7 +116,9 @@ jobs:
|
|||||||
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
|
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
|
||||||
- name: Homebrew cache
|
- name: Homebrew cache
|
||||||
uses: ./.github/workflows/auto-cache
|
uses: ./.github/workflows/auto-cache
|
||||||
|
if: false # disabling the cache for now because it is breaking macos builds...
|
||||||
with:
|
with:
|
||||||
|
save: false # No need save here if we manually save it later conditionally
|
||||||
path: ~/Library/Caches/Homebrew
|
path: ~/Library/Caches/Homebrew
|
||||||
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
@@ -103,11 +127,11 @@ jobs:
|
|||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: ./tools/mac_setup.sh
|
run: ./tools/mac_setup.sh
|
||||||
env:
|
env:
|
||||||
# package install has DeprecationWarnings
|
PYTHONWARNINGS: default # package install has DeprecationWarnings
|
||||||
PYTHONWARNINGS: default
|
HOMEBREW_DISPLAY_INSTALL_TIMES: 1
|
||||||
- name: Save Homebrew cache
|
- name: Save Homebrew cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v4
|
||||||
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new')
|
if: github.ref == 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
path: ~/Library/Caches/Homebrew
|
path: ~/Library/Caches/Homebrew
|
||||||
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||||
@@ -115,6 +139,7 @@ jobs:
|
|||||||
- name: Getting scons cache
|
- name: Getting scons cache
|
||||||
uses: ./.github/workflows/auto-cache
|
uses: ./.github/workflows/auto-cache
|
||||||
with:
|
with:
|
||||||
|
save: false # No need save here if we manually save it later conditionally
|
||||||
path: /tmp/scons_cache
|
path: /tmp/scons_cache
|
||||||
key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||||
restore-keys: |
|
restore-keys: |
|
||||||
@@ -124,15 +149,19 @@ jobs:
|
|||||||
run: . .venv/bin/activate && scons -j$(nproc)
|
run: . .venv/bin/activate && scons -j$(nproc)
|
||||||
- name: Save scons cache
|
- name: Save scons cache
|
||||||
uses: actions/cache/save@v4
|
uses: actions/cache/save@v4
|
||||||
if: (github.ref == 'refs/heads/master' || github.ref == 'refs/heads/master-new')
|
if: github.ref == 'refs/heads/master'
|
||||||
with:
|
with:
|
||||||
path: /tmp/scons_cache
|
path: /tmp/scons_cache
|
||||||
key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
key: scons-${{ runner.arch }}-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||||
|
|
||||||
static_analysis:
|
static_analysis:
|
||||||
name: static analysis
|
name: static analysis
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-latest'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
env:
|
env:
|
||||||
PYTHONWARNINGS: default
|
PYTHONWARNINGS: default
|
||||||
steps:
|
steps:
|
||||||
@@ -146,34 +175,44 @@ jobs:
|
|||||||
|
|
||||||
unit_tests:
|
unit_tests:
|
||||||
name: unit tests
|
name: unit tests
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-24.04'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
|
id: setup-step
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||||
- name: Run unit tests
|
- name: Run unit tests
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && 1 || 20 }}
|
timeout-minutes: ${{ contains(runner.name, 'nsc') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 999 }}
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "$PYTEST --collect-only -m 'not slow' &> /dev/null && \
|
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
||||||
|
# Pre-compile Python bytecode so each pytest worker doesn't need to
|
||||||
|
$PYTEST --collect-only -m 'not slow' -qq && \
|
||||||
MAX_EXAMPLES=1 $PYTEST -m 'not slow' && \
|
MAX_EXAMPLES=1 $PYTEST -m 'not slow' && \
|
||||||
./selfdrive/ui/tests/create_test_translations.sh && \
|
|
||||||
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
chmod -R 777 /tmp/comma_download_cache"
|
||||||
|
|
||||||
process_replay:
|
process_replay:
|
||||||
name: process replay
|
name: process replay
|
||||||
if: github.repository == 'commaai/openpilot' # disable process_replay for forks
|
if: false # disable process_replay for forks
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-24.04'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
|
id: setup-step
|
||||||
- name: Cache test routes
|
- name: Cache test routes
|
||||||
id: dependency-cache
|
id: dependency-cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
@@ -184,7 +223,7 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
${{ env.RUN }} "scons -j$(nproc)"
|
||||||
- name: Run replay
|
- name: Run replay
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && 1 || 20 }}
|
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
|
${{ env.RUN }} "selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
chmod -R 777 /tmp/comma_download_cache"
|
||||||
@@ -209,138 +248,53 @@ jobs:
|
|||||||
${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \
|
${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
chmod -R 777 /tmp/comma_download_cache"
|
||||||
|
|
||||||
test_cars:
|
|
||||||
name: cars
|
|
||||||
runs-on:
|
|
||||||
- 'ubuntu-24.04'
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
job: [0, 1, 2, 3]
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Cache test routes
|
|
||||||
id: routes-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: .ci_cache/comma_download_cache
|
|
||||||
key: car_models-${{ hashFiles('selfdrive/car/tests/test_models.py', 'opendbc/car/tests/routes.py') }}-${{ matrix.job }}
|
|
||||||
- name: Build openpilot
|
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
- name: Test car models
|
|
||||||
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.routes-cache.outputs.cache-hit == 'true') && 1 || 6 }}
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "MAX_EXAMPLES=1 $PYTEST selfdrive/car/tests/test_models.py && \
|
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
|
||||||
env:
|
|
||||||
NUM_JOBS: 4
|
|
||||||
JOB_ID: ${{ matrix.job }}
|
|
||||||
|
|
||||||
car_docs_diff:
|
|
||||||
name: PR comments
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
#if: github.event_name == 'pull_request'
|
|
||||||
if: false # TODO: run this in opendbc?
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
ref: ${{ github.event.pull_request.base.ref }}
|
|
||||||
- run: git lfs pull
|
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
|
||||||
- name: Get base car info
|
|
||||||
run: |
|
|
||||||
${{ env.RUN }} "scons -j$(nproc) && python3 selfdrive/debug/dump_car_docs.py --path /tmp/openpilot_cache/base_car_docs"
|
|
||||||
sudo chown -R $USER:$USER ${{ github.workspace }}
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
with:
|
|
||||||
submodules: true
|
|
||||||
path: current
|
|
||||||
- run: cd current && git lfs pull
|
|
||||||
- name: Save car docs diff
|
|
||||||
id: save_diff
|
|
||||||
run: |
|
|
||||||
cd current
|
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
|
||||||
output=$(${{ env.RUN }} "python3 selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_docs")
|
|
||||||
output="${output//$'\n'/'%0A'}"
|
|
||||||
echo "::set-output name=diff::$output"
|
|
||||||
- name: Find comment
|
|
||||||
if: ${{ env.AZURE_TOKEN != '' }}
|
|
||||||
uses: peter-evans/find-comment@3eae4d37986fb5a8592848f6a574fdf654e61f9e
|
|
||||||
id: fc
|
|
||||||
with:
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body-includes: This PR makes changes to
|
|
||||||
- name: Update comment
|
|
||||||
if: ${{ steps.save_diff.outputs.diff != '' && env.AZURE_TOKEN != '' }}
|
|
||||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
|
|
||||||
with:
|
|
||||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
issue-number: ${{ github.event.pull_request.number }}
|
|
||||||
body: "${{ steps.save_diff.outputs.diff }}"
|
|
||||||
edit-mode: replace
|
|
||||||
- name: Delete comment
|
|
||||||
if: ${{ steps.fc.outputs.comment-id != '' && steps.save_diff.outputs.diff == '' && env.AZURE_TOKEN != '' }}
|
|
||||||
uses: actions/github-script@v7
|
|
||||||
with:
|
|
||||||
script: |
|
|
||||||
github.rest.issues.deleteComment({
|
|
||||||
owner: context.repo.owner,
|
|
||||||
repo: context.repo.repo,
|
|
||||||
comment_id: ${{ steps.fc.outputs.comment-id }}
|
|
||||||
})
|
|
||||||
|
|
||||||
simulator_driving:
|
simulator_driving:
|
||||||
name: simulator driving
|
name: simulator driving
|
||||||
runs-on:
|
runs-on: ${{
|
||||||
- 'ubuntu-24.04'
|
(github.repository == 'commaai/openpilot') &&
|
||||||
if: (github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
|
if: false # FIXME: Started to timeout recently
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
|
id: setup-step
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "scons -j$(nproc)"
|
${{ env.RUN }} "scons -j$(nproc)"
|
||||||
- name: Driving test
|
- name: Driving test
|
||||||
timeout-minutes: 1
|
timeout-minutes: ${{ (steps.setup-step.outputs.duration < 18) && 1 || 2 }}
|
||||||
run: |
|
run: |
|
||||||
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
||||||
source selfdrive/test/setup_vsound.sh && \
|
source selfdrive/test/setup_vsound.sh && \
|
||||||
CI=1 pytest -s tools/sim/tests/test_metadrive_bridge.py"
|
CI=1 pytest -s tools/sim/tests/test_metadrive_bridge.py"
|
||||||
|
|
||||||
create_ui_report:
|
create_raylib_ui_report:
|
||||||
# This job name needs to be the same as UI_JOB_NAME in ui_preview.yaml
|
name: Create raylib UI Report
|
||||||
name: Create UI Report
|
runs-on: ${{
|
||||||
runs-on:
|
(github.repository == 'commaai/openpilot') &&
|
||||||
- 'ubuntu-24.04'
|
((github.event_name != 'pull_request') ||
|
||||||
|
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
|
||||||
|
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|
||||||
|
|| fromJSON('["ubuntu-24.04"]') }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
submodules: true
|
submodules: true
|
||||||
- uses: ./.github/workflows/setup-with-retry
|
- uses: ./.github/workflows/setup-with-retry
|
||||||
- name: caching frames
|
|
||||||
id: frames-cache
|
|
||||||
uses: actions/cache@v4
|
|
||||||
with:
|
|
||||||
path: .ci_cache/comma_download_cache
|
|
||||||
key: ui_screenshots_test_${{ hashFiles('selfdrive/ui/tests/test_ui/run.py') }}
|
|
||||||
- name: Build openpilot
|
- name: Build openpilot
|
||||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||||
- name: Create Test Report
|
- name: Create raylib UI Report
|
||||||
timeout-minutes: ${{ ((steps.frames-cache.outputs.cache-hit == 'true') && 2 || 4) }}
|
|
||||||
run: >
|
run: >
|
||||||
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
|
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
|
||||||
source selfdrive/test/setup_xvfb.sh &&
|
source selfdrive/test/setup_xvfb.sh &&
|
||||||
CACHE_ROOT=/tmp/comma_download_cache python3 selfdrive/ui/tests/test_ui/run.py &&
|
python3 selfdrive/ui/tests/test_ui/raylib_screenshots.py"
|
||||||
chmod -R 777 /tmp/comma_download_cache"
|
- name: Upload Raylib UI Report
|
||||||
- name: Upload Test Report
|
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: ${{ env.REPORT_NAME }}
|
name: raylib-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
|
||||||
path: selfdrive/ui/tests/test_ui/report_1/screenshots
|
path: selfdrive/ui/tests/test_ui/raylib_report/screenshots
|
||||||
@@ -4,7 +4,7 @@ inputs:
|
|||||||
workflow:
|
workflow:
|
||||||
description: 'The workflow file name to monitor'
|
description: 'The workflow file name to monitor'
|
||||||
required: true
|
required: true
|
||||||
default: 'selfdrive_tests.yaml'
|
default: 'tests.yaml'
|
||||||
branch:
|
branch:
|
||||||
description: 'The branch to monitor (defaults to current branch)'
|
description: 'The branch to monitor (defaults to current branch)'
|
||||||
required: false
|
required: false
|
||||||
|
|||||||
+5
-10
@@ -10,12 +10,13 @@ venv/
|
|||||||
.overlay_init
|
.overlay_init
|
||||||
.overlay_consistent
|
.overlay_consistent
|
||||||
.sconsign.dblite
|
.sconsign.dblite
|
||||||
model2.png
|
|
||||||
a.out
|
a.out
|
||||||
.hypothesis
|
.hypothesis
|
||||||
|
.cache/
|
||||||
|
|
||||||
/docs_site/
|
/docs_site/
|
||||||
|
|
||||||
|
*.mp4
|
||||||
*.dylib
|
*.dylib
|
||||||
*.DSYM
|
*.DSYM
|
||||||
*.d
|
*.d
|
||||||
@@ -35,30 +36,23 @@ a.out
|
|||||||
*.class
|
*.class
|
||||||
*.pyxbldc
|
*.pyxbldc
|
||||||
*.vcd
|
*.vcd
|
||||||
*.qm
|
*.mo
|
||||||
*_pyx.cpp
|
*_pyx.cpp
|
||||||
|
*.stats
|
||||||
config.json
|
config.json
|
||||||
clcache
|
clcache
|
||||||
compile_commands.json
|
compile_commands.json
|
||||||
compare_runtime*.html
|
compare_runtime*.html
|
||||||
|
|
||||||
persist
|
|
||||||
selfdrive/pandad/pandad
|
selfdrive/pandad/pandad
|
||||||
cereal/services.h
|
cereal/services.h
|
||||||
cereal/gen
|
cereal/gen
|
||||||
cereal/messaging/bridge
|
cereal/messaging/bridge
|
||||||
selfdrive/mapd/default_speeds_by_region.json
|
|
||||||
system/proclogd/proclogd
|
|
||||||
selfdrive/ui/translations/tmp
|
selfdrive/ui/translations/tmp
|
||||||
selfdrive/test/longitudinal_maneuvers/out
|
|
||||||
selfdrive/car/tests/cars_dump
|
selfdrive/car/tests/cars_dump
|
||||||
system/camerad/camerad
|
system/camerad/camerad
|
||||||
system/camerad/test/ae_gray_test
|
system/camerad/test/ae_gray_test
|
||||||
|
|
||||||
notebooks
|
|
||||||
hyperthneed
|
|
||||||
provisioning
|
|
||||||
|
|
||||||
.coverage*
|
.coverage*
|
||||||
coverage.xml
|
coverage.xml
|
||||||
htmlcov
|
htmlcov
|
||||||
@@ -75,6 +69,7 @@ sunnypilot/modeld*/thneed/compile
|
|||||||
sunnypilot/modeld*/models/*.thneed
|
sunnypilot/modeld*/models/*.thneed
|
||||||
sunnypilot/modeld*/models/*.pkl
|
sunnypilot/modeld*/models/*.pkl
|
||||||
|
|
||||||
|
# openpilot log files
|
||||||
*.bz2
|
*.bz2
|
||||||
*.zst
|
*.zst
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@
|
|||||||
url = https://github.com/sunnypilot/opendbc.git
|
url = https://github.com/sunnypilot/opendbc.git
|
||||||
[submodule "msgq"]
|
[submodule "msgq"]
|
||||||
path = msgq_repo
|
path = msgq_repo
|
||||||
url = https://github.com/sunnypilot/msgq.git
|
url = https://github.com/commaai/msgq.git
|
||||||
[submodule "rednose_repo"]
|
[submodule "rednose_repo"]
|
||||||
path = rednose_repo
|
path = rednose_repo
|
||||||
url = https://github.com/commaai/rednose.git
|
url = https://github.com/commaai/rednose.git
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
url = https://github.com/commaai/teleoprtc
|
url = https://github.com/commaai/teleoprtc
|
||||||
[submodule "tinygrad"]
|
[submodule "tinygrad"]
|
||||||
path = tinygrad_repo
|
path = tinygrad_repo
|
||||||
url = https://github.com/tinygrad/tinygrad.git
|
url = https://github.com/commaai/tinygrad.git
|
||||||
[submodule "sunnypilot/neural_network_data"]
|
[submodule "sunnypilot/neural_network_data"]
|
||||||
path = sunnypilot/neural_network_data
|
path = sunnypilot/neural_network_data
|
||||||
url = https://github.com/sunnypilot/neural-network-data.git
|
url = https://github.com/sunnypilot/neural-network-data.git
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Build_BIG_UI" type="PythonConfigurationType" factoryName="Python">
|
||||||
|
<module name="sunnypilot" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<envs>
|
||||||
|
<env name="BIG" value="1" />
|
||||||
|
</envs>
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="SCRIPT_NAME" value="$ProjectFileDir$/selfdrive/ui/ui.py" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="ToolBeforeRunTask" enabled="true" actionId="Tool_External Tools_uv Scons Build Debug" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="Build_SMALL_UI" type="PythonConfigurationType" factoryName="Python">
|
||||||
|
<module name="sunnypilot" />
|
||||||
|
<option name="ENV_FILES" value="" />
|
||||||
|
<option name="INTERPRETER_OPTIONS" value="" />
|
||||||
|
<option name="PARENT_ENVS" value="true" />
|
||||||
|
<option name="SDK_HOME" value="" />
|
||||||
|
<option name="WORKING_DIRECTORY" value="$ProjectFileDir$/" />
|
||||||
|
<option name="IS_MODULE_SDK" value="true" />
|
||||||
|
<option name="ADD_CONTENT_ROOTS" value="true" />
|
||||||
|
<option name="ADD_SOURCE_ROOTS" value="true" />
|
||||||
|
<option name="SCRIPT_NAME" value="$ProjectFileDir$/selfdrive/ui/ui.py" />
|
||||||
|
<option name="PARAMETERS" value="" />
|
||||||
|
<option name="SHOW_COMMAND_LINE" value="false" />
|
||||||
|
<option name="EMULATE_TERMINAL" value="false" />
|
||||||
|
<option name="MODULE_MODE" value="false" />
|
||||||
|
<option name="REDIRECT_INPUT" value="false" />
|
||||||
|
<option name="INPUT_FILE" value="" />
|
||||||
|
<method v="2">
|
||||||
|
<option name="ToolBeforeRunTask" enabled="true" actionId="Tool_External Tools_uv Scons Build Debug" />
|
||||||
|
</method>
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
Vendored
+40
-1
@@ -23,6 +23,11 @@
|
|||||||
"id": "args",
|
"id": "args",
|
||||||
"description": "Arguments to pass to the process",
|
"description": "Arguments to pass to the process",
|
||||||
"type": "promptString"
|
"type": "promptString"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "replayArg",
|
||||||
|
"type": "promptString",
|
||||||
|
"description": "Enter route or segment to replay."
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"configurations": [
|
"configurations": [
|
||||||
@@ -40,7 +45,41 @@
|
|||||||
"type": "cppdbg",
|
"type": "cppdbg",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"program": "${workspaceFolder}/${input:cpp_process}",
|
"program": "${workspaceFolder}/${input:cpp_process}",
|
||||||
"cwd": "${workspaceFolder}",
|
"cwd": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Attach LLDB to Replay drive",
|
||||||
|
"type": "lldb",
|
||||||
|
"request": "attach",
|
||||||
|
"pid": "${command:pickMyProcess}",
|
||||||
|
"initCommands": [
|
||||||
|
"script import time; time.sleep(3)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Replay drive",
|
||||||
|
"type": "debugpy",
|
||||||
|
"request": "launch",
|
||||||
|
"program": "${workspaceFolder}/opendbc/safety/tests/safety_replay/replay_drive.py",
|
||||||
|
"args": [
|
||||||
|
"${input:replayArg}"
|
||||||
|
],
|
||||||
|
"console": "integratedTerminal",
|
||||||
|
"justMyCode": false,
|
||||||
|
"env": {
|
||||||
|
"PYTHONPATH": "${workspaceFolder}"
|
||||||
|
},
|
||||||
|
"subProcess": true,
|
||||||
|
"stopOnEntry": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compounds": [
|
||||||
|
{
|
||||||
|
"name": "Replay drive + Safety LLDB",
|
||||||
|
"configurations": [
|
||||||
|
"Replay drive",
|
||||||
|
"Attach LLDB to Replay drive"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
+1104
File diff suppressed because it is too large
Load Diff
@@ -9,4 +9,6 @@ WORKDIR ${OPENPILOT_PATH}
|
|||||||
|
|
||||||
COPY . ${OPENPILOT_PATH}/
|
COPY . ${OPENPILOT_PATH}/
|
||||||
|
|
||||||
RUN scons --cache-readonly -j$(nproc)
|
ENV UV_BIN="/home/batman/.local/bin/"
|
||||||
|
ENV PATH="$UV_BIN:$PATH"
|
||||||
|
RUN UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV uv run scons --cache-readonly -j$(nproc)
|
||||||
|
|||||||
@@ -0,0 +1,12 @@
|
|||||||
|
FROM ghcr.io/sunnypilot/sunnypilot-base:latest
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
ENV OPENPILOT_PATH=/home/batman/openpilot
|
||||||
|
|
||||||
|
RUN mkdir -p ${OPENPILOT_PATH}
|
||||||
|
WORKDIR ${OPENPILOT_PATH}
|
||||||
|
|
||||||
|
COPY . ${OPENPILOT_PATH}/
|
||||||
|
|
||||||
|
RUN scons --cache-readonly -j$(nproc)
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
FROM ubuntu:24.04
|
||||||
|
|
||||||
|
ENV PYTHONUNBUFFERED=1
|
||||||
|
|
||||||
|
ENV DEBIAN_FRONTEND=noninteractive
|
||||||
|
RUN apt-get update && \
|
||||||
|
apt-get install -y --no-install-recommends sudo tzdata locales ssh pulseaudio xvfb x11-xserver-utils gnome-screenshot python3-tk python3-dev && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
|
||||||
|
ENV LANG=en_US.UTF-8
|
||||||
|
ENV LANGUAGE=en_US:en
|
||||||
|
ENV LC_ALL=en_US.UTF-8
|
||||||
|
|
||||||
|
COPY tools/install_ubuntu_dependencies.sh /tmp/tools/
|
||||||
|
RUN /tmp/tools/install_ubuntu_dependencies.sh && \
|
||||||
|
rm -rf /var/lib/apt/lists/* /tmp/* && \
|
||||||
|
cd /usr/lib/gcc/arm-none-eabi/* && \
|
||||||
|
rm -rf arm/ thumb/nofp thumb/v6* thumb/v8* thumb/v7+fp thumb/v7-r+fp.sp
|
||||||
|
|
||||||
|
# Add OpenCL
|
||||||
|
RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||||
|
apt-utils \
|
||||||
|
alien \
|
||||||
|
unzip \
|
||||||
|
tar \
|
||||||
|
curl \
|
||||||
|
xz-utils \
|
||||||
|
dbus \
|
||||||
|
gcc-arm-none-eabi \
|
||||||
|
tmux \
|
||||||
|
vim \
|
||||||
|
libx11-6 \
|
||||||
|
wget \
|
||||||
|
rsync \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
RUN mkdir -p /tmp/opencl-driver-intel && \
|
||||||
|
cd /tmp/opencl-driver-intel && \
|
||||||
|
wget https://github.com/intel/llvm/releases/download/2024-WW14/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \
|
||||||
|
wget https://github.com/oneapi-src/oneTBB/releases/download/v2021.12.0/oneapi-tbb-2021.12.0-lin.tgz && \
|
||||||
|
mkdir -p /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \
|
||||||
|
cd /opt/intel/oclcpuexp_2024.17.3.0.09_rel && \
|
||||||
|
tar -zxvf /tmp/opencl-driver-intel/oclcpuexp-2024.17.3.0.09_rel.tar.gz && \
|
||||||
|
mkdir -p /etc/OpenCL/vendors && \
|
||||||
|
echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64/libintelocl.so > /etc/OpenCL/vendors/intel_expcpu.icd && \
|
||||||
|
cd /opt/intel && \
|
||||||
|
tar -zxvf /tmp/opencl-driver-intel/oneapi-tbb-2021.12.0-lin.tgz && \
|
||||||
|
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
||||||
|
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
||||||
|
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbb.so.12 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
||||||
|
ln -s /opt/intel/oneapi-tbb-2021.12.0/lib/intel64/gcc4.8/libtbbmalloc.so.2 /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 && \
|
||||||
|
mkdir -p /etc/ld.so.conf.d && \
|
||||||
|
echo /opt/intel/oclcpuexp_2024.17.3.0.09_rel/x64 > /etc/ld.so.conf.d/libintelopenclexp.conf && \
|
||||||
|
ldconfig -f /etc/ld.so.conf.d/libintelopenclexp.conf && \
|
||||||
|
cd / && \
|
||||||
|
rm -rf /tmp/opencl-driver-intel
|
||||||
|
|
||||||
|
ENV NVIDIA_VISIBLE_DEVICES=all
|
||||||
|
ENV NVIDIA_DRIVER_CAPABILITIES=graphics,utility,compute
|
||||||
|
ENV QTWEBENGINE_DISABLE_SANDBOX=1
|
||||||
|
|
||||||
|
RUN dbus-uuidgen > /etc/machine-id
|
||||||
|
RUN apt-get update && apt-get install -y fonts-noto-cjk fonts-noto-color-emoji
|
||||||
|
|
||||||
|
ARG USER=batman
|
||||||
|
ARG USER_UID=1001
|
||||||
|
RUN useradd -m -s /bin/bash -u $USER_UID $USER
|
||||||
|
RUN usermod -aG sudo $USER
|
||||||
|
RUN echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
|
||||||
|
USER $USER
|
||||||
|
|
||||||
|
COPY --chown=$USER pyproject.toml uv.lock /home/$USER
|
||||||
|
COPY --chown=$USER tools/install_python_dependencies.sh /home/$USER/tools/
|
||||||
|
|
||||||
|
ENV VIRTUAL_ENV=/home/$USER/.venv
|
||||||
|
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||||
|
RUN cd /home/$USER && \
|
||||||
|
tools/install_python_dependencies.sh && \
|
||||||
|
rm -rf tools/ pyproject.toml uv.lock .cache
|
||||||
|
|
||||||
|
USER root
|
||||||
|
RUN sudo git config --global --add safe.directory /tmp/openpilot
|
||||||
Vendored
+11
-25
@@ -167,7 +167,7 @@ node {
|
|||||||
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', 'release3', 'release3-staging',
|
||||||
'testing-closet*', 'hotfix-*']
|
'release-tici', 'release-tizi', 'release-tizi-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_')) {
|
||||||
@@ -178,20 +178,20 @@ node {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
if (env.BRANCH_NAME == 'devel-staging') {
|
if (env.BRANCH_NAME == 'devel-staging') {
|
||||||
deviceStage("build release3-staging", "tici-needs-can", [], [
|
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
|
||||||
step("build release3-staging", "RELEASE_BRANCH=release3-staging $SOURCE_DIR/release/build_release.sh"),
|
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
if (env.BRANCH_NAME == '__nightly') {
|
if (env.BRANCH_NAME == '__nightly') {
|
||||||
parallel (
|
parallel (
|
||||||
'nightly': {
|
'nightly': {
|
||||||
deviceStage("build nightly", "tici-needs-can", [], [
|
deviceStage("build nightly", "tizi-needs-can", [], [
|
||||||
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"),
|
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'nightly-dev': {
|
'nightly-dev': {
|
||||||
deviceStage("build nightly-dev", "tici-needs-can", [], [
|
deviceStage("build nightly-dev", "tizi-needs-can", [], [
|
||||||
step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"),
|
step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
@@ -200,39 +200,30 @@ node {
|
|||||||
|
|
||||||
if (!env.BRANCH_NAME.matches(excludeRegex)) {
|
if (!env.BRANCH_NAME.matches(excludeRegex)) {
|
||||||
parallel (
|
parallel (
|
||||||
// tici tests
|
|
||||||
'onroad tests': {
|
'onroad tests': {
|
||||||
deviceStage("onroad", "tici-needs-can", ["UNSAFE=1"], [
|
deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [
|
||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
step("build openpilot", "cd system/manager && ./build.py"),
|
||||||
step("check dirty", "release/check-dirty.sh"),
|
step("check dirty", "release/check-dirty.sh"),
|
||||||
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]),
|
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'HW + Unit Tests': {
|
'HW + Unit Tests': {
|
||||||
deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [
|
deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("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", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
||||||
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
|
step("test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"),
|
||||||
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
|
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]),
|
||||||
step("test pigeond", "pytest system/ubloxd/tests/test_pigeond.py", [diffPaths: ["system/ubloxd/"]]),
|
|
||||||
step("test manager", "pytest system/manager/test/test_manager.py"),
|
step("test manager", "pytest system/manager/test/test_manager.py"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'loopback': {
|
'loopback': {
|
||||||
deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [
|
deviceStage("loopback", "tizi-loopback", ["UNSAFE=1"], [
|
||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
step("build openpilot", "cd system/manager && ./build.py"),
|
||||||
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'camerad AR0231': {
|
|
||||||
deviceStage("AR0231", "tici-ar0231", ["UNSAFE=1"], [
|
|
||||||
step("build", "cd system/manager && ./build.py"),
|
|
||||||
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
|
||||||
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
|
||||||
])
|
|
||||||
},
|
|
||||||
'camerad OX03C10': {
|
'camerad OX03C10': {
|
||||||
deviceStage("OX03C10", "tici-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 camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 60]),
|
||||||
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
step("test exposure", "pytest system/camerad/test/test_exposure.py"),
|
||||||
@@ -246,17 +237,13 @@ node {
|
|||||||
])
|
])
|
||||||
},
|
},
|
||||||
'sensord': {
|
'sensord': {
|
||||||
deviceStage("LSM + MMC", "tici-lsmc", ["UNSAFE=1"], [
|
deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py"),
|
|
||||||
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
|
||||||
])
|
|
||||||
deviceStage("BMX + LSM", "tici-bmx-lsm", ["UNSAFE=1"], [
|
|
||||||
step("build", "cd system/manager && ./build.py"),
|
step("build", "cd system/manager && ./build.py"),
|
||||||
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
step("test sensord", "pytest system/sensord/tests/test_sensord.py"),
|
||||||
])
|
])
|
||||||
},
|
},
|
||||||
'replay': {
|
'replay': {
|
||||||
deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [
|
deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [
|
||||||
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
||||||
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]),
|
||||||
])
|
])
|
||||||
@@ -266,7 +253,6 @@ node {
|
|||||||
step("build openpilot", "cd system/manager && ./build.py"),
|
step("build openpilot", "cd system/manager && ./build.py"),
|
||||||
step("test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
step("test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"),
|
||||||
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"),
|
||||||
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py", [diffPaths: ["panda", "selfdrive/pandad/"]]),
|
|
||||||
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
step("test amp", "pytest system/hardware/tici/tests/test_amplifier.py"),
|
||||||
// TODO: enable once new AGNOS is available
|
// TODO: enable once new AGNOS is available
|
||||||
// step("test esim", "pytest system/hardware/tici/tests/test_esim.py"),
|
// step("test esim", "pytest system/hardware/tici/tests/test_esim.py"),
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
## 🌞 What is sunnypilot?
|
## 🌞 What is sunnypilot?
|
||||||
[sunnypilot](https://github.com/sunnyhaibin/sunnypilot) is a fork of comma.ai's openpilot, an open source driver assistance system. sunnypilot offers the user a unique driving experience for over 300+ supported car makes and models with modified behaviors of driving assist engagements. sunnypilot complies with comma.ai's safety rules as accurately as possible.
|
[sunnypilot](https://github.com/sunnyhaibin/sunnypilot) is a fork of comma.ai's openpilot, an open source driver assistance system. sunnypilot offers the user a unique driving experience for over 300+ supported car makes and models with modified behaviors of driving assist engagements. sunnypilot complies with comma.ai's safety rules as accurately as possible.
|
||||||
|
|
||||||
## 💭 Join our Discord
|
## 💭 Join our Community Forum
|
||||||
Join the official sunnypilot Discord server to stay up to date with all the latest features and be a part of shaping the future of sunnypilot!
|
Join the official sunnypilot community forum to stay up to date with all the latest features and be a part of shaping the future of sunnypilot!
|
||||||
* https://discord.gg/sunnypilot
|
* https://community.sunnypilot.ai/
|
||||||
|
|
||||||
 
|
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
|
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
|
||||||
@@ -16,25 +14,54 @@ https://docs.sunnypilot.ai/ is your one stop shop for everything from features t
|
|||||||
* A supported device to run this software
|
* A supported device to run this software
|
||||||
* a [comma three](https://comma.ai/shop/products/three) or a [C3X](https://comma.ai/shop/comma-3x)
|
* a [comma three](https://comma.ai/shop/products/three) or a [C3X](https://comma.ai/shop/comma-3x)
|
||||||
* This software
|
* This software
|
||||||
* One of [the 300+ supported cars](https://github.com/commaai/openpilot/blob/master/docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, Ford and more. If your car is not supported but has adaptive cruise control and lane-keeping assist, it's likely able to run sunnypilot.
|
* One of [the 325+ supported cars](https://github.com/sunnypilot/sunnypilot/blob/master/docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, Ford, and more. If your car is not supported but has adaptive cruise control and lane-keeping assist, it's likely able to run sunnypilot.
|
||||||
* A [car harness](https://comma.ai/shop/products/car-harness) to connect to your car
|
* A [car harness](https://comma.ai/shop/products/car-harness) to connect to your car
|
||||||
|
|
||||||
Detailed instructions for [how to mount the device in a car](https://comma.ai/setup).
|
Detailed instructions for [how to mount the device in a car](https://comma.ai/setup).
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
Please refer to [Recommended Branches](#-recommended-branches) to find your preferred/supported branch. This guide will assume you want to install the latest `release-c3` branch.
|
Please refer to [Recommended Branches](#recommended-branches) to find your preferred/supported branch. This guide will assume you want to install the latest `staging` branch.
|
||||||
|
|
||||||
|
### If you want to use our newest branches (our rewrite)
|
||||||
|
> [!TIP]
|
||||||
|
>You can see the rewrite state on our [rewrite project board](https://github.com/orgs/sunnypilot/projects/2), and to install the new branches, you can use the following links
|
||||||
|
|
||||||
* sunnypilot not installed or you installed a version before 0.8.17?
|
* sunnypilot not installed or you installed a version before 0.8.17?
|
||||||
1. [Factory reset/uninstall](https://github.com/commaai/openpilot/wiki/FAQ#how-can-i-reset-the-device) the previous software if you have another software/fork installed.
|
1. [Factory reset/uninstall](https://github.com/commaai/openpilot/wiki/FAQ#how-can-i-reset-the-device) the previous software if you have another software/fork installed.
|
||||||
2. After factory reset/uninstall and upon reboot, select `Custom Software` when given the option.
|
2. After factory reset/uninstall and upon reboot, select `Custom Software` when given the option.
|
||||||
3. Input the installation URL per [Recommended Branches](#-recommended-branches). Example: ```release-c3.sunnypilot.ai```.
|
3. Input the installation URL per [Recommended Branches](#recommended-branches). Example: ```https://staging.sunnypilot.ai```.
|
||||||
4. Complete the rest of the installation following the onscreen instructions.
|
4. Complete the rest of the installation following the onscreen instructions.
|
||||||
|
|
||||||
* sunnypilot already installed and you installed a version after 0.8.17?
|
* sunnypilot already installed and you installed a version after 0.8.17?
|
||||||
1. On the comma three, go to `Settings` ▶️ `Software`.
|
1. On the comma three/3X, go to `Settings` ▶️ `Software`.
|
||||||
2. At the `Download` option, press `CHECK`. This will fetch the list of latest branches from sunnypilot.
|
2. At the `Download` option, press `CHECK`. This will fetch the list of latest branches from sunnypilot.
|
||||||
3. At the `Target Branch` option, press `SELECT` to open the Target Branch selector.
|
3. At the `Target Branch` option, press `SELECT` to open the Target Branch selector.
|
||||||
4. Scroll to select the desired branch per Recommended Branches (see below). Example: `release-c3`
|
4. Scroll to select the desired branch per Recommended Branches (see below). Example: `staging`
|
||||||
|
|
||||||
|
### Recommended Branches
|
||||||
|
| Branch | Installation URL |
|
||||||
|
|:---------------:|:---------------------------------------------:|
|
||||||
|
| `release` | `https://release.sunnypilot.ai` |
|
||||||
|
| `staging` | `https://staging.sunnypilot.ai` |
|
||||||
|
| `dev` | `https://dev.sunnypilot.ai` |
|
||||||
|
| `custom-branch` | `https://install.sunnypilot.ai/{branch_name}` |
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> You can use sunnypilot/targetbranch as an install URL. Example: 'sunnypilot/staging'.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> Do you require further assistance with software installation? Join the [sunnypilot community forum](https://community.sunnypilot.ai/new-topic?category=general/qa) and create a topic in the General/Q&A Category channel.
|
||||||
|
|
||||||
|
|
||||||
|
<details>
|
||||||
|
|
||||||
|
<summary>Older legacy branches</summary>
|
||||||
|
|
||||||
|
### If you want to use our older legacy branches (*not recommended*)
|
||||||
|
|
||||||
|
> [**IMPORTANT**]
|
||||||
|
> It is recommended to [re-flash AGNOS](https://flash.comma.ai/) if you intend to downgrade from the new branches.
|
||||||
|
> You can still restore the latest sunnylink backup made on the old branches.
|
||||||
|
|
||||||
| Branch | Installation URL |
|
| Branch | Installation URL |
|
||||||
|:------------:|:--------------------------------:|
|
|:------------:|:--------------------------------:|
|
||||||
@@ -42,29 +69,13 @@ Please refer to [Recommended Branches](#-recommended-branches) to find your pref
|
|||||||
| `staging-c3` | https://staging-c3.sunnypilot.ai |
|
| `staging-c3` | https://staging-c3.sunnypilot.ai |
|
||||||
| `dev-c3` | https://dev-c3.sunnypilot.ai |
|
| `dev-c3` | https://dev-c3.sunnypilot.ai |
|
||||||
|
|
||||||
### If you want to use our newest branches (our rewrite)
|
</details>
|
||||||
> [!TIP]
|
|
||||||
>You can see the rewrite state on our [rewrite project board](https://github.com/orgs/sunnypilot/projects/2), and to install the new branches, you can use the following links
|
|
||||||
|
|
||||||
|
|
||||||
> [!IMPORTANT]
|
|
||||||
> It is recommended to [re-flash AGNOS](https://flash.comma.ai/) if you intend to downgrade from the new branches.
|
|
||||||
> You can still restore the latest sunnylink backup made on the old branches.
|
|
||||||
|
|
||||||
| Branch | Installation URL |
|
|
||||||
|:----------------:|:---------------------------------------------:|
|
|
||||||
| `staging-c3-new` | `https://staging-c3-new.sunnypilot.ai` |
|
|
||||||
| `dev-c3-new` | `https://dev-c3-new.sunnypilot.ai` |
|
|
||||||
| `custom-branch` | `https://install.sunnypilot.ai/{branch_name}` |
|
|
||||||
| `release-c3-new` | **Not yet available**. |
|
|
||||||
|
|
||||||
> [!TIP]
|
|
||||||
> Do you require further assistance with software installation? Join the [sunnypilot Discord server](https://discord.sunnypilot.com) and message us in the `#installation-help` channel.
|
|
||||||
|
|
||||||
## 🎆 Pull Requests
|
## 🎆 Pull Requests
|
||||||
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
|
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
|
||||||
|
|
||||||
Pull requests should be against the most current `master-new` branch.
|
Pull requests should be against the most current `master` branch.
|
||||||
|
|
||||||
## 📊 User Data
|
## 📊 User Data
|
||||||
|
|
||||||
|
|||||||
+29
-4
@@ -1,11 +1,36 @@
|
|||||||
Version 0.10.0 (2025-07-07)
|
Version 0.10.2 (2025-11-19)
|
||||||
|
========================
|
||||||
|
* comma four support
|
||||||
|
|
||||||
|
Version 0.10.1 (2025-09-08)
|
||||||
|
========================
|
||||||
|
* New driving model #36276
|
||||||
|
* World Model: removed global localization inputs
|
||||||
|
* World Model: 2x the number of parameters
|
||||||
|
* World Model: trained on 4x the number of segments
|
||||||
|
* VAE Compression Model: new architecture and training objective
|
||||||
|
* Driving Vision Model: trained on 4x the number of segments
|
||||||
|
* New Driver Monitoring model #36198
|
||||||
|
* Acura TLX 2021 support thanks to MVL!
|
||||||
|
* Honda City 2023 support thanks to vanillagorillaa and drFritz!
|
||||||
|
* Honda N-Box 2018 support thanks to miettal!
|
||||||
|
* Honda Odyssey 2021-25 support thanks to csouers and MVL!
|
||||||
|
* Honda Passport 2026 support thanks to vanillagorillaa and MVL!
|
||||||
|
|
||||||
|
Version 0.10.0 (2025-08-05)
|
||||||
========================
|
========================
|
||||||
* New driving model
|
* New driving model
|
||||||
* Lead car ground-truth fixes
|
* New training architecture
|
||||||
* Ported over VAE from the MLSIM stack
|
* Described in our CVPR paper: "Learning to Drive from a World Model"
|
||||||
* New training architecture described in CVPR paper
|
* Longitudinal MPC replaced by E2E planning from World Model in Experimental Mode
|
||||||
|
* Action from lateral MPC as training objective replaced by E2E planning from World Model
|
||||||
|
* Low-speed lead car ground-truth fixes
|
||||||
* Enable live-learned steering actuation delay
|
* Enable live-learned steering actuation delay
|
||||||
* Opt-in audio recording for dashcam video
|
* Opt-in audio recording for dashcam video
|
||||||
|
* Acura MDX 2025 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda Accord 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda CR-V 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
* Honda Pilot 2023-25 support thanks to vanillagorillaa and MVL!
|
||||||
|
|
||||||
Version 0.9.9 (2025-05-23)
|
Version 0.9.9 (2025-05-23)
|
||||||
========================
|
========================
|
||||||
|
|||||||
+105
-256
@@ -3,178 +3,52 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import sysconfig
|
import sysconfig
|
||||||
import platform
|
import platform
|
||||||
|
import shlex
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import SCons.Errors
|
import SCons.Errors
|
||||||
|
|
||||||
SCons.Warnings.warningAsException(True)
|
SCons.Warnings.warningAsException(True)
|
||||||
|
|
||||||
# pending upstream fix - https://github.com/SCons/scons/issues/4461
|
|
||||||
#SetOption('warn', 'all')
|
|
||||||
|
|
||||||
TICI = os.path.isfile('/TICI')
|
|
||||||
AGNOS = TICI
|
|
||||||
|
|
||||||
Decider('MD5-timestamp')
|
Decider('MD5-timestamp')
|
||||||
|
|
||||||
SetOption('num_jobs', int(os.cpu_count()/2))
|
SetOption('num_jobs', max(1, int(os.cpu_count()/2)))
|
||||||
|
|
||||||
AddOption('--kaitai',
|
|
||||||
action='store_true',
|
|
||||||
help='Regenerate kaitai struct parsers')
|
|
||||||
|
|
||||||
AddOption('--asan',
|
|
||||||
action='store_true',
|
|
||||||
help='turn on ASAN')
|
|
||||||
|
|
||||||
AddOption('--ubsan',
|
|
||||||
action='store_true',
|
|
||||||
help='turn on UBSan')
|
|
||||||
|
|
||||||
AddOption('--coverage',
|
|
||||||
action='store_true',
|
|
||||||
help='build with test coverage options')
|
|
||||||
|
|
||||||
AddOption('--clazy',
|
|
||||||
action='store_true',
|
|
||||||
help='build with clazy')
|
|
||||||
|
|
||||||
AddOption('--ccflags',
|
|
||||||
action='store',
|
|
||||||
type='string',
|
|
||||||
default='',
|
|
||||||
help='pass arbitrary flags over the command line')
|
|
||||||
|
|
||||||
AddOption('--external-sconscript',
|
|
||||||
action='store',
|
|
||||||
metavar='FILE',
|
|
||||||
dest='external_sconscript',
|
|
||||||
help='add an external SConscript to the build')
|
|
||||||
|
|
||||||
AddOption('--mutation',
|
|
||||||
action='store_true',
|
|
||||||
help='generate mutation-ready code')
|
|
||||||
|
|
||||||
|
AddOption('--kaitai', action='store_true', help='Regenerate kaitai struct parsers')
|
||||||
|
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('--minimal',
|
AddOption('--minimal',
|
||||||
action='store_false',
|
action='store_false',
|
||||||
dest='extras',
|
dest='extras',
|
||||||
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
|
default=os.path.exists(File('#.gitattributes').abspath), # minimal by default on release branch (where there's no LFS)
|
||||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||||
|
|
||||||
AddOption('--stock-ui',
|
# Detect platform
|
||||||
action='store_true',
|
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
||||||
dest='stock_ui',
|
|
||||||
default=False,
|
|
||||||
help='Build stock openpilot UI instead of sunnypilot UI')
|
|
||||||
|
|
||||||
## Architecture name breakdown (arch)
|
|
||||||
## - larch64: linux tici aarch64
|
|
||||||
## - aarch64: linux pc aarch64
|
|
||||||
## - x86_64: linux pc x64
|
|
||||||
## - Darwin: mac x64 or arm64
|
|
||||||
real_arch = arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
|
|
||||||
if platform.system() == "Darwin":
|
if platform.system() == "Darwin":
|
||||||
arch = "Darwin"
|
arch = "Darwin"
|
||||||
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
|
brew_prefix = subprocess.check_output(['brew', '--prefix'], encoding='utf8').strip()
|
||||||
elif arch == "aarch64" and AGNOS:
|
elif arch == "aarch64" and os.path.isfile('/TICI'):
|
||||||
arch = "larch64"
|
arch = "larch64"
|
||||||
assert arch in ["larch64", "aarch64", "x86_64", "Darwin"]
|
assert arch in [
|
||||||
|
"larch64", # linux tici arm64
|
||||||
lenv = {
|
"aarch64", # linux pc arm64
|
||||||
"PATH": os.environ['PATH'],
|
"x86_64", # linux pc x64
|
||||||
"LD_LIBRARY_PATH": [Dir(f"#third_party/acados/{arch}/lib").abspath],
|
"Darwin", # macOS arm64 (x86 not supported)
|
||||||
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
]
|
||||||
|
|
||||||
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
|
||||||
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
|
||||||
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
|
||||||
}
|
|
||||||
|
|
||||||
rpath = lenv["LD_LIBRARY_PATH"].copy()
|
|
||||||
|
|
||||||
if arch == "larch64":
|
|
||||||
cpppath = [
|
|
||||||
"#third_party/opencl/include",
|
|
||||||
]
|
|
||||||
|
|
||||||
libpath = [
|
|
||||||
"/usr/local/lib",
|
|
||||||
"/system/vendor/lib64",
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
]
|
|
||||||
|
|
||||||
libpath += [
|
|
||||||
"#third_party/snpe/larch64",
|
|
||||||
"#third_party/libyuv/larch64/lib",
|
|
||||||
"/usr/lib/aarch64-linux-gnu"
|
|
||||||
]
|
|
||||||
cflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
cxxflags = ["-DQCOM2", "-mcpu=cortex-a57"]
|
|
||||||
rpath += ["/usr/local/lib"]
|
|
||||||
else:
|
|
||||||
cflags = []
|
|
||||||
cxxflags = []
|
|
||||||
cpppath = []
|
|
||||||
rpath += []
|
|
||||||
|
|
||||||
# MacOS
|
|
||||||
if arch == "Darwin":
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"{brew_prefix}/lib",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/lib",
|
|
||||||
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
|
||||||
]
|
|
||||||
|
|
||||||
cflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cxxflags += ["-DGL_SILENCE_DEPRECATION"]
|
|
||||||
cpppath += [
|
|
||||||
f"{brew_prefix}/include",
|
|
||||||
f"{brew_prefix}/opt/openssl@3.0/include",
|
|
||||||
]
|
|
||||||
lenv["DYLD_LIBRARY_PATH"] = lenv["LD_LIBRARY_PATH"]
|
|
||||||
# Linux
|
|
||||||
else:
|
|
||||||
libpath = [
|
|
||||||
f"#third_party/acados/{arch}/lib",
|
|
||||||
f"#third_party/libyuv/{arch}/lib",
|
|
||||||
"/usr/lib",
|
|
||||||
"/usr/local/lib",
|
|
||||||
]
|
|
||||||
|
|
||||||
if arch == "x86_64":
|
|
||||||
libpath += [
|
|
||||||
f"#third_party/snpe/{arch}"
|
|
||||||
]
|
|
||||||
rpath += [
|
|
||||||
Dir(f"#third_party/snpe/{arch}").abspath,
|
|
||||||
]
|
|
||||||
|
|
||||||
if GetOption('asan'):
|
|
||||||
ccflags = ["-fsanitize=address", "-fno-omit-frame-pointer"]
|
|
||||||
ldflags = ["-fsanitize=address"]
|
|
||||||
elif GetOption('ubsan'):
|
|
||||||
ccflags = ["-fsanitize=undefined"]
|
|
||||||
ldflags = ["-fsanitize=undefined"]
|
|
||||||
else:
|
|
||||||
ccflags = []
|
|
||||||
ldflags = []
|
|
||||||
|
|
||||||
# no --as-needed on mac linker
|
|
||||||
if arch != "Darwin":
|
|
||||||
ldflags += ["-Wl,--as-needed", "-Wl,--no-undefined"]
|
|
||||||
|
|
||||||
if not GetOption('stock_ui'):
|
|
||||||
cflags += ["-DSUNNYPILOT"]
|
|
||||||
cxxflags += ["-DSUNNYPILOT"]
|
|
||||||
|
|
||||||
ccflags_option = GetOption('ccflags')
|
|
||||||
if ccflags_option:
|
|
||||||
ccflags += ccflags_option.split(' ')
|
|
||||||
|
|
||||||
env = Environment(
|
env = Environment(
|
||||||
ENV=lenv,
|
ENV={
|
||||||
|
"PATH": os.environ['PATH'],
|
||||||
|
"PYTHONPATH": Dir("#").abspath + ':' + Dir(f"#third_party/acados").abspath,
|
||||||
|
"ACADOS_SOURCE_DIR": Dir("#third_party/acados").abspath,
|
||||||
|
"ACADOS_PYTHON_INTERFACE_PATH": Dir("#third_party/acados/acados_template").abspath,
|
||||||
|
"TERA_PATH": Dir("#").abspath + f"/third_party/acados/{arch}/t_renderer"
|
||||||
|
},
|
||||||
|
CC='clang',
|
||||||
|
CXX='clang++',
|
||||||
CCFLAGS=[
|
CCFLAGS=[
|
||||||
"-g",
|
"-g",
|
||||||
"-fPIC",
|
"-fPIC",
|
||||||
@@ -187,37 +61,32 @@ env = Environment(
|
|||||||
"-Wno-c99-designator",
|
"-Wno-c99-designator",
|
||||||
"-Wno-reorder-init-list",
|
"-Wno-reorder-init-list",
|
||||||
"-Wno-vla-cxx-extension",
|
"-Wno-vla-cxx-extension",
|
||||||
] + cflags + ccflags,
|
],
|
||||||
|
CFLAGS=["-std=gnu11"],
|
||||||
CPPPATH=cpppath + [
|
CXXFLAGS=["-std=c++1z"],
|
||||||
|
CPPPATH=[
|
||||||
"#",
|
"#",
|
||||||
|
"#msgq",
|
||||||
|
"#third_party",
|
||||||
|
"#third_party/json11",
|
||||||
|
"#third_party/linux/include",
|
||||||
"#third_party/acados/include",
|
"#third_party/acados/include",
|
||||||
"#third_party/acados/include/blasfeo/include",
|
"#third_party/acados/include/blasfeo/include",
|
||||||
"#third_party/acados/include/hpipm/include",
|
"#third_party/acados/include/hpipm/include",
|
||||||
"#third_party/catch2/include",
|
"#third_party/catch2/include",
|
||||||
"#third_party/libyuv/include",
|
"#third_party/libyuv/include",
|
||||||
"#third_party/json11",
|
|
||||||
"#third_party/linux/include",
|
|
||||||
"#third_party/snpe/include",
|
"#third_party/snpe/include",
|
||||||
"#third_party",
|
|
||||||
"#msgq",
|
|
||||||
],
|
],
|
||||||
|
LIBPATH=[
|
||||||
CC='clang',
|
"#common",
|
||||||
CXX='clang++',
|
|
||||||
LINKFLAGS=ldflags,
|
|
||||||
|
|
||||||
RPATH=rpath,
|
|
||||||
|
|
||||||
CFLAGS=["-std=gnu11"] + cflags,
|
|
||||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
|
||||||
LIBPATH=libpath + [
|
|
||||||
"#msgq_repo",
|
"#msgq_repo",
|
||||||
"#third_party",
|
"#third_party",
|
||||||
"#selfdrive/pandad",
|
"#selfdrive/pandad",
|
||||||
"#common",
|
|
||||||
"#rednose/helpers",
|
"#rednose/helpers",
|
||||||
|
f"#third_party/libyuv/{arch}/lib",
|
||||||
|
f"#third_party/acados/{arch}/lib",
|
||||||
],
|
],
|
||||||
|
RPATH=[],
|
||||||
CYTHONCFILESUFFIX=".cpp",
|
CYTHONCFILESUFFIX=".cpp",
|
||||||
COMPILATIONDB_USE_ABSPATH=True,
|
COMPILATIONDB_USE_ABSPATH=True,
|
||||||
REDNOSE_ROOT="#",
|
REDNOSE_ROOT="#",
|
||||||
@@ -225,30 +94,72 @@ env = Environment(
|
|||||||
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
|
||||||
)
|
)
|
||||||
|
|
||||||
if arch == "Darwin":
|
# Arch-specific flags and paths
|
||||||
# RPATH is not supported on macOS, instead use the linker flags
|
if arch == "larch64":
|
||||||
darwin_rpath_link_flags = [f"-Wl,-rpath,{path}" for path in env["RPATH"]]
|
env.Append(CPPPATH=["#third_party/opencl/include"])
|
||||||
env["LINKFLAGS"] += darwin_rpath_link_flags
|
env.Append(LIBPATH=[
|
||||||
|
"/usr/local/lib",
|
||||||
|
"/system/vendor/lib64",
|
||||||
|
"/usr/lib/aarch64-linux-gnu",
|
||||||
|
"#third_party/snpe/larch64",
|
||||||
|
])
|
||||||
|
arch_flags = ["-D__TICI__", "-mcpu=cortex-a57", "-DQCOM2"]
|
||||||
|
env.Append(CCFLAGS=arch_flags)
|
||||||
|
env.Append(CXXFLAGS=arch_flags)
|
||||||
|
elif arch == "Darwin":
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
f"{brew_prefix}/lib",
|
||||||
|
f"{brew_prefix}/opt/openssl@3.0/lib",
|
||||||
|
f"{brew_prefix}/opt/llvm/lib/c++",
|
||||||
|
"/System/Library/Frameworks/OpenGL.framework/Libraries",
|
||||||
|
])
|
||||||
|
env.Append(CCFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
|
env.Append(CXXFLAGS=["-DGL_SILENCE_DEPRECATION"])
|
||||||
|
env.Append(CPPPATH=[
|
||||||
|
f"{brew_prefix}/include",
|
||||||
|
f"{brew_prefix}/opt/openssl@3.0/include",
|
||||||
|
])
|
||||||
|
else:
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
"/usr/lib",
|
||||||
|
"/usr/local/lib",
|
||||||
|
])
|
||||||
|
|
||||||
env.CompilationDatabase('compile_commands.json')
|
if arch == "x86_64":
|
||||||
|
env.Append(LIBPATH=[
|
||||||
|
f"#third_party/snpe/{arch}"
|
||||||
|
])
|
||||||
|
env.Append(RPATH=[
|
||||||
|
Dir(f"#third_party/snpe/{arch}").abspath,
|
||||||
|
])
|
||||||
|
|
||||||
# Setup cache dir
|
# Sanitizers and extra CCFLAGS from CLI
|
||||||
default_cache_dir = '/data/scons_cache' if AGNOS else '/tmp/scons_cache'
|
if GetOption('asan'):
|
||||||
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
env.Append(CCFLAGS=["-fsanitize=address", "-fno-omit-frame-pointer"])
|
||||||
CacheDir(cache_dir)
|
env.Append(LINKFLAGS=["-fsanitize=address"])
|
||||||
Clean(["."], cache_dir)
|
elif GetOption('ubsan'):
|
||||||
|
env.Append(CCFLAGS=["-fsanitize=undefined"])
|
||||||
|
env.Append(LINKFLAGS=["-fsanitize=undefined"])
|
||||||
|
|
||||||
|
_extra_cc = shlex.split(GetOption('ccflags') or '')
|
||||||
|
if _extra_cc:
|
||||||
|
env.Append(CCFLAGS=_extra_cc)
|
||||||
|
|
||||||
|
# no --as-needed on mac linker
|
||||||
|
if arch != "Darwin":
|
||||||
|
env.Append(LINKFLAGS=["-Wl,--as-needed", "-Wl,--no-undefined"])
|
||||||
|
|
||||||
|
# progress output
|
||||||
node_interval = 5
|
node_interval = 5
|
||||||
node_count = 0
|
node_count = 0
|
||||||
def progress_function(node):
|
def progress_function(node):
|
||||||
global node_count
|
global node_count
|
||||||
node_count += node_interval
|
node_count += node_interval
|
||||||
sys.stderr.write("progress: %d\n" % node_count)
|
sys.stderr.write("progress: %d\n" % node_count)
|
||||||
|
|
||||||
if os.environ.get('SCONS_PROGRESS'):
|
if os.environ.get('SCONS_PROGRESS'):
|
||||||
Progress(progress_function, interval=node_interval)
|
Progress(progress_function, interval=node_interval)
|
||||||
|
|
||||||
# Cython build environment
|
# ********** Cython build environment **********
|
||||||
py_include = sysconfig.get_paths()['include']
|
py_include = sysconfig.get_paths()['include']
|
||||||
envCython = env.Clone()
|
envCython = env.Clone()
|
||||||
envCython["CPPPATH"] += [py_include, np.get_include()]
|
envCython["CPPPATH"] += [py_include, np.get_include()]
|
||||||
@@ -257,84 +168,28 @@ envCython["CCFLAGS"].remove("-Werror")
|
|||||||
|
|
||||||
envCython["LIBS"] = []
|
envCython["LIBS"] = []
|
||||||
if arch == "Darwin":
|
if arch == "Darwin":
|
||||||
envCython["LINKFLAGS"] = ["-bundle", "-undefined", "dynamic_lookup"] + darwin_rpath_link_flags
|
envCython["LINKFLAGS"] = env["LINKFLAGS"] + ["-bundle", "-undefined", "dynamic_lookup"]
|
||||||
else:
|
else:
|
||||||
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
envCython["LINKFLAGS"] = ["-pthread", "-shared"]
|
||||||
|
|
||||||
np_version = SCons.Script.Value(np.__version__)
|
np_version = SCons.Script.Value(np.__version__)
|
||||||
Export('envCython', 'np_version')
|
Export('envCython', 'np_version')
|
||||||
|
|
||||||
# Qt build environment
|
Export('env', 'arch')
|
||||||
qt_env = env.Clone()
|
|
||||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "DBus", "Xml"]
|
|
||||||
|
|
||||||
qt_libs = []
|
# Setup cache dir
|
||||||
if arch == "Darwin":
|
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
|
||||||
qt_env['QTDIR'] = f"{brew_prefix}/opt/qt@5"
|
cache_dir = ARGUMENTS.get('cache_dir', default_cache_dir)
|
||||||
qt_dirs = [
|
CacheDir(cache_dir)
|
||||||
os.path.join(qt_env['QTDIR'], "include"),
|
Clean(["."], cache_dir)
|
||||||
]
|
|
||||||
qt_dirs += [f"{qt_env['QTDIR']}/include/Qt{m}" for m in qt_modules]
|
|
||||||
qt_env["LINKFLAGS"] += ["-F" + os.path.join(qt_env['QTDIR'], "lib")]
|
|
||||||
qt_env["FRAMEWORKS"] += [f"Qt{m}" for m in qt_modules] + ["OpenGL"]
|
|
||||||
qt_env.AppendENVPath('PATH', os.path.join(qt_env['QTDIR'], "bin"))
|
|
||||||
else:
|
|
||||||
qt_install_prefix = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_PREFIX'], encoding='utf8').strip()
|
|
||||||
qt_install_headers = subprocess.check_output(['qmake', '-query', 'QT_INSTALL_HEADERS'], encoding='utf8').strip()
|
|
||||||
|
|
||||||
qt_env['QTDIR'] = qt_install_prefix
|
# ********** start building stuff **********
|
||||||
qt_dirs = [
|
|
||||||
f"{qt_install_headers}",
|
|
||||||
]
|
|
||||||
|
|
||||||
qt_gui_path = os.path.join(qt_install_headers, "QtGui")
|
|
||||||
qt_gui_dirs = [d for d in os.listdir(qt_gui_path) if os.path.isdir(os.path.join(qt_gui_path, d))]
|
|
||||||
qt_dirs += [f"{qt_install_headers}/QtGui/{qt_gui_dirs[0]}/QtGui", ] if qt_gui_dirs else []
|
|
||||||
qt_dirs += [f"{qt_install_headers}/Qt{m}" for m in qt_modules]
|
|
||||||
|
|
||||||
qt_libs = [f"Qt5{m}" for m in qt_modules]
|
|
||||||
if arch == "larch64":
|
|
||||||
qt_libs += ["GLESv2", "wayland-client"]
|
|
||||||
qt_env.PrependENVPath('PATH', Dir("#third_party/qt5/larch64/bin/").abspath)
|
|
||||||
elif arch != "Darwin":
|
|
||||||
qt_libs += ["GL"]
|
|
||||||
qt_env['QT3DIR'] = qt_env['QTDIR']
|
|
||||||
qt_env.Tool('qt3')
|
|
||||||
|
|
||||||
qt_env['CPPPATH'] += qt_dirs + ["#third_party/qrcode"]
|
|
||||||
qt_flags = [
|
|
||||||
"-D_REENTRANT",
|
|
||||||
"-DQT_NO_DEBUG",
|
|
||||||
"-DQT_WIDGETS_LIB",
|
|
||||||
"-DQT_GUI_LIB",
|
|
||||||
"-DQT_CORE_LIB",
|
|
||||||
"-DQT_MESSAGELOGCONTEXT",
|
|
||||||
]
|
|
||||||
qt_env['CXXFLAGS'] += qt_flags
|
|
||||||
qt_env['LIBPATH'] += ['#selfdrive/ui', ]
|
|
||||||
qt_env['LIBS'] = qt_libs
|
|
||||||
|
|
||||||
if GetOption("clazy"):
|
|
||||||
checks = [
|
|
||||||
"level0",
|
|
||||||
"level1",
|
|
||||||
"no-range-loop",
|
|
||||||
"no-non-pod-global-static",
|
|
||||||
]
|
|
||||||
qt_env['CXX'] = 'clazy'
|
|
||||||
qt_env['ENV']['CLAZY_IGNORE_DIRS'] = qt_dirs[0]
|
|
||||||
qt_env['ENV']['CLAZY_CHECKS'] = ','.join(checks)
|
|
||||||
|
|
||||||
Export('env', 'qt_env', 'arch', 'real_arch')
|
|
||||||
|
|
||||||
# Build common module
|
# Build common module
|
||||||
SConscript(['common/SConscript'])
|
SConscript(['common/SConscript'])
|
||||||
Import('_common', '_gpucommon')
|
Import('_common')
|
||||||
|
|
||||||
common = [_common, 'json11', 'zmq']
|
common = [_common, 'json11', 'zmq']
|
||||||
gpucommon = [_gpucommon]
|
Export('common')
|
||||||
|
|
||||||
Export('common', 'gpucommon')
|
|
||||||
|
|
||||||
# Build messaging (cereal + msgq + socketmaster + their dependencies)
|
# Build messaging (cereal + msgq + socketmaster + their dependencies)
|
||||||
# Enable swaglog include in submodules
|
# Enable swaglog include in submodules
|
||||||
@@ -361,11 +216,6 @@ SConscript([
|
|||||||
'system/ubloxd/SConscript',
|
'system/ubloxd/SConscript',
|
||||||
'system/loggerd/SConscript',
|
'system/loggerd/SConscript',
|
||||||
])
|
])
|
||||||
if arch != "Darwin":
|
|
||||||
SConscript([
|
|
||||||
'system/logcatd/SConscript',
|
|
||||||
'system/proclogd/SConscript',
|
|
||||||
])
|
|
||||||
|
|
||||||
if arch == "larch64":
|
if arch == "larch64":
|
||||||
SConscript(['system/camerad/SConscript'])
|
SConscript(['system/camerad/SConscript'])
|
||||||
@@ -382,6 +232,5 @@ if Dir('#tools/cabana/').exists() and GetOption('extras'):
|
|||||||
if arch != "larch64":
|
if arch != "larch64":
|
||||||
SConscript(['tools/cabana/SConscript'])
|
SConscript(['tools/cabana/SConscript'])
|
||||||
|
|
||||||
external_sconscript = GetOption('external_sconscript')
|
|
||||||
if external_sconscript:
|
env.CompilationDatabase('compile_commands.json')
|
||||||
SConscript([external_sconscript])
|
|
||||||
|
|||||||
+218
-2
@@ -25,8 +25,92 @@ struct ModularAssistiveDrivingSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct IntelligentCruiseButtonManagement {
|
||||||
|
state @0 :IntelligentCruiseButtonManagementState;
|
||||||
|
sendButton @1 :SendButtonState;
|
||||||
|
vTarget @2 :Float32;
|
||||||
|
|
||||||
|
enum IntelligentCruiseButtonManagementState {
|
||||||
|
inactive @0; # No button press or default state
|
||||||
|
preActive @1; # Pre-active state before transitioning to increasing or decreasing
|
||||||
|
increasing @2; # Increasing speed
|
||||||
|
decreasing @3; # Decreasing speed
|
||||||
|
holding @4; # Holding steady speed
|
||||||
|
}
|
||||||
|
|
||||||
|
enum SendButtonState {
|
||||||
|
none @0;
|
||||||
|
increase @1;
|
||||||
|
decrease @2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Same struct as Log.RadarState.LeadData
|
||||||
|
struct LeadData {
|
||||||
|
dRel @0 :Float32;
|
||||||
|
yRel @1 :Float32;
|
||||||
|
vRel @2 :Float32;
|
||||||
|
aRel @3 :Float32;
|
||||||
|
vLead @4 :Float32;
|
||||||
|
dPath @6 :Float32;
|
||||||
|
vLat @7 :Float32;
|
||||||
|
vLeadK @8 :Float32;
|
||||||
|
aLeadK @9 :Float32;
|
||||||
|
fcw @10 :Bool;
|
||||||
|
status @11 :Bool;
|
||||||
|
aLeadTau @12 :Float32;
|
||||||
|
modelProb @13 :Float32;
|
||||||
|
radar @14 :Bool;
|
||||||
|
radarTrackId @15 :Int32 = -1;
|
||||||
|
|
||||||
|
aLeadDEPRECATED @5 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
struct SelfdriveStateSP @0x81c2f05a394cf4af {
|
||||||
mads @0 :ModularAssistiveDrivingSystem;
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
|
intelligentCruiseButtonManagement @1 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
|
enum AudibleAlert {
|
||||||
|
none @0;
|
||||||
|
|
||||||
|
engage @1;
|
||||||
|
disengage @2;
|
||||||
|
refuse @3;
|
||||||
|
|
||||||
|
warningSoft @4;
|
||||||
|
warningImmediate @5;
|
||||||
|
|
||||||
|
prompt @6;
|
||||||
|
promptRepeat @7;
|
||||||
|
promptDistracted @8;
|
||||||
|
|
||||||
|
# unused, these are reserved for upstream events so we don't collide
|
||||||
|
reserved9 @9;
|
||||||
|
reserved10 @10;
|
||||||
|
reserved11 @11;
|
||||||
|
reserved12 @12;
|
||||||
|
reserved13 @13;
|
||||||
|
reserved14 @14;
|
||||||
|
reserved15 @15;
|
||||||
|
reserved16 @16;
|
||||||
|
reserved17 @17;
|
||||||
|
reserved18 @18;
|
||||||
|
reserved19 @19;
|
||||||
|
reserved20 @20;
|
||||||
|
reserved21 @21;
|
||||||
|
reserved22 @22;
|
||||||
|
reserved23 @23;
|
||||||
|
reserved24 @24;
|
||||||
|
reserved25 @25;
|
||||||
|
reserved26 @26;
|
||||||
|
reserved27 @27;
|
||||||
|
reserved28 @28;
|
||||||
|
reserved29 @29;
|
||||||
|
reserved30 @30;
|
||||||
|
|
||||||
|
promptSingleLow @31;
|
||||||
|
promptSingleHigh @32;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ModelManagerSP @0xaedffd8f31e7b55d {
|
struct ModelManagerSP @0xaedffd8f31e7b55d {
|
||||||
@@ -101,6 +185,13 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
|
|||||||
|
|
||||||
struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
|
struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
|
||||||
dec @0 :DynamicExperimentalControl;
|
dec @0 :DynamicExperimentalControl;
|
||||||
|
longitudinalPlanSource @1 :LongitudinalPlanSource;
|
||||||
|
smartCruiseControl @2 :SmartCruiseControl;
|
||||||
|
speedLimit @3 :SpeedLimit;
|
||||||
|
vTarget @4 :Float32;
|
||||||
|
aTarget @5 :Float32;
|
||||||
|
events @6 :List(OnroadEventSP.Event);
|
||||||
|
e2eAlerts @7 :E2eAlerts;
|
||||||
|
|
||||||
struct DynamicExperimentalControl {
|
struct DynamicExperimentalControl {
|
||||||
state @0 :DynamicExperimentalControlState;
|
state @0 :DynamicExperimentalControlState;
|
||||||
@@ -112,6 +203,97 @@ struct LongitudinalPlanSP @0xf35cc4560bbf6ec2 {
|
|||||||
blended @1;
|
blended @1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SmartCruiseControl {
|
||||||
|
vision @0 :Vision;
|
||||||
|
map @1 :Map;
|
||||||
|
|
||||||
|
struct Vision {
|
||||||
|
state @0 :VisionState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
currentLateralAccel @3 :Float32;
|
||||||
|
maxPredictedLateralAccel @4 :Float32;
|
||||||
|
enabled @5 :Bool;
|
||||||
|
active @6 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Map {
|
||||||
|
state @0 :MapState;
|
||||||
|
vTarget @1 :Float32;
|
||||||
|
aTarget @2 :Float32;
|
||||||
|
enabled @3 :Bool;
|
||||||
|
active @4 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum VisionState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on vision range.
|
||||||
|
entering @2; # A substantial turn is predicted ahead, adapting speed to turn comfort levels.
|
||||||
|
turning @3; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
leaving @4; # Road ahead straightens. Start to allow positive acceleration.
|
||||||
|
overriding @5; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum MapState {
|
||||||
|
disabled @0; # System disabled or inactive.
|
||||||
|
enabled @1; # No predicted substantial turn on map range.
|
||||||
|
turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||||
|
overriding @3; # System overriding with manual control.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SpeedLimit {
|
||||||
|
resolver @0 :Resolver;
|
||||||
|
assist @1 :Assist;
|
||||||
|
|
||||||
|
struct Resolver {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
|
distToSpeedLimit @1 :Float32;
|
||||||
|
source @2 :Source;
|
||||||
|
speedLimitOffset @3 :Float32;
|
||||||
|
speedLimitLast @4 :Float32;
|
||||||
|
speedLimitFinal @5 :Float32;
|
||||||
|
speedLimitFinalLast @6 :Float32;
|
||||||
|
speedLimitValid @7 :Bool;
|
||||||
|
speedLimitLastValid @8 :Bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Assist {
|
||||||
|
state @0 :AssistState;
|
||||||
|
enabled @1 :Bool;
|
||||||
|
active @2 :Bool;
|
||||||
|
vTarget @3 :Float32;
|
||||||
|
aTarget @4 :Float32;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum Source {
|
||||||
|
none @0;
|
||||||
|
car @1;
|
||||||
|
map @2;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum AssistState {
|
||||||
|
disabled @0;
|
||||||
|
inactive @1; # No speed limit set or not enabled by parameter.
|
||||||
|
preActive @2;
|
||||||
|
pending @3; # Awaiting new speed limit.
|
||||||
|
adapting @4; # Reducing speed to match new speed limit.
|
||||||
|
active @5; # Cruising at speed limit.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum LongitudinalPlanSource {
|
||||||
|
cruise @0;
|
||||||
|
sccVision @1;
|
||||||
|
sccMap @2;
|
||||||
|
speedLimitAssist @3;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct E2eAlerts {
|
||||||
|
greenLightAlert @0 :Bool;
|
||||||
|
leadDepartAlert @1 :Bool;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct OnroadEventSP @0xda96579883444c35 {
|
struct OnroadEventSP @0xda96579883444c35 {
|
||||||
@@ -151,12 +333,22 @@ struct OnroadEventSP @0xda96579883444c35 {
|
|||||||
experimentalModeSwitched @14;
|
experimentalModeSwitched @14;
|
||||||
wrongCarModeAlertOnly @15;
|
wrongCarModeAlertOnly @15;
|
||||||
pedalPressedAlertOnly @16;
|
pedalPressedAlertOnly @16;
|
||||||
|
laneTurnLeft @17;
|
||||||
|
laneTurnRight @18;
|
||||||
|
speedLimitPreActive @19;
|
||||||
|
speedLimitActive @20;
|
||||||
|
speedLimitChanged @21;
|
||||||
|
speedLimitPending @22;
|
||||||
|
e2eChime @23;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CarParamsSP @0x80ae746ee2596b11 {
|
struct CarParamsSP @0x80ae746ee2596b11 {
|
||||||
flags @0 :UInt32; # flags for car specific quirks in sunnypilot
|
flags @0 :UInt32; # flags for car specific quirks in sunnypilot
|
||||||
safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags
|
safetyParam @1 : Int16; # flags for sunnypilot's custom safety flags
|
||||||
|
pcmCruiseSpeed @3 :Bool;
|
||||||
|
intelligentCruiseButtonManagementAvailable @4 :Bool;
|
||||||
|
enableGasInterceptor @5 :Bool;
|
||||||
|
|
||||||
neuralNetworkLateralControl @2 :NeuralNetworkLateralControl;
|
neuralNetworkLateralControl @2 :NeuralNetworkLateralControl;
|
||||||
|
|
||||||
@@ -174,10 +366,26 @@ struct CarParamsSP @0x80ae746ee2596b11 {
|
|||||||
struct CarControlSP @0xa5cd762cd951a455 {
|
struct CarControlSP @0xa5cd762cd951a455 {
|
||||||
mads @0 :ModularAssistiveDrivingSystem;
|
mads @0 :ModularAssistiveDrivingSystem;
|
||||||
params @1 :List(Param);
|
params @1 :List(Param);
|
||||||
|
leadOne @2 :LeadData;
|
||||||
|
leadTwo @3 :LeadData;
|
||||||
|
intelligentCruiseButtonManagement @4 :IntelligentCruiseButtonManagement;
|
||||||
|
|
||||||
struct Param {
|
struct Param {
|
||||||
key @0 :Text;
|
key @0 :Text;
|
||||||
value @1 :Text;
|
type @2 :ParamType;
|
||||||
|
value @3 :Data;
|
||||||
|
|
||||||
|
valueDEPRECATED @1 :Text; # The data type change may cause issues with backwards compatibility.
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ParamType {
|
||||||
|
string @0;
|
||||||
|
bool @1;
|
||||||
|
int @2;
|
||||||
|
float @3;
|
||||||
|
time @4;
|
||||||
|
json @5;
|
||||||
|
bytes @6;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -224,6 +432,7 @@ struct BackupManagerSP @0xf98d843bfd7004a3 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
struct CarStateSP @0xb86e6369214c01c8 {
|
struct CarStateSP @0xb86e6369214c01c8 {
|
||||||
|
speedLimit @0 :Float32;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LiveMapDataSP @0xf416ec09499d9d19 {
|
struct LiveMapDataSP @0xf416ec09499d9d19 {
|
||||||
@@ -235,7 +444,14 @@ struct LiveMapDataSP @0xf416ec09499d9d19 {
|
|||||||
roadName @5 :Text;
|
roadName @5 :Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
struct ModelDataV2SP @0xa1680744031fdb2d {
|
||||||
|
laneTurnDirection @0 :TurnDirection;
|
||||||
|
|
||||||
|
enum TurnDirection {
|
||||||
|
none @0;
|
||||||
|
turnLeft @1;
|
||||||
|
turnRight @2;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct CustomReserved10 @0xcb9fd56c7057593a {
|
struct CustomReserved10 @0xcb9fd56c7057593a {
|
||||||
|
|||||||
+31
-14
@@ -127,7 +127,9 @@ struct OnroadEvent @0xc4fa6047f024e718 {
|
|||||||
espActive @90;
|
espActive @90;
|
||||||
personalityChanged @91;
|
personalityChanged @91;
|
||||||
aeb @92;
|
aeb @92;
|
||||||
userFlag @95;
|
userBookmark @95;
|
||||||
|
excessiveActuation @96;
|
||||||
|
audioFeedback @97;
|
||||||
|
|
||||||
soundsUnavailableDEPRECATED @47;
|
soundsUnavailableDEPRECATED @47;
|
||||||
}
|
}
|
||||||
@@ -492,7 +494,6 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
|||||||
gpuTempC @27 :List(Float32);
|
gpuTempC @27 :List(Float32);
|
||||||
dspTempC @49 :Float32;
|
dspTempC @49 :Float32;
|
||||||
memoryTempC @28 :Float32;
|
memoryTempC @28 :Float32;
|
||||||
nvmeTempC @35 :List(Float32);
|
|
||||||
modemTempC @36 :List(Float32);
|
modemTempC @36 :List(Float32);
|
||||||
pmicTempC @39 :List(Float32);
|
pmicTempC @39 :List(Float32);
|
||||||
intakeTempC @46 :Float32;
|
intakeTempC @46 :Float32;
|
||||||
@@ -568,6 +569,7 @@ struct DeviceState @0xa4d8b5af2aa492eb {
|
|||||||
chargingDisabledDEPRECATED @18 :Bool;
|
chargingDisabledDEPRECATED @18 :Bool;
|
||||||
usbOnlineDEPRECATED @12 :Bool;
|
usbOnlineDEPRECATED @12 :Bool;
|
||||||
ambientTempCDEPRECATED @30 :Float32;
|
ambientTempCDEPRECATED @30 :Float32;
|
||||||
|
nvmeTempCDEPRECATED @35 :List(Float32);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PandaState @0xa7649e2575e4591e {
|
struct PandaState @0xa7649e2575e4591e {
|
||||||
@@ -583,9 +585,8 @@ struct PandaState @0xa7649e2575e4591e {
|
|||||||
heartbeatLost @22 :Bool;
|
heartbeatLost @22 :Bool;
|
||||||
interruptLoad @25 :Float32;
|
interruptLoad @25 :Float32;
|
||||||
fanPower @28 :UInt8;
|
fanPower @28 :UInt8;
|
||||||
fanStallCount @34 :UInt8;
|
|
||||||
|
|
||||||
spiChecksumErrorCount @33 :UInt16;
|
spiErrorCount @33 :UInt16;
|
||||||
|
|
||||||
harnessStatus @21 :HarnessStatus;
|
harnessStatus @21 :HarnessStatus;
|
||||||
sbu1Voltage @35 :Float32;
|
sbu1Voltage @35 :Float32;
|
||||||
@@ -712,6 +713,7 @@ struct PandaState @0xa7649e2575e4591e {
|
|||||||
usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerModeDEPRECATED;
|
usbPowerModeDEPRECATED @12 :PeripheralState.UsbPowerModeDEPRECATED;
|
||||||
safetyParamDEPRECATED @20 :Int16;
|
safetyParamDEPRECATED @20 :Int16;
|
||||||
safetyParam2DEPRECATED @26 :UInt32;
|
safetyParam2DEPRECATED @26 :UInt32;
|
||||||
|
fanStallCountDEPRECATED @34 :UInt8;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PeripheralState {
|
struct PeripheralState {
|
||||||
@@ -916,6 +918,8 @@ struct ControlsState @0x97ff69c53601abf1 {
|
|||||||
saturated @7 :Bool;
|
saturated @7 :Bool;
|
||||||
actualLateralAccel @9 :Float32;
|
actualLateralAccel @9 :Float32;
|
||||||
desiredLateralAccel @10 :Float32;
|
desiredLateralAccel @10 :Float32;
|
||||||
|
desiredLateralJerk @11 :Float32;
|
||||||
|
version @12 :Int32;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LateralLQRState {
|
struct LateralLQRState {
|
||||||
@@ -2144,13 +2148,10 @@ struct Joystick {
|
|||||||
struct DriverStateV2 {
|
struct DriverStateV2 {
|
||||||
frameId @0 :UInt32;
|
frameId @0 :UInt32;
|
||||||
modelExecutionTime @1 :Float32;
|
modelExecutionTime @1 :Float32;
|
||||||
dspExecutionTimeDEPRECATED @2 :Float32;
|
|
||||||
gpuExecutionTime @8 :Float32;
|
gpuExecutionTime @8 :Float32;
|
||||||
rawPredictions @3 :Data;
|
rawPredictions @3 :Data;
|
||||||
|
|
||||||
poorVisionProb @4 :Float32;
|
|
||||||
wheelOnRightProb @5 :Float32;
|
wheelOnRightProb @5 :Float32;
|
||||||
|
|
||||||
leftDriverData @6 :DriverData;
|
leftDriverData @6 :DriverData;
|
||||||
rightDriverData @7 :DriverData;
|
rightDriverData @7 :DriverData;
|
||||||
|
|
||||||
@@ -2165,10 +2166,14 @@ struct DriverStateV2 {
|
|||||||
leftBlinkProb @7 :Float32;
|
leftBlinkProb @7 :Float32;
|
||||||
rightBlinkProb @8 :Float32;
|
rightBlinkProb @8 :Float32;
|
||||||
sunglassesProb @9 :Float32;
|
sunglassesProb @9 :Float32;
|
||||||
occludedProb @10 :Float32;
|
phoneProb @13 :Float32;
|
||||||
readyProb @11 :List(Float32);
|
notReadyProbDEPRECATED @12 :List(Float32);
|
||||||
notReadyProb @12 :List(Float32);
|
occludedProbDEPRECATED @10 :Float32;
|
||||||
|
readyProbDEPRECATED @11 :List(Float32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
dspExecutionTimeDEPRECATED @2 :Float32;
|
||||||
|
poorVisionProbDEPRECATED @4 :Float32;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct DriverStateDEPRECATED @0xb83c6cc593ed0a00 {
|
struct DriverStateDEPRECATED @0xb83c6cc593ed0a00 {
|
||||||
@@ -2220,6 +2225,9 @@ struct DriverMonitoringState @0xb83cda094a1da284 {
|
|||||||
hiStdCount @14 :UInt32;
|
hiStdCount @14 :UInt32;
|
||||||
isActiveMode @16 :Bool;
|
isActiveMode @16 :Bool;
|
||||||
isRHD @4 :Bool;
|
isRHD @4 :Bool;
|
||||||
|
uncertainCount @19 :UInt32;
|
||||||
|
phoneProbOffset @20 :Float32;
|
||||||
|
phoneProbValidCount @21 :UInt32;
|
||||||
|
|
||||||
isPreviewDEPRECATED @15 :Bool;
|
isPreviewDEPRECATED @15 :Bool;
|
||||||
rhdCheckedDEPRECATED @5 :Bool;
|
rhdCheckedDEPRECATED @5 :Bool;
|
||||||
@@ -2467,7 +2475,7 @@ struct DebugAlert {
|
|||||||
alertText2 @1 :Text;
|
alertText2 @1 :Text;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct UserFlag {
|
struct UserBookmark @0xfe346a9de48d9b50 {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct SoundPressure @0xdc24138990726023 {
|
struct SoundPressure @0xdc24138990726023 {
|
||||||
@@ -2485,6 +2493,11 @@ struct AudioData {
|
|||||||
sampleRate @1 :UInt32;
|
sampleRate @1 :UInt32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct AudioFeedback {
|
||||||
|
audio @0 :AudioData;
|
||||||
|
blockNum @1 :UInt16;
|
||||||
|
}
|
||||||
|
|
||||||
struct Touch {
|
struct Touch {
|
||||||
sec @0 :Int64;
|
sec @0 :Int64;
|
||||||
usec @1 :Int64;
|
usec @1 :Int64;
|
||||||
@@ -2585,9 +2598,13 @@ struct Event {
|
|||||||
mapRenderState @105: MapRenderState;
|
mapRenderState @105: MapRenderState;
|
||||||
|
|
||||||
# UI services
|
# UI services
|
||||||
userFlag @93 :UserFlag;
|
|
||||||
uiDebug @102 :UIDebug;
|
uiDebug @102 :UIDebug;
|
||||||
|
|
||||||
|
# driving feedback
|
||||||
|
userBookmark @93 :UserBookmark;
|
||||||
|
bookmarkButton @148 :UserBookmark;
|
||||||
|
audioFeedback @149 :AudioFeedback;
|
||||||
|
|
||||||
# *********** debug ***********
|
# *********** debug ***********
|
||||||
testJoystick @52 :Joystick;
|
testJoystick @52 :Joystick;
|
||||||
roadEncodeData @86 :EncodeData;
|
roadEncodeData @86 :EncodeData;
|
||||||
@@ -2620,7 +2637,7 @@ struct Event {
|
|||||||
backupManagerSP @113 :Custom.BackupManagerSP;
|
backupManagerSP @113 :Custom.BackupManagerSP;
|
||||||
carStateSP @114 :Custom.CarStateSP;
|
carStateSP @114 :Custom.CarStateSP;
|
||||||
liveMapDataSP @115 :Custom.LiveMapDataSP;
|
liveMapDataSP @115 :Custom.LiveMapDataSP;
|
||||||
customReserved9 @116 :Custom.CustomReserved9;
|
modelDataV2SP @116 :Custom.ModelDataV2SP;
|
||||||
customReserved10 @136 :Custom.CustomReserved10;
|
customReserved10 @136 :Custom.CustomReserved10;
|
||||||
customReserved11 @137 :Custom.CustomReserved11;
|
customReserved11 @137 :Custom.CustomReserved11;
|
||||||
customReserved12 @138 :Custom.CustomReserved12;
|
customReserved12 @138 :Custom.CustomReserved12;
|
||||||
@@ -2673,7 +2690,7 @@ struct Event {
|
|||||||
lateralPlanDEPRECATED @64 :LateralPlan;
|
lateralPlanDEPRECATED @64 :LateralPlan;
|
||||||
navModelDEPRECATED @104 :NavModelData;
|
navModelDEPRECATED @104 :NavModelData;
|
||||||
uiPlanDEPRECATED @106 :UiPlan;
|
uiPlanDEPRECATED @106 :UiPlan;
|
||||||
liveLocationKalmanDEPRECATED @72 :LiveLocationKalman;
|
liveLocationKalman @72 :LiveLocationKalman;
|
||||||
liveTracksDEPRECATED @16 :List(LiveTracksDEPRECATED);
|
liveTracksDEPRECATED @16 :List(LiveTracksDEPRECATED);
|
||||||
onroadEventsDEPRECATED @68: List(Car.OnroadEventDEPRECATED);
|
onroadEventsDEPRECATED @68: List(Car.OnroadEventDEPRECATED);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ MessageContext message_context;
|
|||||||
struct SubMaster::SubMessage {
|
struct SubMaster::SubMessage {
|
||||||
std::string name;
|
std::string name;
|
||||||
SubSocket *socket = nullptr;
|
SubSocket *socket = nullptr;
|
||||||
int freq = 0;
|
float freq = 0.0f;
|
||||||
bool updated = false, alive = false, valid = false, ignore_alive;
|
bool updated = false, alive = false, valid = false, ignore_alive;
|
||||||
uint64_t rcv_time = 0, rcv_frame = 0;
|
uint64_t rcv_time = 0, rcv_frame = 0;
|
||||||
void *allocated_msg_reader = nullptr;
|
void *allocated_msg_reader = nullptr;
|
||||||
|
|||||||
@@ -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", "gas", "steeringAngleDeg"]
|
fields = ["vEgo", "aEgo", "brake", "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:
|
||||||
@@ -177,8 +177,8 @@ class TestMessaging:
|
|||||||
|
|
||||||
# wait 5 socket timeouts before sending
|
# wait 5 socket timeouts before sending
|
||||||
msg = random_carstate()
|
msg = random_carstate()
|
||||||
delayed_send(sock_timeout*5, pub_sock, msg.to_bytes())
|
|
||||||
start_time = time.monotonic()
|
start_time = time.monotonic()
|
||||||
|
delayed_send(sock_timeout*5, pub_sock, msg.to_bytes())
|
||||||
recvd = messaging.recv_one_retry(sub_sock)
|
recvd = messaging.recv_one_retry(sub_sock)
|
||||||
assert (time.monotonic() - start_time) >= sock_timeout*5
|
assert (time.monotonic() - start_time) >= sock_timeout*5
|
||||||
assert isinstance(recvd, capnp._DynamicStructReader)
|
assert isinstance(recvd, capnp._DynamicStructReader)
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ class TestSubMaster:
|
|||||||
"cameraOdometry": (20, 10),
|
"cameraOdometry": (20, 10),
|
||||||
"liveCalibration": (4, 4),
|
"liveCalibration": (4, 4),
|
||||||
"carParams": (None, None),
|
"carParams": (None, None),
|
||||||
"userFlag": (None, None),
|
"userBookmark": (None, None),
|
||||||
}
|
}
|
||||||
|
|
||||||
for service, (max_freq, min_freq) in checks.items():
|
for service, (max_freq, min_freq) in checks.items():
|
||||||
|
|||||||
+7
-3
@@ -72,9 +72,11 @@ _services: dict[str, tuple] = {
|
|||||||
"navRoute": (True, 0.),
|
"navRoute": (True, 0.),
|
||||||
"navThumbnail": (True, 0.),
|
"navThumbnail": (True, 0.),
|
||||||
"qRoadEncodeIdx": (False, 20.),
|
"qRoadEncodeIdx": (False, 20.),
|
||||||
"userFlag": (True, 0., 1),
|
"userBookmark": (True, 0., 1),
|
||||||
"soundPressure": (True, 10., 10),
|
"soundPressure": (True, 10., 10),
|
||||||
"rawAudioData": (False, 20.),
|
"rawAudioData": (False, 20.),
|
||||||
|
"bookmarkButton": (True, 0., 1),
|
||||||
|
"audioFeedback": (True, 0., 1),
|
||||||
|
|
||||||
# sunnypilot
|
# sunnypilot
|
||||||
"modelManagerSP": (False, 1., 1),
|
"modelManagerSP": (False, 1., 1),
|
||||||
@@ -86,6 +88,8 @@ _services: dict[str, tuple] = {
|
|||||||
"carControlSP": (True, 100., 10),
|
"carControlSP": (True, 100., 10),
|
||||||
"carStateSP": (True, 100., 10),
|
"carStateSP": (True, 100., 10),
|
||||||
"liveMapDataSP": (True, 1., 1),
|
"liveMapDataSP": (True, 1., 1),
|
||||||
|
"modelDataV2SP": (True, 20.),
|
||||||
|
"liveLocationKalman": (True, 20.),
|
||||||
|
|
||||||
# debug
|
# debug
|
||||||
"uiDebug": (True, 0., 1),
|
"uiDebug": (True, 0., 1),
|
||||||
@@ -118,12 +122,12 @@ def build_header():
|
|||||||
h += "#include <map>\n"
|
h += "#include <map>\n"
|
||||||
h += "#include <string>\n"
|
h += "#include <string>\n"
|
||||||
|
|
||||||
h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n"
|
h += "struct service { std::string name; bool should_log; float frequency; int decimation; };\n"
|
||||||
h += "static std::map<std::string, service> services = {\n"
|
h += "static std::map<std::string, service> services = {\n"
|
||||||
for k, v in SERVICE_LIST.items():
|
for k, v in SERVICE_LIST.items():
|
||||||
should_log = "true" if v.should_log else "false"
|
should_log = "true" if v.should_log else "false"
|
||||||
decimation = -1 if v.decimation is None else v.decimation
|
decimation = -1 if v.decimation is None else v.decimation
|
||||||
h += ' { "%s", {"%s", %s, %d, %d}},\n' % \
|
h += ' { "%s", {"%s", %s, %f, %d}},\n' % \
|
||||||
(k, k, should_log, v.frequency, decimation)
|
(k, k, should_log, v.frequency, decimation)
|
||||||
h += "};\n"
|
h += "};\n"
|
||||||
|
|
||||||
|
|||||||
+3
-9
@@ -4,18 +4,12 @@ common_libs = [
|
|||||||
'params.cc',
|
'params.cc',
|
||||||
'swaglog.cc',
|
'swaglog.cc',
|
||||||
'util.cc',
|
'util.cc',
|
||||||
'watchdog.cc',
|
'ratekeeper.cc',
|
||||||
'ratekeeper.cc'
|
|
||||||
]
|
|
||||||
|
|
||||||
_common = env.Library('common', common_libs, LIBS="json11")
|
|
||||||
|
|
||||||
files = [
|
|
||||||
'clutil.cc',
|
'clutil.cc',
|
||||||
]
|
]
|
||||||
|
|
||||||
_gpucommon = env.Library('gpucommon', files)
|
_common = env.Library('common', common_libs, LIBS="json11")
|
||||||
Export('_common', '_gpucommon')
|
Export('_common')
|
||||||
|
|
||||||
if GetOption('extras'):
|
if GetOption('extras'):
|
||||||
env.Program('tests/test_common',
|
env.Program('tests/test_common',
|
||||||
|
|||||||
@@ -14,9 +14,13 @@ class Api:
|
|||||||
def post(self, *args, **kwargs):
|
def post(self, *args, **kwargs):
|
||||||
return self.service.post(*args, **kwargs)
|
return self.service.post(*args, **kwargs)
|
||||||
|
|
||||||
def get_token(self, expiry_hours=1):
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
return self.service.get_token(expiry_hours)
|
return self.service.get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
|
|
||||||
def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
|
def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
|
||||||
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, **params)
|
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, **params)
|
||||||
|
|
||||||
|
|
||||||
|
def get_key_pair():
|
||||||
|
return CommaConnectApi(None).get_key_pair()
|
||||||
|
|||||||
+20
-6
@@ -1,18 +1,22 @@
|
|||||||
import jwt
|
import jwt
|
||||||
|
import os
|
||||||
import requests
|
import requests
|
||||||
import unicodedata
|
import unicodedata
|
||||||
from datetime import datetime, timedelta, UTC
|
from datetime import datetime, timedelta, UTC
|
||||||
from openpilot.system.hardware.hw import Paths
|
from openpilot.system.hardware.hw import Paths
|
||||||
from openpilot.system.version import get_version
|
from openpilot.system.version import get_version
|
||||||
|
|
||||||
|
# name : jwt signature algorithm
|
||||||
|
KEYS = {"id_rsa" : "RS256",
|
||||||
|
"id_ecdsa" : "ES256"}
|
||||||
|
|
||||||
|
|
||||||
class BaseApi:
|
class BaseApi:
|
||||||
def __init__(self, dongle_id, api_host, user_agent="openpilot-"):
|
def __init__(self, dongle_id, api_host, user_agent="openpilot-"):
|
||||||
self.dongle_id = dongle_id
|
self.dongle_id = dongle_id
|
||||||
self.api_host = api_host
|
self.api_host = api_host
|
||||||
self.user_agent = user_agent
|
self.user_agent = user_agent
|
||||||
with open(f'{Paths.persist_root()}/comma/id_rsa') as f:
|
self.jwt_algorithm, self.private_key, _ = self.get_key_pair()
|
||||||
self.private_key = f.read()
|
|
||||||
|
|
||||||
def get(self, *args, **kwargs):
|
def get(self, *args, **kwargs):
|
||||||
return self.request('GET', *args, **kwargs)
|
return self.request('GET', *args, **kwargs)
|
||||||
@@ -23,7 +27,7 @@ class BaseApi:
|
|||||||
def request(self, method, endpoint, timeout=None, access_token=None, **params):
|
def request(self, method, endpoint, timeout=None, access_token=None, **params):
|
||||||
return self.api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
return self.api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
||||||
|
|
||||||
def _get_token(self, expiry_hours=1, **extra_payload):
|
def _get_token(self, payload_extra=None, expiry_hours=1, **extra_payload):
|
||||||
now = datetime.now(UTC).replace(tzinfo=None)
|
now = datetime.now(UTC).replace(tzinfo=None)
|
||||||
payload = {
|
payload = {
|
||||||
'identity': self.dongle_id,
|
'identity': self.dongle_id,
|
||||||
@@ -32,13 +36,15 @@ class BaseApi:
|
|||||||
'exp': now + timedelta(hours=expiry_hours),
|
'exp': now + timedelta(hours=expiry_hours),
|
||||||
**extra_payload
|
**extra_payload
|
||||||
}
|
}
|
||||||
token = jwt.encode(payload, self.private_key, algorithm='RS256')
|
if payload_extra is not None:
|
||||||
|
payload.update(payload_extra)
|
||||||
|
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
|
||||||
if isinstance(token, bytes):
|
if isinstance(token, bytes):
|
||||||
token = token.decode('utf8')
|
token = token.decode('utf8')
|
||||||
return token
|
return token
|
||||||
|
|
||||||
def get_token(self, expiry_hours=1):
|
def get_token(self, payload_extra=None, expiry_hours=1):
|
||||||
return self._get_token(expiry_hours)
|
return self._get_token(payload_extra, expiry_hours)
|
||||||
|
|
||||||
def remove_non_ascii_chars(self, text):
|
def remove_non_ascii_chars(self, text):
|
||||||
normalized_text = unicodedata.normalize('NFD', text)
|
normalized_text = unicodedata.normalize('NFD', text)
|
||||||
@@ -54,3 +60,11 @@ class BaseApi:
|
|||||||
headers['User-Agent'] = self.user_agent + version
|
headers['User-Agent'] = self.user_agent + version
|
||||||
|
|
||||||
return requests.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
|
return requests.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_key_pair():
|
||||||
|
for key in KEYS:
|
||||||
|
if os.path.isfile(Paths.persist_root() + f'/comma/{key}') and os.path.isfile(Paths.persist_root() + f'/comma/{key}.pub'):
|
||||||
|
with open(Paths.persist_root() + f'/comma/{key}') as private, open(Paths.persist_root() + f'/comma/{key}.pub') as public:
|
||||||
|
return KEYS[key], private.read(), public.read()
|
||||||
|
return None, None, None
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
class Conversions:
|
# conversions
|
||||||
|
class CV:
|
||||||
# Speed
|
# Speed
|
||||||
MPH_TO_KPH = 1.609344
|
MPH_TO_KPH = 1.609344
|
||||||
KPH_TO_MPH = 1. / MPH_TO_KPH
|
KPH_TO_MPH = 1. / MPH_TO_KPH
|
||||||
@@ -17,3 +18,6 @@ class Conversions:
|
|||||||
|
|
||||||
# Mass
|
# Mass
|
||||||
LB_TO_KG = 0.453592
|
LB_TO_KG = 0.453592
|
||||||
|
|
||||||
|
|
||||||
|
ACCELERATION_DUE_TO_GRAVITY = 9.81 # m/s^2
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# remove all keys that end in DEPRECATED
|
|
||||||
def strip_deprecated_keys(d):
|
|
||||||
for k in list(d.keys()):
|
|
||||||
if isinstance(k, str):
|
|
||||||
if k.endswith('DEPRECATED'):
|
|
||||||
d.pop(k)
|
|
||||||
elif isinstance(d[k], dict):
|
|
||||||
strip_deprecated_keys(d[k])
|
|
||||||
return d
|
|
||||||
@@ -15,3 +15,20 @@ class FirstOrderFilter:
|
|||||||
self.initialized = True
|
self.initialized = True
|
||||||
self.x = x
|
self.x = x
|
||||||
return self.x
|
return self.x
|
||||||
|
|
||||||
|
|
||||||
|
class BounceFilter(FirstOrderFilter):
|
||||||
|
def __init__(self, x0, rc, dt, initialized=True, bounce=2):
|
||||||
|
self.velocity = FirstOrderFilter(0.0, 0.15, dt)
|
||||||
|
self.bounce = bounce
|
||||||
|
super().__init__(x0, rc, dt, initialized)
|
||||||
|
|
||||||
|
def update(self, x):
|
||||||
|
super().update(x)
|
||||||
|
scale = self.dt / (1.0 / 60.0) # tuned at 60 fps
|
||||||
|
self.velocity.x += (x - self.x) * self.bounce * scale * self.dt
|
||||||
|
self.velocity.update(0.0)
|
||||||
|
if abs(self.velocity.x) < 1e-5:
|
||||||
|
self.velocity.x = 0.0
|
||||||
|
self.x += self.velocity.x
|
||||||
|
return self.x
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
from functools import cache
|
from functools import cache
|
||||||
import subprocess
|
import subprocess
|
||||||
from openpilot.common.run import run_cmd, run_cmd_default
|
from openpilot.common.utils import run_cmd, run_cmd_default
|
||||||
|
|
||||||
|
|
||||||
@cache
|
@cache
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define DEFAULT_MODEL "Tomb Raider 14 (Default)"
|
#define DEFAULT_MODEL "The Cool People (Default)"
|
||||||
|
|||||||
+14
-6
@@ -103,10 +103,10 @@ Params::~Params() {
|
|||||||
assert(queue.empty());
|
assert(queue.empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> Params::allKeys(ParamKeyType type) const {
|
std::vector<std::string> Params::allKeys(ParamKeyFlag flag) const {
|
||||||
std::vector<std::string> ret;
|
std::vector<std::string> ret;
|
||||||
for (auto &p : keys) {
|
for (auto &p : keys) {
|
||||||
if (type == ALL || (p.second & type)) {
|
if (flag == ALL || (p.second.flags & flag)) {
|
||||||
ret.push_back(p.first);
|
ret.push_back(p.first);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -117,8 +117,16 @@ bool Params::checkKey(const std::string &key) {
|
|||||||
return keys.find(key) != keys.end();
|
return keys.find(key) != keys.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ParamKeyFlag Params::getKeyFlag(const std::string &key) {
|
||||||
|
return static_cast<ParamKeyFlag>(keys[key].flags);
|
||||||
|
}
|
||||||
|
|
||||||
ParamKeyType Params::getKeyType(const std::string &key) {
|
ParamKeyType Params::getKeyType(const std::string &key) {
|
||||||
return static_cast<ParamKeyType>(keys[key]);
|
return keys[key].type;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::string> Params::getKeyDefaultValue(const std::string &key) {
|
||||||
|
return keys[key].default_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Params::put(const char* key, const char* value, size_t value_size) {
|
int Params::put(const char* key, const char* value, size_t value_size) {
|
||||||
@@ -197,17 +205,17 @@ std::map<std::string, std::string> Params::readAll() {
|
|||||||
return util::read_files_in_dir(getParamPath());
|
return util::read_files_in_dir(getParamPath());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Params::clearAll(ParamKeyType key_type) {
|
void Params::clearAll(ParamKeyFlag key_flag) {
|
||||||
FileLock file_lock(params_path + "/.lock");
|
FileLock file_lock(params_path + "/.lock");
|
||||||
|
|
||||||
// 1) delete params of key_type
|
// 1) delete params of key_flag
|
||||||
// 2) delete files that are not defined in the keys.
|
// 2) delete files that are not defined in the keys.
|
||||||
if (DIR *d = opendir(getParamPath().c_str())) {
|
if (DIR *d = opendir(getParamPath().c_str())) {
|
||||||
struct dirent *de = NULL;
|
struct dirent *de = NULL;
|
||||||
while ((de = readdir(d))) {
|
while ((de = readdir(d))) {
|
||||||
if (de->d_type != DT_DIR) {
|
if (de->d_type != DT_DIR) {
|
||||||
auto it = keys.find(de->d_name);
|
auto it = keys.find(de->d_name);
|
||||||
if (it == keys.end() || (it->second & key_type)) {
|
if (it == keys.end() || (it->second.flags & key_flag)) {
|
||||||
unlink(getParamPath(de->d_name).c_str());
|
unlink(getParamPath(de->d_name).c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
-4
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <future>
|
#include <future>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <tuple>
|
#include <tuple>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
@@ -9,17 +10,34 @@
|
|||||||
|
|
||||||
#include "common/queue.h"
|
#include "common/queue.h"
|
||||||
|
|
||||||
enum ParamKeyType {
|
enum ParamKeyFlag {
|
||||||
PERSISTENT = 0x02,
|
PERSISTENT = 0x02,
|
||||||
CLEAR_ON_MANAGER_START = 0x04,
|
CLEAR_ON_MANAGER_START = 0x04,
|
||||||
CLEAR_ON_ONROAD_TRANSITION = 0x08,
|
CLEAR_ON_ONROAD_TRANSITION = 0x08,
|
||||||
CLEAR_ON_OFFROAD_TRANSITION = 0x10,
|
CLEAR_ON_OFFROAD_TRANSITION = 0x10,
|
||||||
DONT_LOG = 0x20,
|
DONT_LOG = 0x20,
|
||||||
DEVELOPMENT_ONLY = 0x40,
|
DEVELOPMENT_ONLY = 0x40,
|
||||||
BACKUP = 0x80,
|
CLEAR_ON_IGNITION_ON = 0x80,
|
||||||
|
BACKUP = 0x100,
|
||||||
ALL = 0xFFFFFFFF
|
ALL = 0xFFFFFFFF
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ParamKeyType {
|
||||||
|
STRING = 0, // must be utf-8 decodable
|
||||||
|
BOOL = 1,
|
||||||
|
INT = 2,
|
||||||
|
FLOAT = 3,
|
||||||
|
TIME = 4, // ISO 8601
|
||||||
|
JSON = 5,
|
||||||
|
BYTES = 6
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParamKeyAttributes {
|
||||||
|
uint32_t flags;
|
||||||
|
ParamKeyType type;
|
||||||
|
std::optional<std::string> default_value = std::nullopt;
|
||||||
|
};
|
||||||
|
|
||||||
class Params {
|
class Params {
|
||||||
public:
|
public:
|
||||||
explicit Params(const std::string &path = {});
|
explicit Params(const std::string &path = {});
|
||||||
@@ -28,16 +46,18 @@ public:
|
|||||||
Params(const Params&) = delete;
|
Params(const Params&) = delete;
|
||||||
Params& operator=(const Params&) = delete;
|
Params& operator=(const Params&) = delete;
|
||||||
|
|
||||||
std::vector<std::string> allKeys(ParamKeyType type = ALL) const;
|
std::vector<std::string> allKeys(ParamKeyFlag flag = ALL) const;
|
||||||
bool checkKey(const std::string &key);
|
bool checkKey(const std::string &key);
|
||||||
|
ParamKeyFlag getKeyFlag(const std::string &key);
|
||||||
ParamKeyType getKeyType(const std::string &key);
|
ParamKeyType getKeyType(const std::string &key);
|
||||||
|
std::optional<std::string> getKeyDefaultValue(const std::string &key);
|
||||||
inline std::string getParamPath(const std::string &key = {}) {
|
inline std::string getParamPath(const std::string &key = {}) {
|
||||||
return params_path + params_prefix + (key.empty() ? "" : "/" + key);
|
return params_path + params_prefix + (key.empty() ? "" : "/" + key);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete a value
|
// Delete a value
|
||||||
int remove(const std::string &key);
|
int remove(const std::string &key);
|
||||||
void clearAll(ParamKeyType type);
|
void clearAll(ParamKeyFlag flag);
|
||||||
|
|
||||||
// helpers for reading values
|
// helpers for reading values
|
||||||
std::string get(const std::string &key, bool block = false);
|
std::string get(const std::string &key, bool block = false);
|
||||||
|
|||||||
+2
-1
@@ -1,5 +1,6 @@
|
|||||||
from openpilot.common.params_pyx import Params, ParamKeyType, UnknownKeyName
|
from openpilot.common.params_pyx import Params, ParamKeyFlag, ParamKeyType, UnknownKeyName
|
||||||
assert Params
|
assert Params
|
||||||
|
assert ParamKeyFlag
|
||||||
assert ParamKeyType
|
assert ParamKeyType
|
||||||
assert UnknownKeyName
|
assert UnknownKeyName
|
||||||
|
|
||||||
|
|||||||
+245
-194
@@ -3,217 +3,268 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <unordered_map>
|
#include <unordered_map>
|
||||||
|
|
||||||
inline static std::unordered_map<std::string, uint32_t> keys = {
|
#include "cereal/gen/cpp/log.capnp.h"
|
||||||
{"AccessToken", CLEAR_ON_MANAGER_START | DONT_LOG},
|
|
||||||
{"AdbEnabled", PERSISTENT | BACKUP},
|
inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
|
||||||
{"AlwaysOnDM", PERSISTENT | BACKUP},
|
{"AccessToken", {CLEAR_ON_MANAGER_START | DONT_LOG, STRING}},
|
||||||
{"ApiCache_Device", PERSISTENT},
|
{"AdbEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"ApiCache_FirehoseStats", PERSISTENT},
|
{"AlwaysOnDM", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"AssistNowToken", PERSISTENT},
|
{"ApiCache_Device", {PERSISTENT, STRING}},
|
||||||
{"AthenadPid", PERSISTENT},
|
{"ApiCache_FirehoseStats", {PERSISTENT, JSON}},
|
||||||
{"AthenadUploadQueue", PERSISTENT},
|
{"AssistNowToken", {PERSISTENT, STRING}},
|
||||||
{"AthenadRecentlyViewedRoutes", PERSISTENT},
|
{"AthenadPid", {PERSISTENT, INT}},
|
||||||
{"BootCount", PERSISTENT},
|
{"AthenadUploadQueue", {PERSISTENT, JSON}},
|
||||||
{"CalibrationParams", PERSISTENT},
|
{"AthenadRecentlyViewedRoutes", {PERSISTENT, STRING}},
|
||||||
{"CameraDebugExpGain", CLEAR_ON_MANAGER_START},
|
{"BootCount", {PERSISTENT, INT}},
|
||||||
{"CameraDebugExpTime", CLEAR_ON_MANAGER_START},
|
{"CalibrationParams", {PERSISTENT, BYTES}},
|
||||||
{"CarBatteryCapacity", PERSISTENT},
|
{"CameraDebugExpGain", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"CarParams", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"CameraDebugExpTime", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"CarParamsCache", CLEAR_ON_MANAGER_START},
|
{"CarBatteryCapacity", {PERSISTENT, INT}},
|
||||||
{"CarParamsPersistent", PERSISTENT},
|
{"CarParams", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
|
||||||
{"CarParamsPrevRoute", PERSISTENT},
|
{"CarParamsCache", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
{"CompletedTrainingVersion", PERSISTENT},
|
{"CarParamsPersistent", {PERSISTENT, BYTES}},
|
||||||
{"ControlsReady", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"CarParamsPrevRoute", {PERSISTENT, BYTES}},
|
||||||
{"CurrentBootlog", PERSISTENT},
|
{"CompletedTrainingVersion", {PERSISTENT, STRING, "0"}},
|
||||||
{"CurrentRoute", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"ControlsReady", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"DisableLogging", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"CurrentBootlog", {PERSISTENT, STRING}},
|
||||||
{"DisablePowerDown", PERSISTENT | BACKUP},
|
{"CurrentRoute", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
{"DisableUpdates", PERSISTENT | BACKUP},
|
{"DisableLogging", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"DisengageOnAccelerator", PERSISTENT | BACKUP},
|
{"DisablePowerDown", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"DongleId", PERSISTENT},
|
{"DisableUpdates", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DoReboot", CLEAR_ON_MANAGER_START},
|
{"DisengageOnAccelerator", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"DoShutdown", CLEAR_ON_MANAGER_START},
|
{"DongleId", {PERSISTENT, STRING}},
|
||||||
{"DoUninstall", CLEAR_ON_MANAGER_START},
|
{"DoReboot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"AlphaLongitudinalEnabled", PERSISTENT | DEVELOPMENT_ONLY | BACKUP},
|
{"DoShutdown", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"ExperimentalMode", PERSISTENT | BACKUP},
|
{"DoUninstall", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"ExperimentalModeConfirmed", PERSISTENT | BACKUP},
|
{"DriverTooDistracted", {CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON, BOOL}},
|
||||||
{"FirmwareQueryDone", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"AlphaLongitudinalEnabled", {PERSISTENT | DEVELOPMENT_ONLY | BACKUP, BOOL}},
|
||||||
{"ForcePowerDown", PERSISTENT},
|
{"ExperimentalMode", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"GitBranch", PERSISTENT},
|
{"ExperimentalModeConfirmed", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"GitCommit", PERSISTENT},
|
{"FirmwareQueryDone", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"GitCommitDate", PERSISTENT},
|
{"ForcePowerDown", {PERSISTENT, BOOL}},
|
||||||
{"GitDiff", PERSISTENT},
|
{"GitBranch", {PERSISTENT, STRING}},
|
||||||
{"GithubSshKeys", PERSISTENT | BACKUP},
|
{"GitCommit", {PERSISTENT, STRING}},
|
||||||
{"GithubUsername", PERSISTENT | BACKUP},
|
{"GitCommitDate", {PERSISTENT, STRING}},
|
||||||
{"GitRemote", PERSISTENT},
|
{"GitDiff", {PERSISTENT, STRING}},
|
||||||
{"GsmApn", PERSISTENT | BACKUP},
|
{"GithubSshKeys", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GsmMetered", PERSISTENT | BACKUP},
|
{"GithubUsername", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"GsmRoaming", PERSISTENT | BACKUP},
|
{"GitRemote", {PERSISTENT, STRING}},
|
||||||
{"HardwareSerial", PERSISTENT},
|
{"GsmApn", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"HasAcceptedTerms", PERSISTENT},
|
{"GsmMetered", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"InstallDate", PERSISTENT},
|
{"GsmRoaming", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsDriverViewEnabled", CLEAR_ON_MANAGER_START},
|
{"HardwareSerial", {PERSISTENT, STRING}},
|
||||||
{"IsEngaged", PERSISTENT},
|
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
|
||||||
{"IsLdwEnabled", PERSISTENT | BACKUP},
|
{"InstallDate", {PERSISTENT, TIME}},
|
||||||
{"IsMetric", PERSISTENT | BACKUP},
|
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsOffroad", CLEAR_ON_MANAGER_START},
|
{"IsEngaged", {PERSISTENT, BOOL}},
|
||||||
{"IsOnroad", PERSISTENT},
|
{"IsLdwEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsRhdDetected", PERSISTENT},
|
{"IsMetric", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsReleaseBranch", CLEAR_ON_MANAGER_START},
|
{"IsOffroad", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"IsTakingSnapshot", CLEAR_ON_MANAGER_START},
|
{"IsOnroad", {PERSISTENT, BOOL}},
|
||||||
{"IsTestedBranch", CLEAR_ON_MANAGER_START},
|
{"IsRhdDetected", {PERSISTENT, BOOL}},
|
||||||
{"JoystickDebugMode", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"IsReleaseBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"LanguageSetting", PERSISTENT | BACKUP},
|
{"IsTakingSnapshot", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"LastAthenaPingTime", CLEAR_ON_MANAGER_START},
|
{"IsTestedBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"LastGPSPosition", PERSISTENT},
|
{"JoystickDebugMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"LastManagerExitReason", CLEAR_ON_MANAGER_START},
|
{"LanguageSetting", {PERSISTENT | BACKUP, STRING, "en"}},
|
||||||
{"LastOffroadStatusPacket", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"LastAthenaPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"LastPowerDropDetected", CLEAR_ON_MANAGER_START},
|
{"LastGPSPosition", {PERSISTENT, STRING}},
|
||||||
{"LastUpdateException", CLEAR_ON_MANAGER_START},
|
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LastUpdateTime", PERSISTENT},
|
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
|
||||||
{"LiveDelay", PERSISTENT | BACKUP},
|
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LiveParameters", PERSISTENT},
|
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"LiveParametersV2", PERSISTENT},
|
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"LiveTorqueParameters", PERSISTENT | DONT_LOG},
|
{"LastUpdateTime", {PERSISTENT, TIME}},
|
||||||
{"LocationFilterInitialState", PERSISTENT},
|
{"LastUpdateUptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
{"LongitudinalManeuverMode", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"LiveDelay", {PERSISTENT | BACKUP, BYTES}},
|
||||||
{"LongitudinalPersonality", PERSISTENT | BACKUP},
|
{"LiveParameters", {PERSISTENT, JSON}},
|
||||||
{"NetworkMetered", PERSISTENT | BACKUP},
|
{"LiveParametersV2", {PERSISTENT, BYTES}},
|
||||||
{"ObdMultiplexingChanged", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"LiveTorqueParameters", {PERSISTENT | DONT_LOG, BYTES}},
|
||||||
{"ObdMultiplexingEnabled", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"LocationFilterInitialState", {PERSISTENT, BYTES}},
|
||||||
{"Offroad_BadNvme", CLEAR_ON_MANAGER_START},
|
{"LongitudinalManeuverMode", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"Offroad_CarUnrecognized", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"LongitudinalPersonality", {PERSISTENT | BACKUP, INT, std::to_string(static_cast<int>(cereal::LongitudinalPersonality::STANDARD))}},
|
||||||
{"Offroad_ConnectivityNeeded", CLEAR_ON_MANAGER_START},
|
{"NetworkMetered", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"Offroad_ConnectivityNeededPrompt", CLEAR_ON_MANAGER_START},
|
{"ObdMultiplexingChanged", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"Offroad_IsTakingSnapshot", CLEAR_ON_MANAGER_START},
|
{"ObdMultiplexingEnabled", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"Offroad_NeosUpdate", CLEAR_ON_MANAGER_START},
|
{"Offroad_CarUnrecognized", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_NoFirmware", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"Offroad_ConnectivityNeeded", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_Recalibration", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"Offroad_ConnectivityNeededPrompt", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_StorageMissing", CLEAR_ON_MANAGER_START},
|
{"Offroad_ExcessiveActuation", {PERSISTENT, JSON}},
|
||||||
{"Offroad_TemperatureTooHigh", CLEAR_ON_MANAGER_START},
|
{"Offroad_IsTakingSnapshot", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UnofficialHardware", CLEAR_ON_MANAGER_START},
|
{"Offroad_NeosUpdate", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"Offroad_UpdateFailed", CLEAR_ON_MANAGER_START},
|
{"Offroad_NoFirmware", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"OnroadCycleRequested", CLEAR_ON_MANAGER_START},
|
{"Offroad_Recalibration", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"OpenpilotEnabledToggle", PERSISTENT | BACKUP},
|
{"Offroad_TemperatureTooHigh", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"Offroad_UnregisteredHardware", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"PandaSomResetTriggered", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"Offroad_UpdateFailed", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"PandaSignatures", CLEAR_ON_MANAGER_START},
|
{"Offroad_DriverMonitoringUncertain", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"PrimeType", PERSISTENT},
|
{"OnroadCycleRequested", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"RecordAudio", PERSISTENT | BACKUP},
|
{"OpenpilotEnabledToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"RecordFront", PERSISTENT | BACKUP},
|
{"PandaHeartbeatLost", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"RecordFrontLock", PERSISTENT}, // for the internal fleet
|
{"PandaSomResetTriggered", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"SecOCKey", PERSISTENT | DONT_LOG | BACKUP},
|
{"PandaSignatures", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
{"RouteCount", PERSISTENT},
|
{"PrimeType", {PERSISTENT, INT}},
|
||||||
{"SnoozeUpdate", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"RecordAudio", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"SshEnabled", PERSISTENT | BACKUP},
|
{"RecordAudioFeedback", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"TermsVersion", PERSISTENT},
|
{"RecordFront", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"TrainingVersion", PERSISTENT},
|
{"RecordFrontLock", {PERSISTENT, BOOL}}, // for the internal fleet
|
||||||
{"UbloxAvailable", PERSISTENT},
|
{"SecOCKey", {PERSISTENT | DONT_LOG | BACKUP, STRING}},
|
||||||
{"UpdateAvailable", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"ShowDebugInfo", {PERSISTENT, BOOL}},
|
||||||
{"UpdateFailedCount", CLEAR_ON_MANAGER_START},
|
{"RouteCount", {PERSISTENT, INT, "0"}},
|
||||||
{"UpdaterAvailableBranches", PERSISTENT},
|
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
|
||||||
{"UpdaterCurrentDescription", CLEAR_ON_MANAGER_START},
|
{"SshEnabled", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"UpdaterCurrentReleaseNotes", CLEAR_ON_MANAGER_START},
|
{"TermsVersion", {PERSISTENT, STRING}},
|
||||||
{"UpdaterFetchAvailable", CLEAR_ON_MANAGER_START},
|
{"TrainingVersion", {PERSISTENT, STRING}},
|
||||||
{"UpdaterNewDescription", CLEAR_ON_MANAGER_START},
|
{"UbloxAvailable", {PERSISTENT, BOOL}},
|
||||||
{"UpdaterNewReleaseNotes", CLEAR_ON_MANAGER_START},
|
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
|
||||||
{"UpdaterState", CLEAR_ON_MANAGER_START},
|
{"UpdateFailedCount", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"UpdaterTargetBranch", CLEAR_ON_MANAGER_START},
|
{"UpdaterAvailableBranches", {PERSISTENT, STRING}},
|
||||||
{"UpdaterLastFetchTime", PERSISTENT},
|
{"UpdaterCurrentDescription", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
{"Version", PERSISTENT},
|
{"UpdaterCurrentReleaseNotes", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
|
{"UpdaterFetchAvailable", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"UpdaterNewDescription", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
|
{"UpdaterNewReleaseNotes", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
|
{"UpdaterState", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
|
{"UpdaterTargetBranch", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
|
{"UpdaterLastFetchTime", {PERSISTENT, TIME}},
|
||||||
|
{"UptimeOffroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"UptimeOnroad", {PERSISTENT, FLOAT, "0.0"}},
|
||||||
|
{"Version", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
// --- sunnypilot params --- //
|
// --- sunnypilot params --- //
|
||||||
{"ApiCache_DriveStats", PERSISTENT},
|
{"ApiCache_DriveStats", {PERSISTENT, JSON}},
|
||||||
{"AutoLaneChangeBsmDelay", PERSISTENT | BACKUP},
|
{"AutoLaneChangeBsmDelay", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"AutoLaneChangeTimer", PERSISTENT | BACKUP},
|
{"AutoLaneChangeTimer", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"BlinkerMinLateralControlSpeed", PERSISTENT | BACKUP},
|
{"BlinkerMinLateralControlSpeed", {PERSISTENT | BACKUP, INT, "20"}}, // MPH or km/h
|
||||||
{"BlinkerPauseLateralControl", PERSISTENT | BACKUP},
|
{"BlinkerPauseLateralControl", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"Brightness", PERSISTENT | BACKUP},
|
{"Brightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"CarParamsSP", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"CarParamsSP", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
|
||||||
{"CarParamsSPCache", CLEAR_ON_MANAGER_START},
|
{"CarParamsSPCache", {CLEAR_ON_MANAGER_START, BYTES}},
|
||||||
{"CarParamsSPPersistent", PERSISTENT},
|
{"CarParamsSPPersistent", {PERSISTENT, BYTES}},
|
||||||
{"CarPlatformBundle", PERSISTENT | BACKUP},
|
{"CarPlatformBundle", {PERSISTENT | BACKUP, JSON}},
|
||||||
{"ChevronInfo", PERSISTENT | BACKUP},
|
{"ChevronInfo", {PERSISTENT | BACKUP, INT, "4"}},
|
||||||
{"CustomAccIncrementsEnabled", PERSISTENT | BACKUP},
|
{"CustomAccIncrementsEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"CustomAccLongPressIncrement", PERSISTENT | BACKUP},
|
{"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
|
||||||
{"CustomAccShortPressIncrement", PERSISTENT | BACKUP},
|
{"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
{"DeviceBootMode", PERSISTENT | BACKUP},
|
{"DeviceBootMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"EnableGithubRunner", PERSISTENT | BACKUP},
|
{"DevUIInfo", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"InteractivityTimeout", PERSISTENT | BACKUP},
|
{"EnableCopyparty", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"IsDevelopmentBranch", CLEAR_ON_MANAGER_START},
|
{"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"MaxTimeOffroad", PERSISTENT | BACKUP},
|
{"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"ModelRunnerTypeCache", CLEAR_ON_ONROAD_TRANSITION},
|
{"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
|
||||||
{"OffroadMode", CLEAR_ON_MANAGER_START},
|
{"HideVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"QuickBootToggle", PERSISTENT | BACKUP},
|
{"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}},
|
||||||
{"QuietMode", PERSISTENT | BACKUP},
|
{"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"ShowAdvancedControls", PERSISTENT | BACKUP},
|
{"IsDevelopmentBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"IsReleaseSpBranch", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"LastGPSPositionLLK", {PERSISTENT, STRING}},
|
||||||
|
{"LeadDepartAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"MaxTimeOffroad", {PERSISTENT | BACKUP, INT, "1800"}},
|
||||||
|
{"ModelRunnerTypeCache", {CLEAR_ON_ONROAD_TRANSITION, INT}},
|
||||||
|
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
|
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"OnroadScreenOffControl", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
|
||||||
|
{"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TrueVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
// MADS params
|
// MADS params
|
||||||
{"Mads", PERSISTENT | BACKUP},
|
{"Mads", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"MadsMainCruiseAllowed", PERSISTENT | BACKUP},
|
{"MadsMainCruiseAllowed", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"MadsSteeringMode", PERSISTENT | BACKUP},
|
{"MadsSteeringMode", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"MadsUnifiedEngagementMode", PERSISTENT | BACKUP},
|
{"MadsUnifiedEngagementMode", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
|
|
||||||
// Model Manager params
|
// Model Manager params
|
||||||
{"ModelManager_ActiveBundle", PERSISTENT},
|
{"ModelManager_ActiveBundle", {PERSISTENT, JSON}},
|
||||||
{"ModelManager_ClearCache", CLEAR_ON_MANAGER_START},
|
{"ModelManager_ClearCache", {CLEAR_ON_MANAGER_START, BOOL}},
|
||||||
{"ModelManager_DownloadIndex", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
{"ModelManager_DownloadIndex", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, INT, "0"}},
|
||||||
{"ModelManager_LastSyncTime", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
{"ModelManager_Favs", {PERSISTENT | BACKUP, STRING}},
|
||||||
{"ModelManager_ModelsCache", PERSISTENT | BACKUP},
|
{"ModelManager_LastSyncTime", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, INT, "0"}},
|
||||||
|
{"ModelManager_ModelsCache", {PERSISTENT | BACKUP, JSON}},
|
||||||
|
|
||||||
|
// Navigation params
|
||||||
|
{"MapboxToken", {PERSISTENT | BACKUP, STRING}},
|
||||||
|
{"MapboxSettings", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
|
{"MapboxRoute", {CLEAR_ON_MANAGER_START, STRING}},
|
||||||
|
|
||||||
// Neural Network Lateral Control
|
// Neural Network Lateral Control
|
||||||
{"NeuralNetworkLateralControl", PERSISTENT | BACKUP},
|
{"NeuralNetworkLateralControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
// sunnylink params
|
// sunnylink params
|
||||||
{"EnableSunnylinkUploader", PERSISTENT | BACKUP},
|
{"EnableSunnylinkUploader", {PERSISTENT | BACKUP, BOOL}},
|
||||||
{"LastSunnylinkPingTime", CLEAR_ON_MANAGER_START},
|
{"LastSunnylinkPingTime", {CLEAR_ON_MANAGER_START, INT}},
|
||||||
{"SunnylinkCache_Roles", PERSISTENT},
|
{"SunnylinkCache_Roles", {PERSISTENT, STRING}},
|
||||||
{"SunnylinkCache_Users", PERSISTENT},
|
{"SunnylinkCache_Users", {PERSISTENT, STRING}},
|
||||||
{"SunnylinkDongleId", PERSISTENT},
|
{"SunnylinkDongleId", {PERSISTENT, STRING}},
|
||||||
{"SunnylinkdPid", PERSISTENT},
|
{"SunnylinkdPid", {PERSISTENT, INT}},
|
||||||
{"SunnylinkEnabled", PERSISTENT},
|
{"SunnylinkEnabled", {PERSISTENT, BOOL, "1"}},
|
||||||
|
{"SunnylinkTempFault", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL, "0"}},
|
||||||
|
|
||||||
// Backup Manager params
|
// Backup Manager params
|
||||||
{"BackupManager_CreateBackup", PERSISTENT},
|
{"BackupManager_CreateBackup", {PERSISTENT, BOOL}},
|
||||||
{"BackupManager_RestoreVersion", PERSISTENT},
|
{"BackupManager_RestoreVersion", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
// sunnypilot car specific params
|
// sunnypilot car specific params
|
||||||
{"HyundaiLongitudinalTuning", PERSISTENT | BACKUP},
|
{"HyundaiLongitudinalTuning", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
|
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
{"DynamicExperimentalControl", PERSISTENT | BACKUP},
|
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
{"BlindSpot", PERSISTENT | BACKUP},
|
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
// model panel params
|
// sunnypilot model params
|
||||||
{"LagdToggle", PERSISTENT | BACKUP},
|
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
|
||||||
{"LagdToggleDesc", PERSISTENT},
|
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
|
||||||
{"LagdToggledelay", PERSISTENT | BACKUP},
|
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
|
||||||
|
{"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
|
||||||
|
|
||||||
// mapd
|
// mapd
|
||||||
{"MapAdvisorySpeedLimit", CLEAR_ON_ONROAD_TRANSITION},
|
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
|
||||||
{"MapdVersion", PERSISTENT},
|
{"MapdVersion", {PERSISTENT, STRING}},
|
||||||
{"MapSpeedLimit", CLEAR_ON_ONROAD_TRANSITION},
|
{"MapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT, "0.0"}},
|
||||||
{"NextMapSpeedLimit", CLEAR_ON_ONROAD_TRANSITION},
|
{"NextMapSpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, JSON}},
|
||||||
{"Offroad_OSMUpdateRequired", CLEAR_ON_MANAGER_START},
|
{"Offroad_OSMUpdateRequired", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"OsmDbUpdatesCheck", CLEAR_ON_MANAGER_START}, // mapd database update happens with device ON, reset on boot
|
{"OsmDbUpdatesCheck", {CLEAR_ON_MANAGER_START, BOOL}}, // mapd database update happens with device ON, reset on boot
|
||||||
{"OSMDownloadBounds", PERSISTENT},
|
{"OSMDownloadBounds", {PERSISTENT, STRING}},
|
||||||
{"OsmDownloadedDate", PERSISTENT},
|
{"OsmDownloadedDate", {PERSISTENT, STRING, "0.0"}},
|
||||||
{"OSMDownloadLocations", PERSISTENT},
|
{"OSMDownloadLocations", {PERSISTENT, JSON}},
|
||||||
{"OSMDownloadProgress", CLEAR_ON_MANAGER_START},
|
{"OSMDownloadProgress", {CLEAR_ON_MANAGER_START, JSON}},
|
||||||
{"OsmLocal", PERSISTENT},
|
{"OsmLocal", {PERSISTENT, BOOL}},
|
||||||
{"OsmLocationName", PERSISTENT},
|
{"OsmLocationName", {PERSISTENT, STRING}},
|
||||||
{"OsmLocationTitle", PERSISTENT},
|
{"OsmLocationTitle", {PERSISTENT, STRING}},
|
||||||
{"OsmLocationUrl", PERSISTENT},
|
{"OsmLocationUrl", {PERSISTENT, STRING}},
|
||||||
{"OsmStateName", PERSISTENT},
|
{"OsmStateName", {PERSISTENT, STRING, "All"}},
|
||||||
{"OsmStateTitle", PERSISTENT},
|
{"OsmStateTitle", {PERSISTENT, STRING}},
|
||||||
{"OsmWayTest", PERSISTENT},
|
{"OsmWayTest", {PERSISTENT, STRING}},
|
||||||
{"RoadName", CLEAR_ON_ONROAD_TRANSITION},
|
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
|
{"RoadNameToggle", {PERSISTENT, STRING}},
|
||||||
|
|
||||||
// Tuning keys
|
// Speed Limit
|
||||||
{"EnableHkgTuningAngleSmoothingFactor", PERSISTENT | BACKUP},
|
{"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}},
|
||||||
{"HkgTuningAngleMinTorqueReductionGain", PERSISTENT | BACKUP},
|
{"SpeedLimitOffsetType", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"HkgTuningAngleMaxTorqueReductionGain", PERSISTENT | BACKUP},
|
{"SpeedLimitPolicy", {PERSISTENT | BACKUP, INT, "3"}},
|
||||||
{"HkgTuningAngleActiveTorqueReductionGain", PERSISTENT | BACKUP},
|
{"SpeedLimitValueOffset", {PERSISTENT | BACKUP, INT, "0"}},
|
||||||
{"HkgTuningOverridingCycles", PERSISTENT | BACKUP},
|
|
||||||
{"HkgAngleLiveTuning", CLEAR_ON_MANAGER_START}
|
// Smart Cruise Control
|
||||||
|
{"MapTargetVelocities", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
|
||||||
|
{"SmartCruiseControlMap", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"SmartCruiseControlVision", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
|
||||||
|
// Torque lateral control custom params
|
||||||
|
{"CustomTorqueParams", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"EnforceTorqueControl", {PERSISTENT | BACKUP, BOOL}},
|
||||||
|
{"LiveTorqueParamsToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"LiveTorqueParamsRelaxedToggle", {PERSISTENT | BACKUP , BOOL}},
|
||||||
|
{"TorqueParamsOverrideEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
|
||||||
|
{"TorqueParamsOverrideFriction", {PERSISTENT | BACKUP, FLOAT, "0.1"}},
|
||||||
|
{"TorqueParamsOverrideLatAccelFactor", {PERSISTENT | BACKUP, FLOAT, "2.5"}},
|
||||||
};
|
};
|
||||||
|
|||||||
+86
-13
@@ -1,19 +1,35 @@
|
|||||||
# distutils: language = c++
|
# distutils: language = c++
|
||||||
# cython: language_level = 3
|
# cython: language_level = 3
|
||||||
|
import builtins
|
||||||
|
import datetime
|
||||||
|
import json
|
||||||
from libcpp cimport bool
|
from libcpp cimport bool
|
||||||
from libcpp.string cimport string
|
from libcpp.string cimport string
|
||||||
from libcpp.vector cimport vector
|
from libcpp.vector cimport vector
|
||||||
|
from libcpp.optional cimport optional
|
||||||
|
|
||||||
|
from openpilot.common.swaglog import cloudlog
|
||||||
|
|
||||||
cdef extern from "common/params.h":
|
cdef extern from "common/params.h":
|
||||||
cpdef enum ParamKeyType:
|
cpdef enum ParamKeyFlag:
|
||||||
PERSISTENT
|
PERSISTENT
|
||||||
CLEAR_ON_MANAGER_START
|
CLEAR_ON_MANAGER_START
|
||||||
CLEAR_ON_ONROAD_TRANSITION
|
CLEAR_ON_ONROAD_TRANSITION
|
||||||
CLEAR_ON_OFFROAD_TRANSITION
|
CLEAR_ON_OFFROAD_TRANSITION
|
||||||
DEVELOPMENT_ONLY
|
DEVELOPMENT_ONLY
|
||||||
|
CLEAR_ON_IGNITION_ON
|
||||||
BACKUP
|
BACKUP
|
||||||
ALL
|
ALL
|
||||||
|
|
||||||
|
cpdef enum ParamKeyType:
|
||||||
|
STRING
|
||||||
|
BOOL
|
||||||
|
INT
|
||||||
|
FLOAT
|
||||||
|
TIME
|
||||||
|
JSON
|
||||||
|
BYTES
|
||||||
|
|
||||||
cdef cppclass c_Params "Params":
|
cdef cppclass c_Params "Params":
|
||||||
c_Params(string) except + nogil
|
c_Params(string) except + nogil
|
||||||
string get(string, bool) nogil
|
string get(string, bool) nogil
|
||||||
@@ -24,10 +40,31 @@ cdef extern from "common/params.h":
|
|||||||
void putBoolNonBlocking(string, bool) nogil
|
void putBoolNonBlocking(string, bool) nogil
|
||||||
int putBool(string, bool) nogil
|
int putBool(string, bool) nogil
|
||||||
bool checkKey(string) nogil
|
bool checkKey(string) nogil
|
||||||
|
ParamKeyType getKeyType(string) nogil
|
||||||
|
optional[string] getKeyDefaultValue(string) nogil
|
||||||
string getParamPath(string) nogil
|
string getParamPath(string) nogil
|
||||||
void clearAll(ParamKeyType)
|
void clearAll(ParamKeyFlag)
|
||||||
vector[string] allKeys(ParamKeyType)
|
vector[string] allKeys(ParamKeyFlag)
|
||||||
|
|
||||||
|
PYTHON_2_CPP = {
|
||||||
|
(str, STRING): lambda v: v,
|
||||||
|
(builtins.bool, BOOL): lambda v: "1" if v else "0",
|
||||||
|
(int, INT): str,
|
||||||
|
(float, FLOAT): str,
|
||||||
|
(datetime.datetime, TIME): lambda v: v.isoformat(),
|
||||||
|
(dict, JSON): json.dumps,
|
||||||
|
(list, JSON): json.dumps,
|
||||||
|
(bytes, BYTES): lambda v: v,
|
||||||
|
}
|
||||||
|
CPP_2_PYTHON = {
|
||||||
|
STRING: lambda v: v.decode("utf-8"),
|
||||||
|
BOOL: lambda v: v == b"1",
|
||||||
|
INT: int,
|
||||||
|
FLOAT: float,
|
||||||
|
TIME: lambda v: datetime.datetime.fromisoformat(v.decode("utf-8")),
|
||||||
|
JSON: json.loads,
|
||||||
|
BYTES: lambda v: v,
|
||||||
|
}
|
||||||
|
|
||||||
def ensure_bytes(v):
|
def ensure_bytes(v):
|
||||||
return v.encode() if isinstance(v, str) else v
|
return v.encode() if isinstance(v, str) else v
|
||||||
@@ -51,8 +88,8 @@ cdef class Params:
|
|||||||
def __dealloc__(self):
|
def __dealloc__(self):
|
||||||
del self.p
|
del self.p
|
||||||
|
|
||||||
def clear_all(self, tx_type=ParamKeyType.ALL):
|
def clear_all(self, tx_flag=ParamKeyFlag.ALL):
|
||||||
self.p.clearAll(tx_type)
|
self.p.clearAll(tx_flag)
|
||||||
|
|
||||||
def check_key(self, key):
|
def check_key(self, key):
|
||||||
key = ensure_bytes(key)
|
key = ensure_bytes(key)
|
||||||
@@ -60,21 +97,38 @@ cdef class Params:
|
|||||||
raise UnknownKeyName(key)
|
raise UnknownKeyName(key)
|
||||||
return key
|
return key
|
||||||
|
|
||||||
def get(self, key, bool block=False, encoding=None):
|
def python2cpp(self, proposed_type, expected_type, value, key):
|
||||||
|
cast = PYTHON_2_CPP.get((proposed_type, expected_type))
|
||||||
|
if cast:
|
||||||
|
return cast(value)
|
||||||
|
raise TypeError(f"Type mismatch while writing param {key}: {proposed_type=} {expected_type=} {value=}")
|
||||||
|
|
||||||
|
def _cpp2python(self, t, value, default, key):
|
||||||
|
if value is None:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return CPP_2_PYTHON[t](value)
|
||||||
|
except (KeyError, TypeError, ValueError):
|
||||||
|
cloudlog.warning(f"Failed to cast param {key} with {value=} from type {t=}")
|
||||||
|
return self._cpp2python(t, default, None, key)
|
||||||
|
|
||||||
|
def get(self, key, bool block=False, bool return_default=False):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
|
cdef optional[string] default = self.p.getKeyDefaultValue(k)
|
||||||
cdef string val
|
cdef string val
|
||||||
with nogil:
|
with nogil:
|
||||||
val = self.p.get(k, block)
|
val = self.p.get(k, block)
|
||||||
|
|
||||||
|
default_val = (default.value() if default.has_value() else None) if return_default else None
|
||||||
if val == b"":
|
if val == b"":
|
||||||
if block:
|
if block:
|
||||||
# If we got no value while running in blocked mode
|
# If we got no value while running in blocked mode
|
||||||
# it means we got an interrupt while waiting
|
# it means we got an interrupt while waiting
|
||||||
raise KeyboardInterrupt
|
raise KeyboardInterrupt
|
||||||
else:
|
else:
|
||||||
return None
|
return self._cpp2python(t, default_val, None, key)
|
||||||
|
return self._cpp2python(t, val, default_val, key)
|
||||||
return val if encoding is None else val.decode(encoding)
|
|
||||||
|
|
||||||
def get_bool(self, key, bool block=False):
|
def get_bool(self, key, bool block=False):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
@@ -83,6 +137,11 @@ cdef class Params:
|
|||||||
r = self.p.getBool(k, block)
|
r = self.p.getBool(k, block)
|
||||||
return r
|
return r
|
||||||
|
|
||||||
|
def _put_cast(self, key, dat):
|
||||||
|
cdef string k = self.check_key(key)
|
||||||
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
|
return ensure_bytes(self.python2cpp(type(dat), t, dat, key))
|
||||||
|
|
||||||
def put(self, key, dat):
|
def put(self, key, dat):
|
||||||
"""
|
"""
|
||||||
Warning: This function blocks until the param is written to disk!
|
Warning: This function blocks until the param is written to disk!
|
||||||
@@ -91,7 +150,7 @@ cdef class Params:
|
|||||||
in general try to avoid writing params as much as possible.
|
in general try to avoid writing params as much as possible.
|
||||||
"""
|
"""
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
cdef string dat_bytes = ensure_bytes(dat)
|
cdef string dat_bytes = self._put_cast(key, dat)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.put(k, dat_bytes)
|
self.p.put(k, dat_bytes)
|
||||||
|
|
||||||
@@ -102,7 +161,7 @@ cdef class Params:
|
|||||||
|
|
||||||
def put_nonblocking(self, key, dat):
|
def put_nonblocking(self, key, dat):
|
||||||
cdef string k = self.check_key(key)
|
cdef string k = self.check_key(key)
|
||||||
cdef string dat_bytes = ensure_bytes(dat)
|
cdef string dat_bytes = self._put_cast(key, dat)
|
||||||
with nogil:
|
with nogil:
|
||||||
self.p.putNonBlocking(k, dat_bytes)
|
self.p.putNonBlocking(k, dat_bytes)
|
||||||
|
|
||||||
@@ -120,5 +179,19 @@ cdef class Params:
|
|||||||
cdef string key_bytes = ensure_bytes(key)
|
cdef string key_bytes = ensure_bytes(key)
|
||||||
return self.p.getParamPath(key_bytes).decode("utf-8")
|
return self.p.getParamPath(key_bytes).decode("utf-8")
|
||||||
|
|
||||||
def all_keys(self, type=ParamKeyType.ALL):
|
def get_type(self, key):
|
||||||
return self.p.allKeys(type)
|
return self.p.getKeyType(self.check_key(key))
|
||||||
|
|
||||||
|
def all_keys(self, flag=ParamKeyFlag.ALL):
|
||||||
|
return self.p.allKeys(flag)
|
||||||
|
|
||||||
|
def get_default_value(self, key):
|
||||||
|
cdef string k = self.check_key(key)
|
||||||
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
|
cdef optional[string] default = self.p.getKeyDefaultValue(k)
|
||||||
|
return self._cpp2python(t, default.value(), None, key) if default.has_value() else None
|
||||||
|
|
||||||
|
def cpp2python(self, key, value):
|
||||||
|
cdef string k = self.check_key(key)
|
||||||
|
cdef ParamKeyType t = self.p.getKeyType(k)
|
||||||
|
return self._cpp2python(t, value, None, key)
|
||||||
|
|||||||
+18
-25
@@ -2,11 +2,10 @@ import numpy as np
|
|||||||
from numbers import Number
|
from numbers import Number
|
||||||
|
|
||||||
class PIDController:
|
class PIDController:
|
||||||
def __init__(self, k_p, k_i, k_f=0., k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
|
||||||
self._k_p = k_p
|
self._k_p = k_p
|
||||||
self._k_i = k_i
|
self._k_i = k_i
|
||||||
self._k_d = k_d
|
self._k_d = k_d
|
||||||
self.k_f = k_f # feedforward gain
|
|
||||||
if isinstance(self._k_p, Number):
|
if isinstance(self._k_p, Number):
|
||||||
self._k_p = [[0], [self._k_p]]
|
self._k_p = [[0], [self._k_p]]
|
||||||
if isinstance(self._k_i, Number):
|
if isinstance(self._k_i, Number):
|
||||||
@@ -14,11 +13,9 @@ class PIDController:
|
|||||||
if isinstance(self._k_d, Number):
|
if isinstance(self._k_d, Number):
|
||||||
self._k_d = [[0], [self._k_d]]
|
self._k_d = [[0], [self._k_d]]
|
||||||
|
|
||||||
self.pos_limit = pos_limit
|
self.set_limits(pos_limit, neg_limit)
|
||||||
self.neg_limit = neg_limit
|
|
||||||
|
|
||||||
self.i_unwind_rate = 0.3 / rate
|
self.i_dt = 1.0 / rate
|
||||||
self.i_rate = 1.0 / rate
|
|
||||||
self.speed = 0.0
|
self.speed = 0.0
|
||||||
|
|
||||||
self.reset()
|
self.reset()
|
||||||
@@ -35,10 +32,6 @@ class PIDController:
|
|||||||
def k_d(self):
|
def k_d(self):
|
||||||
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
return np.interp(self.speed, self._k_d[0], self._k_d[1])
|
||||||
|
|
||||||
@property
|
|
||||||
def error_integral(self):
|
|
||||||
return self.i/self.k_i
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
self.p = 0.0
|
self.p = 0.0
|
||||||
self.i = 0.0
|
self.i = 0.0
|
||||||
@@ -46,25 +39,25 @@ class PIDController:
|
|||||||
self.f = 0.0
|
self.f = 0.0
|
||||||
self.control = 0
|
self.control = 0
|
||||||
|
|
||||||
def update(self, error, error_rate=0.0, speed=0.0, override=False, feedforward=0., freeze_integrator=False):
|
def set_limits(self, pos_limit, neg_limit):
|
||||||
|
self.pos_limit = pos_limit
|
||||||
|
self.neg_limit = neg_limit
|
||||||
|
|
||||||
|
def update(self, error, error_rate=0.0, speed=0.0, feedforward=0., freeze_integrator=False):
|
||||||
self.speed = speed
|
self.speed = speed
|
||||||
|
self.p = self.k_p * float(error)
|
||||||
|
self.d = self.k_d * error_rate
|
||||||
|
self.f = feedforward
|
||||||
|
|
||||||
self.p = float(error) * self.k_p
|
if not freeze_integrator:
|
||||||
self.f = feedforward * self.k_f
|
i = self.i + self.k_i * self.i_dt * error
|
||||||
self.d = error_rate * self.k_d
|
|
||||||
|
|
||||||
if override:
|
# Don't allow windup if already clipping
|
||||||
self.i -= self.i_unwind_rate * float(np.sign(self.i))
|
test_control = self.p + i + self.d + self.f
|
||||||
else:
|
i_upperbound = self.i if test_control > self.pos_limit else self.pos_limit
|
||||||
if not freeze_integrator:
|
i_lowerbound = self.i if test_control < self.neg_limit else self.neg_limit
|
||||||
self.i = self.i + error * self.k_i * self.i_rate
|
self.i = np.clip(i, i_lowerbound, i_upperbound)
|
||||||
|
|
||||||
# Clip i to prevent exceeding control limits
|
|
||||||
control_no_i = self.p + self.d + self.f
|
|
||||||
control_no_i = np.clip(control_no_i, self.neg_limit, self.pos_limit)
|
|
||||||
self.i = np.clip(self.i, self.neg_limit - control_no_i, self.pos_limit - control_no_i)
|
|
||||||
|
|
||||||
control = self.p + self.i + self.d + self.f
|
control = self.p + self.i + self.d + self.f
|
||||||
|
|
||||||
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
self.control = np.clip(control, self.neg_limit, self.pos_limit)
|
||||||
return self.control
|
return self.control
|
||||||
|
|||||||
+12
-6
@@ -9,20 +9,19 @@ from openpilot.system.hardware.hw import Paths
|
|||||||
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||||
|
|
||||||
class OpenpilotPrefix:
|
class OpenpilotPrefix:
|
||||||
def __init__(self, prefix: str = None, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
|
def __init__(self, prefix: str = None, create_dirs_on_enter: bool = True, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
|
||||||
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
|
||||||
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
|
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
|
||||||
|
self.create_dirs_on_enter = create_dirs_on_enter
|
||||||
self.clean_dirs_on_exit = clean_dirs_on_exit
|
self.clean_dirs_on_exit = clean_dirs_on_exit
|
||||||
self.shared_download_cache = shared_download_cache
|
self.shared_download_cache = shared_download_cache
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None)
|
self.original_prefix = os.environ.get('OPENPILOT_PREFIX', None)
|
||||||
os.environ['OPENPILOT_PREFIX'] = self.prefix
|
os.environ['OPENPILOT_PREFIX'] = self.prefix
|
||||||
try:
|
|
||||||
os.mkdir(self.msgq_path)
|
if self.create_dirs_on_enter:
|
||||||
except FileExistsError:
|
self.create_dirs()
|
||||||
pass
|
|
||||||
os.makedirs(Paths.log_root(), exist_ok=True)
|
|
||||||
|
|
||||||
if self.shared_download_cache:
|
if self.shared_download_cache:
|
||||||
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
|
os.environ["COMMA_CACHE"] = DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||||
@@ -40,6 +39,13 @@ class OpenpilotPrefix:
|
|||||||
pass
|
pass
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def create_dirs(self):
|
||||||
|
try:
|
||||||
|
os.mkdir(self.msgq_path)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
os.makedirs(Paths.log_root(), exist_ok=True)
|
||||||
|
|
||||||
def clean_dirs(self):
|
def clean_dirs(self):
|
||||||
symlink_path = Params().get_param_path()
|
symlink_path = Params().get_param_path()
|
||||||
if os.path.exists(symlink_path):
|
if os.path.exists(symlink_path):
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
import time
|
|
||||||
import functools
|
|
||||||
|
|
||||||
from openpilot.common.swaglog import cloudlog
|
|
||||||
|
|
||||||
|
|
||||||
def retry(attempts=3, delay=1.0, ignore_failure=False):
|
|
||||||
def decorator(func):
|
|
||||||
@functools.wraps(func)
|
|
||||||
def wrapper(*args, **kwargs):
|
|
||||||
for _ in range(attempts):
|
|
||||||
try:
|
|
||||||
return func(*args, **kwargs)
|
|
||||||
except Exception:
|
|
||||||
cloudlog.exception(f"{func.__name__} failed, trying again")
|
|
||||||
time.sleep(delay)
|
|
||||||
|
|
||||||
if ignore_failure:
|
|
||||||
cloudlog.error(f"{func.__name__} failed after retry")
|
|
||||||
else:
|
|
||||||
raise Exception(f"{func.__name__} failed after retry")
|
|
||||||
return wrapper
|
|
||||||
return decorator
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
|
||||||
@retry(attempts=10)
|
|
||||||
def abc():
|
|
||||||
raise ValueError("abc failed :(")
|
|
||||||
abc()
|
|
||||||
@@ -1,13 +0,0 @@
|
|||||||
import subprocess
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
|
|
||||||
return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip()
|
|
||||||
|
|
||||||
|
|
||||||
def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str:
|
|
||||||
try:
|
|
||||||
return run_cmd(cmd, cwd=cwd, env=env)
|
|
||||||
except subprocess.CalledProcessError:
|
|
||||||
return default
|
|
||||||
|
|
||||||
+3
-1
@@ -15,6 +15,8 @@
|
|||||||
#include "common/version.h"
|
#include "common/version.h"
|
||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
class SwaglogState {
|
class SwaglogState {
|
||||||
public:
|
public:
|
||||||
SwaglogState() {
|
SwaglogState() {
|
||||||
@@ -56,7 +58,7 @@ public:
|
|||||||
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
if (char* daemon_name = getenv("MANAGER_DAEMON")) {
|
||||||
ctx_j["daemon"] = daemon_name;
|
ctx_j["daemon"] = daemon_name;
|
||||||
}
|
}
|
||||||
ctx_j["version"] = COMMA_VERSION;
|
ctx_j["version"] = SUNNYPILOT_VERSION;
|
||||||
ctx_j["dirty"] = !getenv("CLEAN");
|
ctx_j["dirty"] = !getenv("CLEAN");
|
||||||
ctx_j["device"] = Hardware::get_name();
|
ctx_j["device"] = Hardware::get_name();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import os
|
import os
|
||||||
from uuid import uuid4
|
from uuid import uuid4
|
||||||
|
|
||||||
from openpilot.common.file_helpers import atomic_write_in_dir
|
from openpilot.common.utils import atomic_write_in_dir
|
||||||
|
|
||||||
|
|
||||||
class TestFileHelpers:
|
class TestFileHelpers:
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from openpilot.common.markdown import parse_markdown
|
|||||||
|
|
||||||
class TestMarkdown:
|
class TestMarkdown:
|
||||||
def test_all_release_notes(self):
|
def test_all_release_notes(self):
|
||||||
with open(os.path.join(BASEDIR, "RELEASES.md")) as f:
|
with open(os.path.join(BASEDIR, "CHANGELOG.md")) as f:
|
||||||
release_notes = f.read().split("\n\n")
|
release_notes = f.read().split("\n\n")
|
||||||
assert len(release_notes) > 10
|
assert len(release_notes) > 10
|
||||||
|
|
||||||
|
|||||||
+44
-12
@@ -1,10 +1,11 @@
|
|||||||
import pytest
|
import pytest
|
||||||
|
import datetime
|
||||||
import os
|
import os
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from openpilot.common.params import Params, ParamKeyType, UnknownKeyName
|
from openpilot.common.params import Params, ParamKeyFlag, UnknownKeyName
|
||||||
|
|
||||||
class TestParams:
|
class TestParams:
|
||||||
def setup_method(self):
|
def setup_method(self):
|
||||||
@@ -12,7 +13,7 @@ class TestParams:
|
|||||||
|
|
||||||
def test_params_put_and_get(self):
|
def test_params_put_and_get(self):
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee")
|
||||||
assert self.params.get("DongleId") == b"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"
|
||||||
@@ -20,7 +21,7 @@ class TestParams:
|
|||||||
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", "test")
|
self.params.put("CarParams", b"test")
|
||||||
self.params.put("DongleId", "cb38263377b873ee")
|
self.params.put("DongleId", "cb38263377b873ee")
|
||||||
assert self.params.get("CarParams") == b"test"
|
assert self.params.get("CarParams") == b"test"
|
||||||
|
|
||||||
@@ -29,24 +30,24 @@ class TestParams:
|
|||||||
f.write("test")
|
f.write("test")
|
||||||
assert os.path.isfile(undefined_param)
|
assert os.path.isfile(undefined_param)
|
||||||
|
|
||||||
self.params.clear_all(ParamKeyType.CLEAR_ON_MANAGER_START)
|
self.params.clear_all(ParamKeyFlag.CLEAR_ON_MANAGER_START)
|
||||||
assert self.params.get("CarParams") is None
|
assert self.params.get("CarParams") is None
|
||||||
assert self.params.get("DongleId") is not None
|
assert self.params.get("DongleId") is not None
|
||||||
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")
|
||||||
self.params.put("AthenadPid", "123")
|
self.params.put("AthenadPid", 123)
|
||||||
assert self.params.get("DongleId") == b"bob"
|
assert self.params.get("DongleId") == "bob"
|
||||||
assert self.params.get("AthenadPid") == b"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", "test")
|
self.params.put("CarParams", b"test")
|
||||||
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", True) == b"test"
|
assert self.params.get("CarParams", block=True) == b"test"
|
||||||
|
|
||||||
def test_params_unknown_key_fails(self):
|
def test_params_unknown_key_fails(self):
|
||||||
with pytest.raises(UnknownKeyName):
|
with pytest.raises(UnknownKeyName):
|
||||||
@@ -76,17 +77,17 @@ class TestParams:
|
|||||||
self.params.put_bool("IsMetric", False)
|
self.params.put_bool("IsMetric", False)
|
||||||
assert not self.params.get_bool("IsMetric")
|
assert not self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", "1")
|
self.params.put("IsMetric", True)
|
||||||
assert self.params.get_bool("IsMetric")
|
assert self.params.get_bool("IsMetric")
|
||||||
|
|
||||||
self.params.put("IsMetric", "0")
|
self.params.put("IsMetric", False)
|
||||||
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", "test")
|
Params().put_nonblocking("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"
|
||||||
@@ -107,3 +108,34 @@ class TestParams:
|
|||||||
assert len(keys) > 20
|
assert len(keys) > 20
|
||||||
assert len(keys) == len(set(keys))
|
assert len(keys) == len(set(keys))
|
||||||
assert b"CarParams" in keys
|
assert b"CarParams" in keys
|
||||||
|
|
||||||
|
def test_params_default_value(self):
|
||||||
|
self.params.remove("LanguageSetting")
|
||||||
|
self.params.remove("LongitudinalPersonality")
|
||||||
|
self.params.remove("LiveParameters")
|
||||||
|
|
||||||
|
assert self.params.get("LanguageSetting") is None
|
||||||
|
assert self.params.get("LanguageSetting", return_default=False) is None
|
||||||
|
assert isinstance(self.params.get("LanguageSetting", return_default=True), str)
|
||||||
|
assert isinstance(self.params.get("LongitudinalPersonality", return_default=True), int)
|
||||||
|
assert self.params.get("LiveParameters") is None
|
||||||
|
assert self.params.get("LiveParameters", return_default=True) is None
|
||||||
|
|
||||||
|
def test_params_get_type(self):
|
||||||
|
# json
|
||||||
|
self.params.put("ApiCache_FirehoseStats", {"a": 0})
|
||||||
|
assert self.params.get("ApiCache_FirehoseStats") == {"a": 0}
|
||||||
|
|
||||||
|
# int
|
||||||
|
self.params.put("BootCount", 1441)
|
||||||
|
assert self.params.get("BootCount") == 1441
|
||||||
|
|
||||||
|
# bool
|
||||||
|
self.params.put("AdbEnabled", True)
|
||||||
|
assert self.params.get("AdbEnabled")
|
||||||
|
assert isinstance(self.params.get("AdbEnabled"), bool)
|
||||||
|
|
||||||
|
# time
|
||||||
|
now = datetime.datetime.now(datetime.UTC)
|
||||||
|
self.params.put("InstallDate", now)
|
||||||
|
assert self.params.get("InstallDate") == now
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
#include "system/hardware/hw.h"
|
#include "system/hardware/hw.h"
|
||||||
#include "third_party/json11/json11.hpp"
|
#include "third_party/json11/json11.hpp"
|
||||||
|
|
||||||
|
#include "sunnypilot/common/version.h"
|
||||||
|
|
||||||
std::string daemon_name = "testy";
|
std::string daemon_name = "testy";
|
||||||
std::string dongle_id = "test_dongle_id";
|
std::string dongle_id = "test_dongle_id";
|
||||||
int LINE_NO = 0;
|
int LINE_NO = 0;
|
||||||
@@ -53,7 +55,7 @@ void recv_log(int thread_cnt, int thread_msg_cnt) {
|
|||||||
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
REQUIRE(ctx["dongle_id"].string_value() == dongle_id);
|
||||||
REQUIRE(ctx["dirty"].bool_value() == true);
|
REQUIRE(ctx["dirty"].bool_value() == true);
|
||||||
|
|
||||||
REQUIRE(ctx["version"].string_value() == COMMA_VERSION);
|
REQUIRE(ctx["version"].string_value() == SUNNYPILOT_VERSION);
|
||||||
|
|
||||||
std::string device = Hardware::get_name();
|
std::string device = Hardware::get_name();
|
||||||
REQUIRE(ctx["device"].string_value() == device);
|
REQUIRE(ctx["device"].string_value() == device);
|
||||||
|
|||||||
+11
-3
@@ -1,4 +1,5 @@
|
|||||||
#include "common/util.h"
|
#include "common/util.h"
|
||||||
|
#include "common/swaglog.h"
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -12,6 +13,7 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <random>
|
#include <random>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <sys/prctl.h>
|
#include <sys/prctl.h>
|
||||||
@@ -78,8 +80,9 @@ std::string read_file(const std::string& fn) {
|
|||||||
std::ifstream f(fn, std::ios::binary | std::ios::in);
|
std::ifstream f(fn, std::ios::binary | std::ios::in);
|
||||||
if (f.is_open()) {
|
if (f.is_open()) {
|
||||||
f.seekg(0, std::ios::end);
|
f.seekg(0, std::ios::end);
|
||||||
int size = f.tellg();
|
std::streamsize size = f.tellg();
|
||||||
if (f.good() && size > 0) {
|
// seekg and tellg on a directory doesn't return pos_type(-1) but max(streamsize)
|
||||||
|
if (f.good() && size > 0 && size < std::numeric_limits<std::streamsize>::max()) {
|
||||||
std::string result(size, '\0');
|
std::string result(size, '\0');
|
||||||
f.seekg(0, std::ios::beg);
|
f.seekg(0, std::ios::beg);
|
||||||
f.read(result.data(), size);
|
f.read(result.data(), size);
|
||||||
@@ -149,11 +152,16 @@ int safe_fflush(FILE *stream) {
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int safe_ioctl(int fd, unsigned long request, void *argp) {
|
int safe_ioctl(int fd, unsigned long request, void *argp, const char* exception_msg) {
|
||||||
int ret;
|
int ret;
|
||||||
do {
|
do {
|
||||||
ret = ioctl(fd, request, argp);
|
ret = ioctl(fd, request, argp);
|
||||||
} while ((ret == -1) && (errno == EINTR));
|
} while ((ret == -1) && (errno == EINTR));
|
||||||
|
|
||||||
|
if (ret == -1 && exception_msg) {
|
||||||
|
LOGE("safe_ioctl error: %s %s(%d) (fd: %d request: %lx argp: %p)", exception_msg, strerror(errno), errno, fd, request, argp);
|
||||||
|
throw std::runtime_error(exception_msg);
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -36,6 +36,7 @@ const double MS_TO_KPH = 3.6;
|
|||||||
const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE;
|
const double MS_TO_MPH = MS_TO_KPH * KM_TO_MILE;
|
||||||
const double METER_TO_MILE = KM_TO_MILE / 1000.0;
|
const double METER_TO_MILE = KM_TO_MILE / 1000.0;
|
||||||
const double METER_TO_FOOT = 3.28084;
|
const double METER_TO_FOOT = 3.28084;
|
||||||
|
const double METER_TO_KM = 1. / 1000.0;
|
||||||
|
|
||||||
#define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1))
|
#define ALIGNED_SIZE(x, align) (((x) + (align)-1) & ~((align)-1))
|
||||||
|
|
||||||
@@ -88,7 +89,7 @@ int write_file(const char* path, const void* data, size_t size, int flags = O_WR
|
|||||||
FILE* safe_fopen(const char* filename, const char* mode);
|
FILE* safe_fopen(const char* filename, const char* mode);
|
||||||
size_t safe_fwrite(const void * ptr, size_t size, size_t count, FILE * stream);
|
size_t safe_fwrite(const void * ptr, size_t size, size_t count, FILE * stream);
|
||||||
int safe_fflush(FILE *stream);
|
int safe_fflush(FILE *stream);
|
||||||
int safe_ioctl(int fd, unsigned long request, void *argp);
|
int safe_ioctl(int fd, unsigned long request, void *argp, const char* exception_msg = nullptr);
|
||||||
|
|
||||||
std::string readlink(const std::string& path);
|
std::string readlink(const std::string& path);
|
||||||
bool file_exists(const std::string& fn);
|
bool file_exists(const std::string& fn);
|
||||||
|
|||||||
@@ -2,9 +2,14 @@ import io
|
|||||||
import os
|
import os
|
||||||
import tempfile
|
import tempfile
|
||||||
import contextlib
|
import contextlib
|
||||||
|
import subprocess
|
||||||
|
import time
|
||||||
|
import functools
|
||||||
|
from subprocess import Popen, PIPE, TimeoutExpired
|
||||||
import zstandard as zstd
|
import zstandard as zstd
|
||||||
|
from openpilot.common.swaglog import cloudlog
|
||||||
|
|
||||||
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
|
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
|
||||||
|
|
||||||
|
|
||||||
class CallbackReader:
|
class CallbackReader:
|
||||||
@@ -27,7 +32,7 @@ class CallbackReader:
|
|||||||
|
|
||||||
|
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str = None, newline: str = None,
|
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None,
|
||||||
overwrite: bool = False):
|
overwrite: bool = False):
|
||||||
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
|
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
|
||||||
dir_name = os.path.dirname(path)
|
dir_name = os.path.dirname(path)
|
||||||
@@ -56,3 +61,58 @@ def get_upload_stream(filepath: str, should_compress: bool) -> tuple[io.Buffered
|
|||||||
compressed_size = compressed_stream.tell()
|
compressed_size = compressed_stream.tell()
|
||||||
compressed_stream.seek(0)
|
compressed_stream.seek(0)
|
||||||
return compressed_stream, compressed_size
|
return compressed_stream, compressed_size
|
||||||
|
|
||||||
|
|
||||||
|
# remove all keys that end in DEPRECATED
|
||||||
|
def strip_deprecated_keys(d):
|
||||||
|
for k in list(d.keys()):
|
||||||
|
if isinstance(k, str):
|
||||||
|
if k.endswith('DEPRECATED'):
|
||||||
|
d.pop(k)
|
||||||
|
elif isinstance(d[k], dict):
|
||||||
|
strip_deprecated_keys(d[k])
|
||||||
|
return d
|
||||||
|
|
||||||
|
|
||||||
|
def run_cmd(cmd: list[str], cwd=None, env=None) -> str:
|
||||||
|
return subprocess.check_output(cmd, encoding='utf8', cwd=cwd, env=env).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def run_cmd_default(cmd: list[str], default: str = "", cwd=None, env=None) -> str:
|
||||||
|
try:
|
||||||
|
return run_cmd(cmd, cwd=cwd, env=env)
|
||||||
|
except subprocess.CalledProcessError:
|
||||||
|
return default
|
||||||
|
|
||||||
|
|
||||||
|
@contextlib.contextmanager
|
||||||
|
def managed_proc(cmd: list[str], env: dict[str, str]):
|
||||||
|
proc = Popen(cmd, env=env, stdout=PIPE, stderr=PIPE)
|
||||||
|
try:
|
||||||
|
yield proc
|
||||||
|
finally:
|
||||||
|
if proc.poll() is None:
|
||||||
|
proc.terminate()
|
||||||
|
try:
|
||||||
|
proc.wait(timeout=5)
|
||||||
|
except TimeoutExpired:
|
||||||
|
proc.kill()
|
||||||
|
|
||||||
|
|
||||||
|
def retry(attempts=3, delay=1.0, ignore_failure=False):
|
||||||
|
def decorator(func):
|
||||||
|
@functools.wraps(func)
|
||||||
|
def wrapper(*args, **kwargs):
|
||||||
|
for _ in range(attempts):
|
||||||
|
try:
|
||||||
|
return func(*args, **kwargs)
|
||||||
|
except Exception:
|
||||||
|
cloudlog.exception(f"{func.__name__} failed, trying again")
|
||||||
|
time.sleep(delay)
|
||||||
|
|
||||||
|
if ignore_failure:
|
||||||
|
cloudlog.error(f"{func.__name__} failed after retry")
|
||||||
|
else:
|
||||||
|
raise Exception(f"{func.__name__} failed after retry")
|
||||||
|
return wrapper
|
||||||
|
return decorator
|
||||||
+1
-1
@@ -1 +1 @@
|
|||||||
#define COMMA_VERSION "0.10.0"
|
#define COMMA_VERSION "0.10.2"
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
#include <string>
|
|
||||||
|
|
||||||
#include "common/watchdog.h"
|
|
||||||
#include "common/util.h"
|
|
||||||
#include "system/hardware/hw.h"
|
|
||||||
|
|
||||||
const std::string watchdog_fn_prefix = Path::shm_path() + "/wd_"; // + <pid>
|
|
||||||
|
|
||||||
bool watchdog_kick(uint64_t ts) {
|
|
||||||
static std::string fn = watchdog_fn_prefix + std::to_string(getpid());
|
|
||||||
return util::write_file(fn.c_str(), &ts, sizeof(ts), O_WRONLY | O_CREAT) > 0;
|
|
||||||
}
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
|
|
||||||
bool watchdog_kick(uint64_t ts);
|
|
||||||
@@ -1,22 +0,0 @@
|
|||||||
import os
|
|
||||||
import time
|
|
||||||
import struct
|
|
||||||
from openpilot.system.hardware.hw import Paths
|
|
||||||
|
|
||||||
WATCHDOG_FN = f"{Paths.shm_path()}/wd_"
|
|
||||||
_LAST_KICK = 0.0
|
|
||||||
|
|
||||||
def kick_watchdog():
|
|
||||||
global _LAST_KICK
|
|
||||||
current_time = time.monotonic()
|
|
||||||
|
|
||||||
if current_time - _LAST_KICK < 1.0:
|
|
||||||
return
|
|
||||||
|
|
||||||
try:
|
|
||||||
with open(f"{WATCHDOG_FN}{os.getpid()}", 'wb') as f:
|
|
||||||
f.write(struct.pack('<Q', int(current_time * 1e9)))
|
|
||||||
f.flush()
|
|
||||||
_LAST_KICK = current_time
|
|
||||||
except OSError:
|
|
||||||
pass
|
|
||||||
+353
-325
@@ -4,322 +4,351 @@
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
# 312 Supported Cars
|
# 341 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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=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|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=RDX 2016-18">Buy Here</a></sub></details>|||
|
|Acura|MDX 2025|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">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Acura&model=RDX 2019-21">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>|||
|
||||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 2014-19">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>|||
|
||||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=A3 Sportback e-tron 2017-18">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>|||
|
||||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q2 2018">Buy Here</a></sub></details>|||
|
|Audi|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 USB-C coupler<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|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=Q3 2019-24">Buy Here</a></sub></details>|||
|
|Audi|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 USB-C coupler<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|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=RS3 2018">Buy Here</a></sub></details>|||
|
|Audi|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 USB-C coupler<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|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Audi&model=S3 2015-17">Buy Here</a></sub></details>|||
|
|Audi|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 USB-C coupler<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>|||
|
||||||
|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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=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>||
|
|Audi|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 USB-C coupler<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>|||
|
||||||
|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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Bolt EV 2022-23">Buy Here</a></sub></details>|||
|
|Audi|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 USB-C coupler<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|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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Equinox 2019-22">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|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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Silverado 1500 2020-21">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|Trailblazer 2021-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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chevrolet&model=Trailblazer 2021-22">Buy Here</a></sub></details>|||
|
|Chevrolet|Bolt EV Non-ACC 2017|Adaptive Cruise Control (ACC)|Stock|24 mph|7 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 Non-ACC 2017">Buy Here</a></sub></details>|||
|
||||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2017-18">Buy Here</a></sub></details>|||
|
|Chevrolet|Bolt EV Non-ACC 2018-21|Adaptive Cruise Control (ACC)|Stock|24 mph|7 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 Non-ACC 2018-21">Buy Here</a></sub></details>|||
|
||||||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2019-20">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>|||
|
||||||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica 2021-23">Buy Here</a></sub></details>|||
|
|Chevrolet|Malibu Non-ACC 2016-23|Adaptive Cruise Control (ACC)|Stock|24 mph|7 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 Malibu Non-ACC 2016-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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2017-18">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>|||
|
||||||
|Chrysler|Pacifica Hybrid 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Chrysler&model=Pacifica Hybrid 2019-24">Buy Here</a></sub></details>|||
|
|Chevrolet|Trailblazer 2021-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 Trailblazer 2021-22">Buy Here</a></sub></details>|||
|
||||||
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None|||
|
|Chrysler|Pacifica 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 2017-18">Buy Here</a></sub></details>|||
|
||||||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=CUPRA&model=Ateca 2018-23">Buy Here</a></sub></details>|||
|
|Chrysler|Pacifica 2019-20|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 2019-20">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Dodge&model=Durango 2020-21">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>|||
|
||||||
|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Bronco Sport 2021-24">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>|||
|
||||||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape 2020-22">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>|||
|
||||||
|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape 2023-24">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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>||
|
||||||
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|CUPRA|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 USB-C coupler<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>|||
|
||||||
|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Hybrid 2023-24">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Plug-in Hybrid 2020-22">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 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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Escape Plug-in Hybrid 2023-24">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Expedition 2022-24">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=MewJc9LYp9M|
|
|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 USB-C coupler<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|Explorer 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer 2020-24">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|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Explorer Hybrid 2020-24">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 USB-C coupler<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|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 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=F-150 2021-23">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=MewJc9LYp9M|
|
|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|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 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=F-150 Hybrid 2021-23">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=MewJc9LYp9M|
|
|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 USB-C coupler<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|Focus 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Focus 2018">Buy Here</a></sub></details>|||
|
|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 USB-C coupler<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|Focus Hybrid 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Focus Hybrid 2018">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga 2020-23">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Hybrid 2020-23">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 USB-C coupler<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|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Hybrid 2024">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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 USB-C coupler<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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Plug-in Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Ford|Focus 2018[<sup>3</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|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Kuga Plug-in Hybrid 2024">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|Ford|Focus Hybrid 2018[<sup>3</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|Maverick 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick 2022">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|Maverick 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick 2023-24">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|Maverick Hybrid 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick Hybrid 2022">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 USB-C coupler<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|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Maverick Hybrid 2023-24">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|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Mustang Mach-E 2021-24">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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 USB-C coupler<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|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 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ford&model=Ranger 2024">Buy Here</a></sub></details>||https://www.youtube.com/watch?v=uUGkH6C_EQU|
|
|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>|||
|
||||||
|Genesis|G70 2018|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G70 2018">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G70 2019-21">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G70 2022-23">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>|||
|
||||||
|Genesis|G80 2017|All|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G80 2017">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 USB-C coupler<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>|
|
||||||
|Genesis|G80 2018-19|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G80 2018-19">Buy Here</a></sub></details>|||
|
|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 USB-C coupler<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>|
|
||||||
|Genesis|G80 (2.5T Advanced Trim, with HDA II) 2024[<sup>6</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G80 (2.5T Advanced Trim, with HDA II) 2024">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|G90 2017-20|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=G90 2017-20">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|GV60 (Advanced Trim) 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV60 (Advanced Trim) 2023">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|GV60 (Performance Trim) 2022-23[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV60 (Performance Trim) 2022-23">Buy Here</a></sub></details>|||
|
|Genesis|G80 2017|All|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=Genesis G80 2017">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV70 (2.5T Trim, without HDA II) 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV70 (2.5T Trim, without HDA II) 2022-24">Buy Here</a></sub></details>|||
|
|Genesis|G80 2018-19|All|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=Genesis G80 2018-19">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV70 (3.5T Trim, without HDA II) 2022-23[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV70 (3.5T Trim, without HDA II) 2022-23">Buy Here</a></sub></details>|||
|
|Genesis|G80 (2.5T Advanced Trim, with HDA II) 2024|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P 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 G80 (2.5T Advanced Trim, with HDA II) 2024">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV70 Electrified (Australia Only) 2022[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV70 Electrified (Australia Only) 2022">Buy Here</a></sub></details>|||
|
|Genesis|G90 2017-20|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=Genesis G90 2017-20">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV70 Electrified (with HDA II) 2023-24[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV70 Electrified (with HDA II) 2023-24">Buy Here</a></sub></details>|||
|
|Genesis|GV60 (Advanced Trim) 2023|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=Genesis GV60 (Advanced Trim) 2023">Buy Here</a></sub></details>|||
|
||||||
|Genesis|GV80 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Genesis&model=GV80 2023">Buy Here</a></sub></details>|||
|
|Genesis|GV60 (Performance Trim) 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=Genesis GV60 (Performance Trim) 2022-23">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 comma 3X<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=GMC&model=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>||
|
|Genesis|GV70 (2.5T Trim, without HDA II) 2022-24|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 GV70 (2.5T Trim, without HDA II) 2022-24">Buy Here</a></sub></details>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=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>||
|
|Genesis|GV70 (3.5T Trim, without HDA II) 2022-23|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 GV70 (3.5T Trim, without HDA II) 2022-23">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Accord Hybrid 2018-22">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>|||
|
||||||
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=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>||
|
|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>|||
|
||||||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>5</sup>](#footnotes)|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=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>||
|
|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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=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>||
|
|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>||
|
||||||
|Honda|Civic Hatchback 2017-21|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Civic Hatchback 2017-21">Buy Here</a></sub></details>|||
|
|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=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|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|Civic Hatchback Hybrid 2025|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Civic Hatchback Hybrid 2025">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Civic Hatchback Hybrid (Europe only) 2023">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|CR-V 2015-16|Touring Trim|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V 2015-16">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|CR-V 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V 2017-22">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|CR-V Hybrid 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=CR-V Hybrid 2017-22">Buy Here</a></sub></details>|||
|
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>5</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|e 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=e 2020">Buy Here</a></sub></details>|||
|
|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|Fit 2018-20|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Fit 2018-20">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|Freed 2020|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Freed 2020">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|HR-V 2019-22|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=HR-V 2019-22">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|HR-V 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=HR-V 2023-25">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|Insight 2019-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Insight 2019-22">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|Inspire 2018|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Inspire 2018">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|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Odyssey 2018-20">Buy Here</a></sub></details>|||
|
|Honda|Clarity 2018-21|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector + Honda Clarity Proxy Board<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://shop.retropilot.org/product/honda-clarity-proxy-board-kit">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Passport 2019-25">Buy Here</a></sub></details>|||
|
|Honda|CR-V 2015-16|Touring Trim|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 CR-V 2015-16">Buy Here</a></sub></details>|||
|
||||||
|Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Pilot 2016-22">Buy Here</a></sub></details>|||
|
|Honda|CR-V 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|15 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 CR-V 2017-22">Buy Here</a></sub></details>|||
|
||||||
|Honda|Ridgeline 2017-25|Honda Sensing|openpilot|26 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Honda&model=Ridgeline 2017-25">Buy Here</a></sub></details>|||
|
|Honda|CR-V 2023-26|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 CR-V 2023-26">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Azera 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera 2022">Buy Here</a></sub></details>|||
|
|Honda|CR-V Hybrid 2017-22|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 CR-V Hybrid 2017-22">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Azera Hybrid 2019|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera Hybrid 2019">Buy Here</a></sub></details>|||
|
|Honda|CR-V 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 CR-V Hybrid 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Azera Hybrid 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Azera Hybrid 2020">Buy Here</a></sub></details>|||
|
|Honda|e 2020|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 e 2020">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Custin 2023">Buy Here</a></sub></details>|||
|
|Honda|Fit 2018-20|Honda Sensing|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 Fit 2018-20">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2017-18">Buy Here</a></sub></details>|||
|
|Honda|Freed 2020|Honda Sensing|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 Freed 2020">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra 2019">Buy Here</a></sub></details>|||
|
|Honda|HR-V 2019-22|Honda Sensing|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 HR-V 2019-22">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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>||
|
|Honda|HR-V 2023-25|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 HR-V 2023-25">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Elantra GT 2017-20">Buy Here</a></sub></details>|||
|
|Honda|Insight 2019-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 Insight 2019-22">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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>||
|
|Honda|Inspire 2018|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 Inspire 2018">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Genesis 2015-16">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>|||
|
||||||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=i30 2017-19">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>|||
|
||||||
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (Southeast Asia and Europe only) 2022-24">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>|||
|
||||||
|Hyundai|Ioniq 5 (with HDA II) 2022-24[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (with HDA II) 2022-24">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>|||
|
||||||
|Hyundai|Ioniq 5 (without HDA II) 2022-24[<sup>6</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 5 (without HDA II) 2022-24">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>|||
|
||||||
|Hyundai|Ioniq 6 (with HDA II) 2023-24[<sup>6</sup>](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq 6 (with HDA II) 2023-24">Buy Here</a></sub></details>|||
|
|Honda|Pilot 2016-22|Honda Sensing|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 Pilot 2016-22">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Electric 2019">Buy Here</a></sub></details>|||
|
|Honda|Pilot 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 Pilot 2023-25">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Electric 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Electric 2020">Buy Here</a></sub></details>|||
|
|Honda|Ridgeline 2017-25|Honda Sensing|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 Ridgeline 2017-25">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Hybrid 2017-19">Buy Here</a></sub></details>|||
|
|Hyundai|Azera 2022|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 Azera 2022">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Hyundai|Azera Hybrid 2019|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=Hyundai Azera Hybrid 2019">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Plug-in Hybrid 2019">Buy Here</a></sub></details>|||
|
|Hyundai|Azera Hybrid 2020|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 Azera Hybrid 2020">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Ioniq Plug-in Hybrid 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Ioniq Plug-in Hybrid 2020-22">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|Kona 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona 2020">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Electric 2018-21">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Electric 2022-23">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|Kona Electric (with HDA II, Korea only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Kona Hybrid 2020">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|Nexo 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Nexo 2021">Buy Here</a></sub></details>|||
|
|Hyundai|Elantra Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|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 Non-SCC 2022">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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|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|Santa Cruz 2022-24[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Cruz 2022-24">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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|Ioniq 5 (with HDA II) 2022-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=Hyundai Ioniq 5 (with HDA II) 2022-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe Hybrid 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq 5 (without HDA II) 2022-24|Highway Driving Assist|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 Ioniq 5 (without HDA II) 2022-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Santa Fe Plug-in Hybrid 2022-23">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq 6 (with HDA II) 2023-24|Highway Driving Assist II|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P 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 6 (with HDA II) 2023-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Sonata 2018-19">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 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=Hyundai Ioniq Electric 2019">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=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|Ioniq Electric 2020|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 Ioniq Electric 2020">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Sonata Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq Hybrid 2017-19|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 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=Hyundai Ioniq Hybrid 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Staria 2023[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Staria 2023">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq Hybrid 2020-22|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=Hyundai Ioniq Hybrid 2020-22">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2021">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq Plug-in Hybrid 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 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=Hyundai Ioniq Plug-in Hybrid 2019">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Tucson 2022[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2022">Buy Here</a></sub></details>|||
|
|Hyundai|Ioniq Plug-in Hybrid 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 Ioniq Plug-in Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Tucson 2023-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson 2023-24">Buy Here</a></sub></details>|||
|
|Hyundai|Kona 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 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 Kona 2020">Buy Here</a></sub></details>|||
|
||||||
|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson Diesel 2019">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|Tucson Hybrid 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson Hybrid 2022-24">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|Tucson Plug-in Hybrid 2024[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Tucson Plug-in Hybrid 2024">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|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Hyundai&model=Veloster 2019-20">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>||
|
||||||
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Jeep&model=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>||
|
|Hyundai|Kona Electric Non-SCC 2019|No Smart Cruise Control (Non-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=Hyundai Kona Electric Non-SCC 2019">Buy Here</a></sub></details>|||
|
||||||
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Jeep&model=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>||
|
|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>|||
|
||||||
|Kia|Carnival 2022-24[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival 2022-24">Buy Here</a></sub></details>|||
|
|Hyundai|Kona Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 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 Kona Non-SCC 2019">Buy Here</a></sub></details>|||
|
||||||
|Kia|Carnival (China only) 2023[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Carnival (China only) 2023">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>|||
|
||||||
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Ceed 2019-21">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>||
|
||||||
|Kia|EV6 (Southeast Asia only) 2022-24[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (Southeast Asia only) 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>|||
|
||||||
|Kia|EV6 (with HDA II) 2022-24[<sup>6</sup>](#footnotes)|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (with HDA II) 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>||
|
||||||
|Kia|EV6 (without HDA II) 2022-24[<sup>6</sup>](#footnotes)|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=EV6 (without HDA II) 2022-24">Buy Here</a></sub></details>|||
|
|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>||
|
||||||
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Forte 2019-21">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>|||
|
||||||
|Kia|Forte 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Forte 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>|||
|
||||||
|Kia|K5 2021-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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=K5 2021-24">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=K5 Hybrid 2020-22">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>||
|
||||||
|Kia|K8 Hybrid (with HDA II) 2023[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=K8 Hybrid (with HDA II) 2023">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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>||
|
|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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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>||
|
|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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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>||
|
|Hyundai|Tucson 2022|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 Tucson 2022">Buy Here</a></sub></details>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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>||
|
|Hyundai|Tucson 2023-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 2023-24">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro EV (with HDA II) 2025[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro EV (with HDA II) 2025">Buy Here</a></sub></details>|||
|
|Hyundai|Tucson Diesel 2019|Smart Cruise Control (SCC)|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 Tucson Diesel 2019">Buy Here</a></sub></details>|||
|
||||||
|Kia|Niro EV (without HDA II) 2023-25[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro EV (without HDA II) 2023-25">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>|||
|
||||||
|Kia|Niro Hybrid 2018|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2018">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2021">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2022">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>||
|
||||||
|Kia|Niro Hybrid 2023[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Hybrid 2023">Buy Here</a></sub></details>|||
|
|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>||
|
||||||
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2018-19">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2020">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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2021">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|Niro Plug-in 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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Niro Plug-in Hybrid 2022">Buy Here</a></sub></details>|||
|
|Kia|Ceed Plug-in Hybrid Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|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=Kia Ceed Plug-in Hybrid Non-SCC 2022">Buy Here</a></sub></details>|||
|
||||||
|Kia|Optima 2017|Advanced Smart Cruise Control|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima 2017">Buy Here</a></sub></details>|||
|
|Kia|EV6 (Southeast Asia only) 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P 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 EV6 (Southeast Asia only) 2022-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima 2019-20">Buy Here</a></sub></details>|||
|
|Kia|EV6 (with HDA II) 2022-24|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P 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 EV6 (with HDA II) 2022-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Optima Hybrid 2019">Buy Here</a></sub></details>|||
|
|Kia|EV6 (without HDA II) 2022-24|Highway Driving Assist|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=Kia EV6 (without HDA II) 2022-24">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Seltos 2021">Buy Here</a></sub></details>|||
|
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 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 Forte 2019-21">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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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|Forte 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|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 Forte 2022-23">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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|Forte Non-SCC 2019|No Smart Cruise Control (Non-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 Forte Non-SCC 2019">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento 2021-23[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento 2021-23">Buy Here</a></sub></details>|||
|
|Kia|K5 2021-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 K5 2021-24">Buy Here</a></sub></details>|||
|
||||||
|Kia|Sorento Hybrid 2021-23[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento Hybrid 2021-23">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|Sorento Plug-in Hybrid 2022-23[<sup>6</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sorento Plug-in Hybrid 2022-23">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|Sportage 2023-24[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sportage 2023-24">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|Sportage Hybrid 2023[<sup>6</sup>](#footnotes)|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Sportage Hybrid 2023">Buy Here</a></sub></details>|||
|
|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=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|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Stinger 2022-23">Buy Here</a></sub></details>|||
|
|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|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Kia&model=Telluride 2020-22">Buy Here</a></sub></details>|||
|
|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>|||
|
||||||
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=CT Hybrid 2017-18">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>|||
|
||||||
|Lexus|ES 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2017-18">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>|||
|
||||||
|Lexus|ES 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES 2019-25">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>|||
|
||||||
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=ES Hybrid 2017-18">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>|||
|
||||||
|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=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>||
|
|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>|||
|
||||||
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=GS F 2016">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>|||
|
||||||
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2017-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>|||
|
||||||
|Lexus|IS 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=IS 2022-24">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>|||
|
||||||
|Lexus|LC 2024-25|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=LC 2024-25">Buy Here</a></sub></details>|||
|
|Kia|Niro Plug-in 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 Plug-in Hybrid 2022">Buy Here</a></sub></details>|||
|
||||||
|Lexus|NX 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX 2018-19">Buy Here</a></sub></details>|||
|
|Kia|Optima 2017|Advanced Smart Cruise Control|Stock|0 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=Kia Optima 2017">Buy Here</a></sub></details>|||
|
||||||
|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX 2020-21">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>|||
|
||||||
|Lexus|NX Hybrid 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX Hybrid 2018-19">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>|||
|
||||||
|Lexus|NX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=NX Hybrid 2020-21">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>|||
|
||||||
|Lexus|RC 2018-20|All|Stock|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RC 2018-20">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>||
|
||||||
|Lexus|RC 2023|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RC 2023">Buy Here</a></sub></details>|||
|
|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>||
|
||||||
|Lexus|RX 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX 2016">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>|||
|
||||||
|Lexus|RX 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX 2017-19">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>|||
|
||||||
|Lexus|RX 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX 2020-22">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>|||
|
||||||
|Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2016">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>|||
|
||||||
|Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2017-19">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>|||
|
||||||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=RX Hybrid 2020-22">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>||
|
||||||
|Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lexus&model=UX Hybrid 2019-24">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>|||
|
||||||
|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator 2020-24">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>|||
|
||||||
|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 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Lincoln&model=Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>|||
|
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[<sup>2</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=Lexus CT Hybrid 2017-18">Buy Here</a></sub></details>|||
|
||||||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=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>||
|
|Lexus|ES 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=MAN&model=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>||
|
|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>|||
|
||||||
|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=CX-5 2022-25">Buy Here</a></sub></details>|||
|
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Mazda&model=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>||
|
|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>||
|
||||||
|Nissan[<sup>7</sup>](#footnotes)|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Altima 2019-20">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>|||
|
||||||
|Nissan[<sup>7</sup>](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=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>||
|
|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>|||
|
||||||
|Nissan[<sup>7</sup>](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=Rogue 2018-20">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>|||
|
||||||
|Nissan[<sup>7</sup>](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Nissan&model=X-Trail 2017">Buy Here</a></sub></details>|||
|
|Lexus|LC 2024-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 LC 2024-25">Buy Here</a></sub></details>|||
|
||||||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ram connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Ram&model=1500 2019-24">Buy Here</a></sub></details>|||
|
|Lexus|NX 2018-19|All|openpilot available[<sup>2</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=Lexus NX 2018-19">Buy Here</a></sub></details>|||
|
||||||
|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Rivian A connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Rivian&model=R1S 2022-24">Buy Here</a></sub></details>||https://youtu.be/uaISd1j7Z4U|
|
|Lexus|NX 2020-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=Lexus NX 2020-21">Buy Here</a></sub></details>|||
|
||||||
|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Rivian A connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Rivian&model=R1T 2022-24">Buy Here</a></sub></details>||https://youtu.be/uaISd1j7Z4U|
|
|Lexus|NX Hybrid 2018-19|All|openpilot available[<sup>2</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=Lexus NX Hybrid 2018-19">Buy Here</a></sub></details>|||
|
||||||
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Ateca 2016-23">Buy Here</a></sub></details>|||
|
|Lexus|NX Hybrid 2020-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=Lexus NX Hybrid 2020-21">Buy Here</a></sub></details>|||
|
||||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=SEAT&model=Leon 2014-20">Buy Here</a></sub></details>|||
|
|Lexus|RC 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=Lexus RC 2018-20">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Ascent 2019-21|All[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>|||
|
|Lexus|RC 2023|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 RC 2023">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>||
|
|Lexus|RX 2016|Lexus Safety System+|openpilot available[<sup>2</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=Lexus RX 2016">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>|||
|
|Lexus|RX 2017-19|All|openpilot available[<sup>2</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=Lexus RX 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Forester 2019-21|All[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>|||
|
|Lexus|RX 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=Lexus RX 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 2017-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>|||
|
|Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[<sup>2</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=Lexus RX Hybrid 2016">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Impreza 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>|||
|
|Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</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=Lexus RX Hybrid 2017-19">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Legacy 2020-22|All[<sup>8</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=Legacy 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>|||
|
|Lexus|RX 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=Lexus RX Hybrid 2020-22">Buy Here</a></sub></details>|||
|
||||||
|Subaru|Outback 2020-22|All[<sup>8</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>|||
|
|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>|||
|
||||||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>||
|
|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>|||
|
||||||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>8</sup>](#footnotes)|openpilot available[<sup>1,9</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Subaru&model=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>|||
|
|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>|||
|
||||||
|Škoda|Fabia 2022-23[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Fabia 2022-23">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|MAN|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 USB-C coupler<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>||
|
||||||
|Škoda|Kamiq 2021-23[<sup>13,15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kamiq 2021-23">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|MAN|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 USB-C coupler<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>||
|
||||||
|Škoda|Karoq 2019-23[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Karoq 2019-23">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>|||
|
||||||
|Škoda|Kodiaq 2017-23[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Kodiaq 2017-23">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>||
|
||||||
|Škoda|Octavia 2015-19[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia 2015-19">Buy Here</a></sub></details>|||
|
|Nissan[<sup>6</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 USB-C coupler<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>|||
|
||||||
|Škoda|Octavia RS 2016[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia RS 2016">Buy Here</a></sub></details>|||
|
|Nissan[<sup>6</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 USB-C coupler<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>||
|
||||||
|Škoda|Octavia Scout 2017-19[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Octavia Scout 2017-19">Buy Here</a></sub></details>|||
|
|Nissan[<sup>6</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 USB-C coupler<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>|||
|
||||||
|Škoda|Scala 2020-23[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Scala 2020-23">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|Nissan[<sup>6</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 USB-C coupler<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>|||
|
||||||
|Škoda|Superb 2015-22[<sup>15</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Škoda&model=Superb 2015-22">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>|||
|
||||||
|Tesla[<sup>11</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>10</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Tesla A connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Tesla&model=Model 3 (with HW3) 2019-23">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>|||
|
||||||
|Tesla[<sup>11</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>10</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Tesla B connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Tesla&model=Model 3 (with HW4) 2024-25">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>|||
|
||||||
|Tesla[<sup>11</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>10</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Tesla A connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Tesla&model=Model Y (with HW3) 2020-23">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 USB-C coupler<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>|
|
||||||
|Tesla[<sup>11</sup>](#footnotes)|Model Y (with HW4) 2024[<sup>10</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Tesla B connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Tesla&model=Model Y (with HW4) 2024">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 USB-C coupler<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>|
|
||||||
|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Alphard 2019-20">Buy Here</a></sub></details>|||
|
|SEAT|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 USB-C coupler<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>|||
|
||||||
|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Alphard Hybrid 2021">Buy Here</a></sub></details>|||
|
|SEAT|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 USB-C coupler<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>|||
|
||||||
|Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon 2016">Buy Here</a></sub></details>|||
|
|Subaru|Ascent 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>|||
|
||||||
|Toyota|Avalon 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon 2017-18">Buy Here</a></sub></details>|||
|
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>||
|
||||||
|Toyota|Avalon 2019-21|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon 2019-21">Buy Here</a></sub></details>|||
|
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>|||
|
||||||
|Toyota|Avalon 2022|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon 2022">Buy Here</a></sub></details>|||
|
|Subaru|Forester 2017-18|EyeSight Driver Assistance[<sup>7</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>|||
|
||||||
|Toyota|Avalon Hybrid 2019-21|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon Hybrid 2019-21">Buy Here</a></sub></details>|||
|
|Subaru|Forester 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>|||
|
||||||
|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Avalon Hybrid 2022">Buy Here</a></sub></details>|||
|
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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 Impreza 2017-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>|||
|
||||||
|Toyota|C-HR 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR 2017-20">Buy Here</a></sub></details>|||
|
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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 Impreza 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>|||
|
||||||
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR 2021">Buy Here</a></sub></details>|||
|
|Subaru|Legacy 2015-18|EyeSight Driver Assistance[<sup>7</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 Legacy 2015-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>|||
|
||||||
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR Hybrid 2017-20">Buy Here</a></sub></details>|||
|
|Subaru|Legacy 2020-22|All[<sup>7</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 Legacy 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>|||
|
||||||
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=C-HR Hybrid 2021-22">Buy Here</a></sub></details>|||
|
|Subaru|Outback 2015-17|EyeSight Driver Assistance[<sup>7</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>|||
|
||||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>12</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Subaru|Outback 2018-19|EyeSight Driver Assistance[<sup>7</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>|||
|
||||||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>12</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry 2021-24">Buy Here</a></sub></details>|||
|
|Subaru|Outback 2020-22|All[<sup>7</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>|||
|
||||||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>||
|
||||||
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Camry Hybrid 2021-24">Buy Here</a></sub></details>|||
|
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</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>|||
|
||||||
|Toyota|Corolla 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla 2017-19">Buy Here</a></sub></details>|||
|
|Š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 USB-C coupler<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)|||
|
||||||
|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Š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 USB-C coupler<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)|||
|
||||||
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>|||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla Cross Hybrid (Non-US only) 2020-22">Buy Here</a></sub></details>|||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla Hybrid 2020-22">Buy Here</a></sub></details>|||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Corolla Hybrid (South America only) 2020-23">Buy Here</a></sub></details>|||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Š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 USB-C coupler<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)|||
|
||||||
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Highlander 2020-23">Buy Here</a></sub></details>|||
|
|Škoda|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 USB-C coupler<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>|||
|
||||||
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Highlander Hybrid 2017-19">Buy Here</a></sub></details>|||
|
|Tesla[<sup>10</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>9</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 USB-C coupler<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>|||
|
||||||
|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Highlander Hybrid 2020-23">Buy Here</a></sub></details>|||
|
|Tesla[<sup>10</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>9</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 USB-C coupler<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>|||
|
||||||
|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Mirai 2021">Buy Here</a></sub></details>|||
|
|Tesla[<sup>10</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>9</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 USB-C coupler<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>|||
|
||||||
|Toyota|Prius 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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>||
|
|Tesla[<sup>10</sup>](#footnotes)|Model Y (with HW4) 2024-25[<sup>9</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 USB-C coupler<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 HW4) 2024-25">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius 2017-20|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Alphard 2019-20|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 Alphard 2019-20">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Alphard Hybrid 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 Alphard Hybrid 2021">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius Prime 2017-20|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Avalon 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|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 Avalon 2016">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Avalon 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|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 Avalon 2017-18">Buy Here</a></sub></details>|||
|
||||||
|Toyota|Prius v 2017|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=Prius v 2017">Buy Here</a></sub></details>|||
|
|Toyota|Avalon 2019-21|All|openpilot available[<sup>2</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 Avalon 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2016">Buy Here</a></sub></details>|||
|
|Toyota|Avalon 2022|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 Avalon 2022">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2017-18">Buy Here</a></sub></details>|||
|
|Toyota|Avalon Hybrid 2019-21|All|openpilot available[<sup>2</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 Avalon Hybrid 2019-21">Buy Here</a></sub></details>|||
|
||||||
|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Avalon Hybrid 2022|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 Avalon Hybrid 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 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2022">Buy Here</a></sub></details>|||
|
|Toyota|C-HR 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 2017-20">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 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 2023-25">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|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|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|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|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|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=RAV4 Hybrid 2019-21">Buy Here</a></sub></details>|||
|
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>11</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|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|Camry 2021-24|All|openpilot|0 mph[<sup>11</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|RAV4 Hybrid 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|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|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Toyota&model=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|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>|||
|
||||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|Toyota|Corolla 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|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>||
|
||||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|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>|||
|
||||||
|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|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>|||
|
||||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas 2018-23">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>||
|
||||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Atlas Cross Sport 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>|||
|
||||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=California 2021-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>|||
|
||||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Caravelle 2020">Buy Here</a></sub></details>|||
|
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|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>||
|
||||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|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>|||
|
||||||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|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>|||
|
||||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=e-Golf 2014-20">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>|||
|
||||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf 2015-20">Buy Here</a></sub></details>|||
|
|Toyota|Prius 2016|Toyota Safety Sense P|openpilot available[<sup>2</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 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>||
|
||||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf Alltrack 2015-19">Buy Here</a></sub></details>|||
|
|Toyota|Prius 2017-20|All|openpilot available[<sup>2</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 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>||
|
||||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTD 2015-20">Buy Here</a></sub></details>|||
|
|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>||
|
||||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTE 2015-20">Buy Here</a></sub></details>|||
|
|Toyota|Prius Prime 2017-20|All|openpilot available[<sup>2</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 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>||
|
||||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf GTI 2015-21">Buy Here</a></sub></details>|||
|
|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>||
|
||||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf R 2015-19">Buy Here</a></sub></details>|||
|
|Toyota|Prius v 2017|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Golf SportsVan 2015-20">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=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>||
|
|Toyota|RAV4 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|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>|||
|
||||||
|Volkswagen|Jetta 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta 2018-23">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>||
|
||||||
|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Jetta GLI 2021-23">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>|||
|
||||||
|Volkswagen|Passat 2015-22[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat 2015-22">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>|||
|
||||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat Alltrack 2015-22">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|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>||
|
||||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Passat GTE 2015-22">Buy Here</a></sub></details>|||
|
|Toyota|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|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>||
|
||||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo 2018-23">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|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>|||
|
||||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|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>||
|
||||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Cross 2021">Buy Here</a></sub></details>[<sup>17</sup>](#footnotes)|||
|
|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>||
|
||||||
|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=T-Roc 2018-23">Buy Here</a></sub></details>|||
|
|Toyota|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|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>||
|
||||||
|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Taos 2022-24">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont 2018-22">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont Cross Sport 2021-22">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Teramont X 2021-22">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan 2018-24">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Tiguan eHybrid 2021-23">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,16</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Volkswagen&model=Touran 2016-23">Buy Here</a></sub></details>|||
|
|Volkswagen|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 USB-C coupler<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,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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|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 USB-C coupler<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|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 USB-C coupler<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|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 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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|Jetta 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 USB-C coupler<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 2018-23">Buy Here</a></sub></details>|||
|
||||||
|
|Volkswagen|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 USB-C coupler<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>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 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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,15</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<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 `devel` or `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 `devel` or `nightly-dev`. <br />
|
||||||
@@ -327,18 +356,17 @@ A supported vehicle is one that just works when you install a comma device. All
|
|||||||
<sup>3</sup>Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in North and South America/Southeast Asia. <br />
|
<sup>3</sup>Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in North and South America/Southeast Asia. <br />
|
||||||
<sup>4</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/gm" target="_blank">GM</a>. <br />
|
<sup>4</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/gm" target="_blank">GM</a>. <br />
|
||||||
<sup>5</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
|
<sup>5</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
|
||||||
<sup>6</sup>Requires a <a href="https://comma.ai/shop/can-fd-panda-kit" target="_blank">CAN FD panda kit</a> if not using comma 3X for this <a href="https://en.wikipedia.org/wiki/CAN_FD" target="_blank">CAN FD car</a>. <br />
|
<sup>6</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/nissan" target="_blank">Nissan</a>. <br />
|
||||||
<sup>7</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/nissan" target="_blank">Nissan</a>. <br />
|
<sup>7</sup>In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance. <br />
|
||||||
<sup>8</sup>In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance. <br />
|
<sup>8</sup>Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB. <br />
|
||||||
<sup>9</sup>Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB. <br />
|
<sup>9</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>10</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>10</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
|
||||||
<sup>11</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
|
<sup>11</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>12</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>12</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||||
<sup>13</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <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>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <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>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality. <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>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 />
|
||||||
<sup>17</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/).
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ Development is coordinated through [Discord](https://discord.comma.ai) and GitHu
|
|||||||
|
|
||||||
### Getting Started
|
### Getting Started
|
||||||
|
|
||||||
* Setup your [development environment](../tools/)
|
* Set up your [development environment](/tools/)
|
||||||
* Join our [Discord](https://discord.comma.ai)
|
* Join our [Discord](https://discord.comma.ai)
|
||||||
* Docs are at https://docs.comma.ai and https://blog.comma.ai
|
* Docs are at https://docs.comma.ai and https://blog.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's lot of bounties that don't require a comma 3/3X or a car.
|
There's lot of bounties that don't require a comma 3X or a car.
|
||||||
|
|
||||||
## Pull Requests
|
## Pull Requests
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
# Debugging Panda Safety with Replay Drive + LLDB
|
||||||
|
|
||||||
|
## 1. Start the debugger in VS Code
|
||||||
|
|
||||||
|
* Select **Replay drive + Safety LLDB**.
|
||||||
|
* Enter the route or segment when prompted.
|
||||||
|
[<img src="https://github.com/user-attachments/assets/b0cc320a-083e-46a7-a9f8-ca775bbe5604">](https://github.com/user-attachments/assets/b0cc320a-083e-46a7-a9f8-ca775bbe5604)
|
||||||
|
|
||||||
|
## 2. Attach LLDB
|
||||||
|
|
||||||
|
* When prompted, pick the running **`replay_drive` process**.
|
||||||
|
* ⚠️ Attach quickly, or `replay_drive` will start consuming messages.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> Add a Python breakpoint at the start of `replay_drive.py` to pause execution and give yourself time to attach LLDB.
|
||||||
|
|
||||||
|
## 3. Set breakpoints in VS Code
|
||||||
|
Breakpoints can be set directly in `modes/xxx.h` (or any C file).
|
||||||
|
No extra LLDB commands are required — just place breakpoints in the editor.
|
||||||
|
|
||||||
|
## 4. Resume execution
|
||||||
|
Once attached, you can step through both Python (on the replay) and C safety code as CAN logs are replayed.
|
||||||
|
|
||||||
|
> [!NOTE]
|
||||||
|
> * Use short routes for quicker iteration.
|
||||||
|
> * Pause `replay_drive` early to avoid wasting log messages.
|
||||||
|
|
||||||
|
## Video
|
||||||
|
|
||||||
|
View a demo of this workflow on the PR that added it: https://github.com/commaai/openpilot/pull/36055#issue-3352911578
|
||||||
+14
-4
@@ -16,7 +16,7 @@ industry standards of safety for Level 2 Driver Assistance Systems. In particula
|
|||||||
ISO26262 guidelines, including those from [pertinent documents](https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/13498a_812_573_alcsystemreport.pdf)
|
ISO26262 guidelines, including those from [pertinent documents](https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/13498a_812_573_alcsystemreport.pdf)
|
||||||
released by NHTSA. In addition, we impose strict coding guidelines (like [MISRA C : 2012](https://www.misra.org.uk/what-is-misra/))
|
released by NHTSA. In addition, we impose strict coding guidelines (like [MISRA C : 2012](https://www.misra.org.uk/what-is-misra/))
|
||||||
on parts of openpilot that are safety relevant. We also perform software-in-the-loop,
|
on parts of openpilot that are safety relevant. We also perform software-in-the-loop,
|
||||||
hardware-in-the-loop and in-vehicle tests before each software release.
|
hardware-in-the-loop, and in-vehicle tests before each software release.
|
||||||
|
|
||||||
Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot
|
Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot
|
||||||
ensuring two main safety requirements.
|
ensuring two main safety requirements.
|
||||||
@@ -29,8 +29,18 @@ ensuring two main safety requirements.
|
|||||||
|
|
||||||
For additional safety implementation details, refer to [panda safety model](https://github.com/commaai/panda#safety-model). For vehicle specific implementation of the safety concept, refer to [opendbc/safety/safety](https://github.com/commaai/opendbc/tree/master/opendbc/safety/safety).
|
For additional safety implementation details, refer to [panda safety model](https://github.com/commaai/panda#safety-model). For vehicle specific implementation of the safety concept, refer to [opendbc/safety/safety](https://github.com/commaai/opendbc/tree/master/opendbc/safety/safety).
|
||||||
|
|
||||||
**Extra note**: comma.ai strongly discourages the use of openpilot forks with safety code either missing or
|
[^1]: For these actuator limits we observe ISO11270 and ISO15622. Lateral limits described there translate to 0.9 seconds of maximum actuation to achieve a 1m lateral deviation.
|
||||||
not fully meeting the above requirements.
|
|
||||||
|
|
||||||
[^1]: For these actuator limits we observe ISO11270 and ISO15622. Lateral limits described there translate to 0.9 seconds of maximum actuation to achieve a 1m lateral deviation.
|
---
|
||||||
|
|
||||||
|
### Forks of openpilot
|
||||||
|
|
||||||
|
* Do not disable or nerf [driver monitoring](https://github.com/commaai/openpilot/tree/master/selfdrive/monitoring)
|
||||||
|
* Do not disable or nerf [excessive actuation checks](https://github.com/commaai/openpilot/tree/master/selfdrive/selfdrived/helpers.py)
|
||||||
|
* If your fork modifies any of the code in `opendbc/safety/`:
|
||||||
|
* your fork cannot use the openpilot trademark
|
||||||
|
* your fork must preserve the full [safety test suite](https://github.com/commaai/opendbc/tree/master/opendbc/safety/tests) and all tests must pass, including any new coverage required by the fork's changes
|
||||||
|
|
||||||
|
Failure to comply with these standards will get you and your users banned from comma.ai servers.
|
||||||
|
|
||||||
|
**comma.ai strongly discourages the use of openpilot forks with safety code either missing or not fully meeting the above requirements.**
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# 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`
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# 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,11 +1,11 @@
|
|||||||
# connect to a comma 3/3X
|
# connect to a comma 3X
|
||||||
|
|
||||||
A comma 3/3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console).
|
A comma 3X is a normal [Linux](https://github.com/commaai/agnos-builder) computer that exposes [SSH](https://wiki.archlinux.org/title/Secure_Shell) and a [serial console](https://wiki.archlinux.org/title/Working_with_the_serial_console).
|
||||||
|
|
||||||
## Serial Console
|
## Serial Console
|
||||||
|
|
||||||
On both the comma three and 3X, the serial console is accessible from the main OBD-C port.
|
On both the comma three and 3X, the serial console is accessible from the main OBD-C port.
|
||||||
Connect the comma 3/3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power.
|
Connect the comma 3X to your computer with a normal USB C cable, or use a [comma serial](https://comma.ai/shop/comma-serial) for steady 12V power.
|
||||||
|
|
||||||
On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/scripts/serial.sh` can be used to connect.
|
On the comma three, the serial console is exposed through a UART-to-USB chip, and `tools/scripts/serial.sh` can be used to connect.
|
||||||
|
|
||||||
@@ -45,7 +45,7 @@ In order to use ADB on your device, you'll need to perform the following steps u
|
|||||||
* Here's an example command for connecting to your device using its tethered connection: `adb connect 192.168.43.1:5555`
|
* 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 3/3X.
|
> The default port for ADB is 5555 on the comma 3X.
|
||||||
|
|
||||||
For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb).
|
For more info on ADB, see the [Android Debug Bridge (ADB) documentation](https://developer.android.com/tools/adb).
|
||||||
|
|
||||||
|
|||||||
@@ -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 3/3X*
|
*Hardware required: jungle and comma 3X*
|
||||||
|
|
||||||
1. Connect your PC to a jungle.
|
1. Connect your PC to a jungle.
|
||||||
2.
|
2.
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
# Turn the speed blue
|
# Turn the speed blue
|
||||||
*A getting started guide for openpilot development*
|
*A getting started guide for openpilot development*
|
||||||
|
|
||||||
In 30 minutes, we'll get an openpilot development environment setup 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 3/3X, we'll deploy the change to your device for testing.
|
And if you have a comma 3X, we'll deploy the change to your device for testing.
|
||||||
|
|
||||||
## 1. Setup your development environment
|
## 1. Set up your development environment
|
||||||
|
|
||||||
Run this to clone openpilot and install all the dependencies:
|
Run this to clone openpilot and install all the dependencies:
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
+10
-1
@@ -6,8 +6,17 @@ export NUMEXPR_NUM_THREADS=1
|
|||||||
export OPENBLAS_NUM_THREADS=1
|
export OPENBLAS_NUM_THREADS=1
|
||||||
export VECLIB_MAXIMUM_THREADS=1
|
export VECLIB_MAXIMUM_THREADS=1
|
||||||
|
|
||||||
|
# models get lower priority than ui
|
||||||
|
# - ui is ~5ms
|
||||||
|
# - modeld is 20ms
|
||||||
|
# - DM is 10ms
|
||||||
|
# in order to run ui at 60fps (16.67ms), we need to allow
|
||||||
|
# it to preempt the model workloads. we have enough
|
||||||
|
# headroom for this until ui is moved to the CPU.
|
||||||
|
export QCOM_PRIORITY=12
|
||||||
|
|
||||||
if [ -z "$AGNOS_VERSION" ]; then
|
if [ -z "$AGNOS_VERSION" ]; then
|
||||||
export AGNOS_VERSION="12.4"
|
export AGNOS_VERSION="15.1"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
export STAGING_ROOT="/data/safe_staging"
|
export STAGING_ROOT="/data/safe_staging"
|
||||||
|
|||||||
@@ -1,3 +1,20 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
IFS=$'\n\t'
|
||||||
|
|
||||||
|
# On any failure, run the fallback launcher
|
||||||
|
trap 'exec ./launch_chffrplus.sh' ERR
|
||||||
|
C3_LAUNCH_SH="./sunnypilot/system/hardware/c3/launch_chffrplus.sh"
|
||||||
|
|
||||||
|
MODEL="$(tr -d '\0' < "/sys/firmware/devicetree/base/model")"
|
||||||
|
export MODEL
|
||||||
|
|
||||||
|
if [ "$MODEL" = "comma tici" ]; then
|
||||||
|
# Force a failure if the launcher doesn't exist
|
||||||
|
[ -x "$C3_LAUNCH_SH" ] || false
|
||||||
|
|
||||||
|
# If it exists, run it
|
||||||
|
exec "$C3_LAUNCH_SH"
|
||||||
|
fi
|
||||||
|
|
||||||
exec ./launch_chffrplus.sh
|
exec ./launch_chffrplus.sh
|
||||||
|
|||||||
+1
-1
@@ -21,7 +21,7 @@ nav:
|
|||||||
- What is openpilot?: getting-started/what-is-openpilot.md
|
- What is openpilot?: getting-started/what-is-openpilot.md
|
||||||
- How-to:
|
- How-to:
|
||||||
- Turn the speed blue: how-to/turn-the-speed-blue.md
|
- Turn the speed blue: how-to/turn-the-speed-blue.md
|
||||||
- Connect to a comma 3/3X: how-to/connect-to-comma.md
|
- Connect to a comma 3X: how-to/connect-to-comma.md
|
||||||
# - Make your first pull request: how-to/make-first-pr.md
|
# - Make your first pull request: how-to/make-first-pr.md
|
||||||
#- Replay a drive: how-to/replay-a-drive.md
|
#- Replay a drive: how-to/replay-a-drive.md
|
||||||
- Concepts:
|
- Concepts:
|
||||||
|
|||||||
+1
-1
Submodule msgq_repo updated: fd7bd0df50...a16cf1f608
+1
-1
Submodule opendbc_repo updated: 682c5f274d...61bf5a90c5
+1
-1
Submodule panda updated: c33cfa0803...dee9061b2a
+24
-15
@@ -23,10 +23,10 @@ dependencies = [
|
|||||||
# core
|
# core
|
||||||
"cffi",
|
"cffi",
|
||||||
"scons",
|
"scons",
|
||||||
"pycapnp",
|
"pycapnp==2.1.0",
|
||||||
"Cython",
|
"Cython",
|
||||||
"setuptools",
|
"setuptools",
|
||||||
"numpy >=2.0, <2.2", # Linting issues with mypy in 2.2
|
"numpy >=2.0",
|
||||||
|
|
||||||
# body / webrtcd
|
# body / webrtcd
|
||||||
"aiohttp",
|
"aiohttp",
|
||||||
@@ -36,13 +36,15 @@ dependencies = [
|
|||||||
"pyopenssl < 24.3.0",
|
"pyopenssl < 24.3.0",
|
||||||
"pyaudio",
|
"pyaudio",
|
||||||
|
|
||||||
|
# ubloxd (TODO: just use struct)
|
||||||
|
"kaitaistruct",
|
||||||
|
|
||||||
# panda
|
# panda
|
||||||
"libusb1",
|
"libusb1",
|
||||||
"spidev; platform_system == 'Linux'",
|
"spidev; platform_system == 'Linux'",
|
||||||
|
|
||||||
# modeld
|
# modeld
|
||||||
"onnx >= 1.14.0",
|
"onnx >= 1.14.0",
|
||||||
"llvmlite",
|
|
||||||
|
|
||||||
# logging
|
# logging
|
||||||
"pyzmq",
|
"pyzmq",
|
||||||
@@ -59,7 +61,7 @@ dependencies = [
|
|||||||
"future-fstrings",
|
"future-fstrings",
|
||||||
|
|
||||||
# joystickd
|
# joystickd
|
||||||
"pygame",
|
"inputs",
|
||||||
|
|
||||||
# these should be removed
|
# these should be removed
|
||||||
"psutil",
|
"psutil",
|
||||||
@@ -70,7 +72,9 @@ dependencies = [
|
|||||||
"zstandard",
|
"zstandard",
|
||||||
|
|
||||||
# ui
|
# ui
|
||||||
|
"raylib < 5.5.0.3", # TODO: unpin when they fix https://github.com/electronstudio/raylib-python-cffi/issues/186
|
||||||
"qrcode",
|
"qrcode",
|
||||||
|
"mapbox-earcut",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.optional-dependencies]
|
[project.optional-dependencies]
|
||||||
@@ -86,8 +90,8 @@ testing = [
|
|||||||
"pytest",
|
"pytest",
|
||||||
"pytest-cpp",
|
"pytest-cpp",
|
||||||
"pytest-subtests",
|
"pytest-subtests",
|
||||||
# https://github.com/pytest-dev/pytest-xdist/issues/1215
|
# https://github.com/pytest-dev/pytest-xdist/pull/1229
|
||||||
"pytest-xdist @ git+https://github.com/sshane/pytest-xdist@909e97b49d12401c10608f9d777bfc9dab8a4413",
|
"pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da",
|
||||||
"pytest-timeout",
|
"pytest-timeout",
|
||||||
"pytest-randomly",
|
"pytest-randomly",
|
||||||
"pytest-asyncio",
|
"pytest-asyncio",
|
||||||
@@ -102,12 +106,14 @@ dev = [
|
|||||||
"av",
|
"av",
|
||||||
"azure-identity",
|
"azure-identity",
|
||||||
"azure-storage-blob",
|
"azure-storage-blob",
|
||||||
"dbus-next",
|
"dbus-next", # TODO: remove once we moved everything to jeepney
|
||||||
"dictdiffer",
|
"dictdiffer",
|
||||||
|
"jeepney",
|
||||||
"matplotlib",
|
"matplotlib",
|
||||||
"opencv-python-headless",
|
"opencv-python-headless",
|
||||||
"parameterized >=0.8, <0.9",
|
"parameterized >=0.8, <0.9",
|
||||||
"pyautogui",
|
"pyautogui",
|
||||||
|
"pygame",
|
||||||
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
|
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
|
||||||
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
|
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
|
||||||
"pywinctl",
|
"pywinctl",
|
||||||
@@ -115,12 +121,11 @@ dev = [
|
|||||||
"tabulate",
|
"tabulate",
|
||||||
"types-requests",
|
"types-requests",
|
||||||
"types-tabulate",
|
"types-tabulate",
|
||||||
"raylib",
|
|
||||||
]
|
]
|
||||||
|
|
||||||
tools = [
|
tools = [
|
||||||
"metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')",
|
"metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')",
|
||||||
"rerun-sdk >= 0.18",
|
"dearpygui>=2.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
@@ -152,12 +157,12 @@ markers = [
|
|||||||
testpaths = [
|
testpaths = [
|
||||||
"common",
|
"common",
|
||||||
"selfdrive",
|
"selfdrive",
|
||||||
|
"system/manager",
|
||||||
"system/updated",
|
"system/updated",
|
||||||
"system/athena",
|
"system/athena",
|
||||||
"system/camerad",
|
"system/camerad",
|
||||||
"system/hardware",
|
"system/hardware",
|
||||||
"system/loggerd",
|
"system/loggerd",
|
||||||
"system/proclogd",
|
|
||||||
"system/tests",
|
"system/tests",
|
||||||
"system/ubloxd",
|
"system/ubloxd",
|
||||||
"system/webrtc",
|
"system/webrtc",
|
||||||
@@ -173,13 +178,10 @@ 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"
|
ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn,ws,uint,grey,deque,stdio,amin,BA,LITE,atEnd,UIs,errorString,arange,FocusIn,od,tim,relA,hist,copyable,jupyter,thead,TGE,abl,lite"
|
||||||
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
|
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
|
||||||
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.ts, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*"
|
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*, selfdrive/assets/offroad/mici_fcc.html"
|
||||||
|
|
||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
python_version = "3.11"
|
python_version = "3.11"
|
||||||
plugins = [
|
|
||||||
"numpy.typing.mypy_plugin",
|
|
||||||
]
|
|
||||||
exclude = [
|
exclude = [
|
||||||
"cereal/",
|
"cereal/",
|
||||||
"msgq/",
|
"msgq/",
|
||||||
@@ -234,7 +236,7 @@ lint.ignore = [
|
|||||||
"B027",
|
"B027",
|
||||||
"B024",
|
"B024",
|
||||||
"NPY002", # new numpy random syntax is worse
|
"NPY002", # new numpy random syntax is worse
|
||||||
"UP038", # (x, y) -> x|y for isinstance
|
"UP045", "UP007", # these don't play nice with raylib atm
|
||||||
]
|
]
|
||||||
line-length = 160
|
line-length = 160
|
||||||
target-version ="py311"
|
target-version ="py311"
|
||||||
@@ -250,6 +252,7 @@ exclude = [
|
|||||||
"teleoprtc_repo",
|
"teleoprtc_repo",
|
||||||
"third_party",
|
"third_party",
|
||||||
"*.ipynb",
|
"*.ipynb",
|
||||||
|
"generated",
|
||||||
]
|
]
|
||||||
lint.flake8-implicit-str-concat.allow-multiline = false
|
lint.flake8-implicit-str-concat.allow-multiline = false
|
||||||
|
|
||||||
@@ -261,7 +264,13 @@ lint.flake8-implicit-str-concat.allow-multiline = false
|
|||||||
"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"
|
||||||
|
"time.time".msg = "Use time.monotonic"
|
||||||
|
|
||||||
|
# raylib banned APIs
|
||||||
"pyray.measure_text_ex".msg = "Use openpilot.system.ui.lib.text_measure"
|
"pyray.measure_text_ex".msg = "Use openpilot.system.ui.lib.text_measure"
|
||||||
|
"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.draw_text".msg = "Use a function (such as rl.draw_font_ex) that takes font as an argument"
|
||||||
|
|
||||||
[tool.ruff.format]
|
[tool.ruff.format]
|
||||||
quote-style = "preserve"
|
quote-style = "preserve"
|
||||||
|
|||||||
+15
-10
@@ -3,29 +3,34 @@
|
|||||||
```
|
```
|
||||||
## release checklist
|
## release checklist
|
||||||
|
|
||||||
**Go to `devel-staging`**
|
### Go to staging
|
||||||
|
- [ ] make a GitHub issue to track release
|
||||||
|
- [ ] create release master branch
|
||||||
- [ ] update RELEASES.md
|
- [ ] update RELEASES.md
|
||||||
- [ ] update `devel-staging`: `git reset --hard origin/master-ci`
|
|
||||||
- [ ] open a pull request from `devel-staging` to `devel`
|
|
||||||
- [ ] post on Discord
|
|
||||||
|
|
||||||
**Go to `devel`**
|
|
||||||
- [ ] bump version on master: `common/version.h` and `RELEASES.md`
|
- [ ] bump version on master: `common/version.h` and `RELEASES.md`
|
||||||
- [ ] before merging the pull request
|
- [ ] build new userdata partition from `release3-staging`
|
||||||
|
- [ ] post on Discord, tag `@release crew`
|
||||||
|
|
||||||
|
Updating staging:
|
||||||
|
1. either rebase on master or cherry-pick changes
|
||||||
|
2. run this to update: `BRANCH=devel-staging release/build_devel.sh`
|
||||||
|
3. build new userdata partition from `release3-staging`
|
||||||
|
|
||||||
|
### Go to release
|
||||||
|
- [ ] before going to release, test the following:
|
||||||
- [ ] update from previous release -> new release
|
- [ ] update from previous release -> new release
|
||||||
- [ ] update from new release -> previous release
|
- [ ] update from new release -> previous release
|
||||||
- [ ] fresh install with `openpilot-test.comma.ai`
|
- [ ] fresh install with `openpilot-test.comma.ai`
|
||||||
- [ ] drive on fresh install
|
- [ ] drive on fresh install
|
||||||
- [ ] no submodules or LFS
|
- [ ] no submodules or LFS
|
||||||
- [ ] check sentry, MTBF, etc.
|
- [ ] check sentry, MTBF, etc.
|
||||||
|
- [ ] stress test passes in production
|
||||||
**Go to `release3`**
|
|
||||||
- [ ] publish the blog post
|
- [ ] publish the blog post
|
||||||
- [ ] `git reset --hard origin/release3-staging`
|
- [ ] `git reset --hard origin/release3-staging`
|
||||||
- [ ] tag the release: `git tag v0.X.X <commit-hash> && git push origin v0.X.X`
|
- [ ] tag the release: `git tag v0.X.X <commit-hash> && git push origin v0.X.X`
|
||||||
- [ ] create GitHub release
|
- [ ] create GitHub release
|
||||||
- [ ] final test install on `openpilot.comma.ai`
|
- [ ] final test install on `openpilot.comma.ai`
|
||||||
- [ ] update factory provisioning
|
- [ ] update factory provisioning
|
||||||
- [ ] close out milestone
|
- [ ] close out milestone and issue
|
||||||
- [ ] post on Discord, X, etc.
|
- [ ] post on Discord, X, etc.
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ cd $BUILD_DIR
|
|||||||
rm -f panda/board/obj/panda.bin.signed
|
rm -f panda/board/obj/panda.bin.signed
|
||||||
rm -f panda/board/obj/panda_h7.bin.signed
|
rm -f panda/board/obj/panda_h7.bin.signed
|
||||||
|
|
||||||
VERSION=$(cat common/version.h | awk -F[\"-] '{print $2}')
|
VERSION=$(cat sunnypilot/common/version.h | awk -F[\"-] '{print $2}')
|
||||||
echo "[-] committing version $VERSION T=$SECONDS"
|
echo "[-] committing version $VERSION T=$SECONDS"
|
||||||
git add -f .
|
git add -f .
|
||||||
git commit -a -m "openpilot v$VERSION release"
|
git commit -a -m "openpilot v$VERSION release"
|
||||||
|
|||||||
@@ -17,28 +17,23 @@ rm -rf $TARGET_DIR
|
|||||||
mkdir -p $TARGET_DIR
|
mkdir -p $TARGET_DIR
|
||||||
cd $TARGET_DIR
|
cd $TARGET_DIR
|
||||||
cp -r $SOURCE_DIR/.git $TARGET_DIR
|
cp -r $SOURCE_DIR/.git $TARGET_DIR
|
||||||
pre-commit uninstall || true
|
|
||||||
|
|
||||||
echo "[-] bringing __nightly and devel in sync T=$SECONDS"
|
echo "[-] setting up stripped branch sync T=$SECONDS"
|
||||||
cd $TARGET_DIR
|
cd $TARGET_DIR
|
||||||
|
|
||||||
git fetch --depth 1 origin __nightly
|
# tmp branch
|
||||||
git fetch --depth 1 origin devel
|
git checkout --orphan tmp
|
||||||
|
|
||||||
git checkout -f --track origin/__nightly
|
|
||||||
git reset --hard __nightly
|
|
||||||
git checkout __nightly
|
|
||||||
git reset --hard origin/devel
|
|
||||||
git clean -xdff
|
|
||||||
git lfs uninstall
|
|
||||||
|
|
||||||
# remove everything except .git
|
# remove everything except .git
|
||||||
echo "[-] erasing old openpilot T=$SECONDS"
|
echo "[-] erasing old sunnypilot T=$SECONDS"
|
||||||
|
git submodule deinit -f --all
|
||||||
|
git rm -rf --cached .
|
||||||
find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \;
|
find . -maxdepth 1 -not -path './.git' -not -name '.' -not -name '..' -exec rm -rf '{}' \;
|
||||||
|
|
||||||
# reset source tree
|
# cleanup before the copy
|
||||||
cd $SOURCE_DIR
|
cd $SOURCE_DIR
|
||||||
git clean -xdff
|
git clean -xdff
|
||||||
|
git submodule foreach --recursive git clean -xdff
|
||||||
|
|
||||||
# do the files copy
|
# do the files copy
|
||||||
echo "[-] copying files T=$SECONDS"
|
echo "[-] copying files T=$SECONDS"
|
||||||
@@ -47,13 +42,14 @@ cp -pR --parents $(./release/release_files.py) $TARGET_DIR/
|
|||||||
|
|
||||||
# in the directory
|
# in the directory
|
||||||
cd $TARGET_DIR
|
cd $TARGET_DIR
|
||||||
|
rm -rf .git/modules/
|
||||||
rm -f panda/board/obj/panda.bin.signed
|
rm -f panda/board/obj/panda.bin.signed
|
||||||
|
|
||||||
# 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)
|
||||||
DATETIME=$(date '+%Y-%m-%dT%H:%M:%S')
|
DATETIME=$(date '+%Y-%m-%dT%H:%M:%S')
|
||||||
VERSION=$(cat $SOURCE_DIR/common/version.h | awk -F\" '{print $2}')
|
VERSION=$(cat $SOURCE_DIR/sunnypilot/common/version.h | awk -F\" '{print $2}')
|
||||||
|
|
||||||
echo -n "$GIT_HASH" > git_src_commit
|
echo -n "$GIT_HASH" > git_src_commit
|
||||||
echo -n "$GIT_COMMIT_DATE" > git_src_commit_date
|
echo -n "$GIT_COMMIT_DATE" > git_src_commit_date
|
||||||
@@ -61,7 +57,7 @@ echo -n "$GIT_COMMIT_DATE" > git_src_commit_date
|
|||||||
echo "[-] committing version $VERSION T=$SECONDS"
|
echo "[-] committing version $VERSION T=$SECONDS"
|
||||||
git add -f .
|
git add -f .
|
||||||
git status
|
git status
|
||||||
git commit -a -m "openpilot v$VERSION release
|
git commit -a -m "sunnypilot v$VERSION release
|
||||||
|
|
||||||
date: $DATETIME
|
date: $DATETIME
|
||||||
master commit: $GIT_HASH
|
master commit: $GIT_HASH
|
||||||
@@ -85,7 +81,7 @@ fi
|
|||||||
|
|
||||||
if [ ! -z "$BRANCH" ]; then
|
if [ ! -z "$BRANCH" ]; then
|
||||||
echo "[-] Pushing to $BRANCH T=$SECONDS"
|
echo "[-] Pushing to $BRANCH T=$SECONDS"
|
||||||
git push -f origin __nightly:$BRANCH
|
git push -f origin tmp:$BRANCH
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "[-] done T=$SECONDS, ready at $TARGET_DIR"
|
echo "[-] done T=$SECONDS, ready at $TARGET_DIR"
|
||||||
@@ -1,17 +1,43 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
has_submodule_changes() {
|
||||||
|
local submodule_path="$1"
|
||||||
|
if [ -n "$SUBMODULE_PATHS" ]; then
|
||||||
|
echo "$SUBMODULE_PATHS" | grep -q "$submodule_path"
|
||||||
|
return $?
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
while read hash submodule ref; do
|
while read hash submodule ref; do
|
||||||
|
if [ -z "$hash" ] || [ -z "$submodule" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
hash=$(echo "$hash" | sed 's/^[+-]//')
|
||||||
|
|
||||||
if [ "$submodule" = "tinygrad_repo" ]; then
|
if [ "$submodule" = "tinygrad_repo" ]; then
|
||||||
echo "Skipping $submodule"
|
echo "Skipping $submodule"
|
||||||
continue
|
continue
|
||||||
fi
|
fi
|
||||||
|
|
||||||
git -C $submodule fetch --depth 100 origin master
|
if [ "$CHECK_PR_REFS" = "true" ] && has_submodule_changes "$submodule"; then
|
||||||
git -C $submodule branch -r --contains $hash | grep "origin/master"
|
echo "Checking $submodule (non-master): verifying hash $hash exists"
|
||||||
if [ "$?" -eq 0 ]; then
|
git -C $submodule fetch --depth 100 origin
|
||||||
echo "$submodule ok"
|
if git -C $submodule cat-file -e $hash 2>/dev/null; then
|
||||||
|
echo "$submodule ok (hash exists)"
|
||||||
|
else
|
||||||
|
echo "$submodule: $hash does not exist in the repository"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
echo "$submodule: $hash is not on master"
|
git -C $submodule fetch --depth 100 origin master
|
||||||
exit 1
|
git -C $submodule branch -r --contains $hash | grep "origin/master"
|
||||||
|
if [ "$?" -eq 0 ]; then
|
||||||
|
echo "$submodule ok"
|
||||||
|
else
|
||||||
|
echo "$submodule: $hash is not on master"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
done <<< $(git submodule status --recursive)
|
done <<< $(git submodule status --recursive)
|
||||||
|
|||||||
Executable
+26
@@ -0,0 +1,26 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# To build sim and docs, you can run the following to mount the scons cache to the same place as in CI:
|
||||||
|
# mkdir -p .ci_cache/scons_cache
|
||||||
|
# sudo mount --bind /tmp/scons_cache/ .ci_cache/scons_cache
|
||||||
|
|
||||||
|
SCRIPT_DIR=$(dirname "$0")
|
||||||
|
OPENPILOT_DIR=$SCRIPT_DIR/../../
|
||||||
|
if [ -n "$TARGET_ARCHITECTURE" ]; then
|
||||||
|
PLATFORM="linux/$TARGET_ARCHITECTURE"
|
||||||
|
TAG_SUFFIX="-$TARGET_ARCHITECTURE"
|
||||||
|
else
|
||||||
|
PLATFORM="linux/$(uname -m)"
|
||||||
|
TAG_SUFFIX=""
|
||||||
|
fi
|
||||||
|
|
||||||
|
source $SCRIPT_DIR/docker_common_sp.sh $1 "$TAG_SUFFIX"
|
||||||
|
|
||||||
|
DOCKER_BUILDKIT=1 docker buildx build --provenance false --pull --platform $PLATFORM --load --cache-to type=inline --cache-from type=registry,ref=$REMOTE_TAG -t $DOCKER_IMAGE:latest -t $REMOTE_TAG -t $LOCAL_TAG -f $OPENPILOT_DIR/$DOCKER_FILE $OPENPILOT_DIR
|
||||||
|
|
||||||
|
if [ -n "$PUSH_IMAGE" ]; then
|
||||||
|
docker push $REMOTE_TAG
|
||||||
|
docker tag $REMOTE_TAG $REMOTE_SHA_TAG
|
||||||
|
docker push $REMOTE_SHA_TAG
|
||||||
|
fi
|
||||||
Executable
+18
@@ -0,0 +1,18 @@
|
|||||||
|
if [ "$1" = "base" ]; then
|
||||||
|
export DOCKER_IMAGE=sunnypilot-base
|
||||||
|
export DOCKER_FILE=Dockerfile.sunnypilot_base
|
||||||
|
elif [ "$1" = "prebuilt" ]; then
|
||||||
|
export DOCKER_IMAGE=sunnypilot-prebuilt
|
||||||
|
export DOCKER_FILE=Dockerfile.sunnypilot
|
||||||
|
else
|
||||||
|
echo "Invalid docker build image: '$1'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export DOCKER_REGISTRY=ghcr.io/sunnypilot
|
||||||
|
export COMMIT_SHA=$(git rev-parse HEAD)
|
||||||
|
|
||||||
|
TAG_SUFFIX=$2
|
||||||
|
LOCAL_TAG=$DOCKER_IMAGE$TAG_SUFFIX
|
||||||
|
REMOTE_TAG=$DOCKER_REGISTRY/$LOCAL_TAG
|
||||||
|
REMOTE_SHA_TAG=$DOCKER_REGISTRY/$LOCAL_TAG:$COMMIT_SHA
|
||||||
@@ -13,17 +13,32 @@ def create_short_name(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)]
|
||||||
|
|
||||||
if len(words) == 1:
|
if len(words) == 1:
|
||||||
# If there's only one word, return it as is, lowercased, truncated to 8 characters
|
return words[0][:8].upper()
|
||||||
truncated = words[0][:8]
|
|
||||||
return truncated.lower() if truncated.isupper() else truncated
|
|
||||||
|
|
||||||
# Handle special case: Name + Version (e.g., "Word A1" -> "WordA1")
|
# Handle special case: Name + Version (e.g., "Word A1" -> "WordA1")
|
||||||
if len(words) == 2 and re.match(r'^[A-Za-z]\d+$', words[1]):
|
if len(words) == 2 and re.match(r'^[A-Za-z]\d+$', words[1]):
|
||||||
first_word = words[0].lower() if words[0].isupper() else words[0]
|
return (words[0] + words[1])[:8].upper()
|
||||||
return (first_word + words[1])[:8]
|
|
||||||
|
|
||||||
# Normal case: first letter and trailing numbers from each word
|
result = ""
|
||||||
result = ''.join(word if word.isdigit() else word[0] + (re.search(r'\d+$', word) or [''])[0] for word in words)
|
for word in words:
|
||||||
|
# Version or number patterns
|
||||||
|
if (re.match(r'^\d+[a-zA-Z]+$', word) or
|
||||||
|
re.match(r'^\d+[vVbB]\d+$', word) or
|
||||||
|
re.match(r'^[vVbB]\d+$', word) or
|
||||||
|
re.match(r'^\d{4}$', word)):
|
||||||
|
result += word.upper()
|
||||||
|
# All uppercase abbreviations (2-3 letters)
|
||||||
|
elif re.match(r'^[A-Z]{2,3}$', word):
|
||||||
|
result += word
|
||||||
|
# Letters+digits (for example tr15 rev2)
|
||||||
|
elif re.match(r'^[a-zA-Z]+[0-9]+$', word):
|
||||||
|
result += word[0].upper() + ''.join(re.findall(r'\d+', word))
|
||||||
|
elif word.isalpha():
|
||||||
|
result += word[0].upper()
|
||||||
|
elif word.isdigit():
|
||||||
|
result += word
|
||||||
|
else:
|
||||||
|
result += word[0].upper()
|
||||||
return result[:8]
|
return result[:8]
|
||||||
|
|
||||||
|
|
||||||
@@ -58,14 +73,14 @@ def generate_metadata(model_path: Path, output_dir: Path, short_name: str):
|
|||||||
"artifact": {
|
"artifact": {
|
||||||
"file_name": tinygrad_file.name,
|
"file_name": tinygrad_file.name,
|
||||||
"download_uri": {
|
"download_uri": {
|
||||||
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/<FILLME>",
|
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/",
|
||||||
"sha256": tinygrad_hash
|
"sha256": tinygrad_hash
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"metadata": {
|
"metadata": {
|
||||||
"file_name": metadata_file.name,
|
"file_name": metadata_file.name,
|
||||||
"download_uri": {
|
"download_uri": {
|
||||||
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/<FILLME>",
|
"url": "https://gitlab.com/sunnypilot/public/docs.sunnypilot.ai/-/raw/main/",
|
||||||
"sha256": metadata_hash
|
"sha256": metadata_hash
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -83,12 +98,12 @@ def create_metadata_json(models: list, output_dir: Path, custom_name=None, short
|
|||||||
"ref": upstream_branch,
|
"ref": upstream_branch,
|
||||||
"environment": "development",
|
"environment": "development",
|
||||||
"runner": "tinygrad",
|
"runner": "tinygrad",
|
||||||
"build_time": datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
||||||
"models": models,
|
|
||||||
"overrides": {},
|
|
||||||
"index": -1,
|
"index": -1,
|
||||||
"minimum_selector_version": "-1",
|
"minimum_selector_version": "-1",
|
||||||
"generation": "-1",
|
"generation": "-1",
|
||||||
|
"build_time": datetime.now(UTC).strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||||
|
"overrides": {},
|
||||||
|
"models": models,
|
||||||
}
|
}
|
||||||
|
|
||||||
# Write metadata to output_dir
|
# Write metadata to output_dir
|
||||||
|
|||||||
+9
-16
@@ -30,7 +30,7 @@ if [ -z "$GIT_ORIGIN" ]; then
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# "Tagging"
|
# "Tagging"
|
||||||
echo "#define COMMA_VERSION \"$VERSION\"" > ${OUTPUT_DIR}/common/version.h
|
echo "#define SUNNYPILOT_VERSION \"$VERSION\"" > ${OUTPUT_DIR}/sunnypilot/common/version.h
|
||||||
|
|
||||||
## set git identity
|
## set git identity
|
||||||
#source $DIR/identity.sh
|
#source $DIR/identity.sh
|
||||||
@@ -51,26 +51,19 @@ git fetch origin $DEV_BRANCH || (git checkout -b $DEV_BRANCH && git commit --all
|
|||||||
|
|
||||||
echo "[-] committing version $VERSION T=$SECONDS"
|
echo "[-] committing version $VERSION T=$SECONDS"
|
||||||
git add -f .
|
git add -f .
|
||||||
git commit -a -m "sunnypilot v$VERSION release"
|
|
||||||
git branch --set-upstream-to=origin/$DEV_BRANCH
|
|
||||||
|
|
||||||
# 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)
|
||||||
DATETIME=$(date '+%Y-%m-%dT%H:%M:%S')
|
DATETIME=$(date '+%Y-%m-%dT%H:%M:%S')
|
||||||
SP_VERSION=$(cat $SOURCE_DIR/common/version.h | awk -F\" '{print $2}')
|
SP_VERSION=$(awk -F\" '{print $2}' $SOURCE_DIR/sunnypilot/common/version.h)
|
||||||
|
|
||||||
# Add built files to git
|
# Commit with detailed message
|
||||||
git add -f .
|
git commit -a -m "sunnypilot v$VERSION
|
||||||
if [ "$EXTRA_VERSION_IDENTIFIER" = "-release" ] || [ "$EXTRA_VERSION_IDENTIFIER" = "-staging" ]; then
|
version: sunnypilot v$SP_VERSION (${EXTRA_VERSION_IDENTIFIER})
|
||||||
export VERSION=${VERSION%"$EXTRA_VERSION_IDENTIFIER"}
|
date: $DATETIME
|
||||||
git commit --amend -m "sunnypilot v$VERSION"
|
master commit: $GIT_HASH
|
||||||
else
|
"
|
||||||
git commit --amend -m "sunnypilot v$VERSION
|
git branch --set-upstream-to=origin/$DEV_BRANCH
|
||||||
version: sunnypilot v$SP_VERSION release
|
|
||||||
date: $DATETIME
|
|
||||||
master commit: $GIT_HASH
|
|
||||||
"
|
|
||||||
fi
|
|
||||||
git branch -m $DEV_BRANCH
|
git branch -m $DEV_BRANCH
|
||||||
|
|
||||||
# Push!
|
# Push!
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user