mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-06-11 07:04:40 +08:00
Compare commits
974 Commits
archive/es
...
archive/ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c68c138c0 | ||
|
|
09460711b0 | ||
|
|
6f9401d902 | ||
|
|
4ef757c49f | ||
|
|
155546a668 | ||
|
|
635b15a573 | ||
|
|
edd042f308 | ||
|
|
3dc08fb679 | ||
|
|
ebf4cf4ad0 | ||
|
|
8e598a17fb | ||
|
|
c52126cd6c | ||
|
|
9cec7bbfb3 | ||
|
|
a8299ef800 | ||
|
|
632c484dd5 | ||
|
|
0fecfd6c45 | ||
|
|
7de2aac3c9 | ||
|
|
c95b58401a | ||
|
|
3e41b1b287 | ||
|
|
01c2174d59 | ||
|
|
25b9a33852 | ||
|
|
7fef6970b4 | ||
|
|
a312a102aa | ||
|
|
bda4d2df63 | ||
|
|
cec8d5a305 | ||
|
|
406bcd79e1 | ||
|
|
417f1e2139 | ||
|
|
2059f986df | ||
|
|
a4185042de | ||
|
|
6f10b8a209 | ||
|
|
66e1810c0d | ||
|
|
579b131a6e | ||
|
|
2d3c6cbe04 | ||
|
|
d0423dcab2 | ||
|
|
a74f794213 | ||
|
|
12d5afba73 | ||
|
|
4a70934625 | ||
|
|
69d4b0fdf0 | ||
|
|
649e7a6d55 | ||
|
|
504dd4543d | ||
|
|
b7695c00e8 | ||
|
|
fb6d44797a | ||
|
|
84725738c8 | ||
|
|
046ed7e9f8 | ||
|
|
fccba867a9 | ||
|
|
4c04ae9a59 | ||
|
|
a256898510 | ||
|
|
0c9f1d8118 | ||
|
|
669553aa37 | ||
|
|
9a27512c82 | ||
|
|
36eafc0dc6 | ||
|
|
0922ab2b8d | ||
|
|
b418159833 | ||
|
|
76f7b2793d | ||
|
|
36d5bb7ecc | ||
|
|
dc41848597 | ||
|
|
40bc424426 | ||
|
|
93a6965c18 | ||
|
|
8b7ffc96b5 | ||
|
|
1de7126d34 | ||
|
|
1c5f0bdbc6 | ||
|
|
0c3f1dc016 | ||
|
|
bccccde568 | ||
|
|
8550a57eaf | ||
|
|
5aac2e5a89 | ||
|
|
442e9f4ae4 | ||
|
|
40aa3a0337 | ||
|
|
a132a23574 | ||
|
|
776b08d561 | ||
|
|
77a8094f55 | ||
|
|
7013eed50c | ||
|
|
9a084a73c5 | ||
|
|
5341512fce | ||
|
|
e491c9d964 | ||
|
|
a89201219d | ||
|
|
de75372880 | ||
|
|
151b4530dd | ||
|
|
987b0d9e03 | ||
|
|
5c4ea14a3c | ||
|
|
cb63f101ca | ||
|
|
3de6ee5ee3 | ||
|
|
54da59c1fe | ||
|
|
ab96d12f2e | ||
|
|
a99816a08b | ||
|
|
b99fe718ec | ||
|
|
8de2399680 | ||
|
|
865b98a5c4 | ||
|
|
02ed9c584c | ||
|
|
9ee409cf60 | ||
|
|
02f6a3e279 | ||
|
|
b45caf4033 | ||
|
|
68e22faa29 | ||
|
|
bc303df6a0 | ||
|
|
38529c5057 | ||
|
|
d5ce4b3085 | ||
|
|
a0bbc005b6 | ||
|
|
3ede1e2a7c | ||
|
|
6552d4ecb8 | ||
|
|
15f0ed29b3 | ||
|
|
9ffd973be9 | ||
|
|
f08137f618 | ||
|
|
4708332abe | ||
|
|
06828f1e80 | ||
|
|
0319379431 | ||
|
|
f449ed144e | ||
|
|
2c10fc3f56 | ||
|
|
04a93dd849 | ||
|
|
4539c97349 | ||
|
|
742a3a94e3 | ||
|
|
a9f879bc99 | ||
|
|
9e63be9ba2 | ||
|
|
7dbf60b4bc | ||
|
|
c64bca97ba | ||
|
|
8065b454c9 | ||
|
|
e798caa3e5 | ||
|
|
83ac80c6c8 | ||
|
|
81dc33e569 | ||
|
|
684209e077 | ||
|
|
0bdab82423 | ||
|
|
ddfb31f1bf | ||
|
|
05669df102 | ||
|
|
188843533f | ||
|
|
0e39d5bcf2 | ||
|
|
df87ce3709 | ||
|
|
c9475ed2f2 | ||
|
|
148eaf8fa6 | ||
|
|
c2be8a5553 | ||
|
|
6fa5d7c3b5 | ||
|
|
4581f6c368 | ||
|
|
965415135a | ||
|
|
3e332071e7 | ||
|
|
00388ca795 | ||
|
|
5b51f03967 | ||
|
|
4684651dc5 | ||
|
|
84dd8ad4a3 | ||
|
|
efd744e03e | ||
|
|
3365ed5eff | ||
|
|
f8cb04e4a8 | ||
|
|
71063d66cd | ||
|
|
1e3d62c88a | ||
|
|
e3f18b9f95 | ||
|
|
1f7c5bcd50 | ||
|
|
c514ee7212 | ||
|
|
2b1ac1ffa1 | ||
|
|
26e52a4aed | ||
|
|
cf100f740e | ||
|
|
a4f0f6ca36 | ||
|
|
a09ccd59cb | ||
|
|
1b2bd205b8 | ||
|
|
43ebf367ef | ||
|
|
19e0fa3094 | ||
|
|
e70dc90a45 | ||
|
|
b573a4cc48 | ||
|
|
43a97c5907 | ||
|
|
da1cb2276b | ||
|
|
2cfb4df82c | ||
|
|
3f84fe3557 | ||
|
|
6688d7b91c | ||
|
|
20a44bb4e9 | ||
|
|
1093a4ac82 | ||
|
|
1a508f55fc | ||
|
|
019eba5c2d | ||
|
|
1ffc59f65a | ||
|
|
284512b2ca | ||
|
|
5e1c54a887 | ||
|
|
5265d13fe0 | ||
|
|
541b5cbf13 | ||
|
|
3b6862030a | ||
|
|
57f21abb4f | ||
|
|
90523b3b00 | ||
|
|
b51472048c | ||
|
|
451e171ad9 | ||
|
|
9ce380d3ce | ||
|
|
b42b156fcd | ||
|
|
2bad3c29d9 | ||
|
|
5c3c06dfdf | ||
|
|
e6caaf40fb | ||
|
|
ccd26de097 | ||
|
|
a7ed190df4 | ||
|
|
280a284b76 | ||
|
|
83209e0860 | ||
|
|
e71ec4e8d7 | ||
|
|
4c549778c0 | ||
|
|
e8857a6713 | ||
|
|
983063c3e6 | ||
|
|
3a43f5d784 | ||
|
|
ae375091db | ||
|
|
045b9f20b7 | ||
|
|
a418c9e40a | ||
|
|
91fd918fcb | ||
|
|
7cfd91bb69 | ||
|
|
260e18f0ae | ||
|
|
e828a7bdcf | ||
|
|
51fdf23304 | ||
|
|
a46f1c6eba | ||
|
|
7b09285817 | ||
|
|
7381872a54 | ||
|
|
9526334049 | ||
|
|
449d70333c | ||
|
|
59a3097242 | ||
|
|
1d61f320a8 | ||
|
|
bbc21b9f52 | ||
|
|
de61d417b9 | ||
|
|
877b810ac9 | ||
|
|
34e329649d | ||
|
|
a3d2d7892f | ||
|
|
23fcd68707 | ||
|
|
e494d98960 | ||
|
|
ba9ea0a25f | ||
|
|
149238845c | ||
|
|
2482ed085e | ||
|
|
8a4bfcf5b4 | ||
|
|
25e15846f1 | ||
|
|
c7b3ece37e | ||
|
|
57a9761186 | ||
|
|
69f57fb6a8 | ||
|
|
c59887c810 | ||
|
|
7c4b7ce799 | ||
|
|
544b554c69 | ||
|
|
1e70b23855 | ||
|
|
f717e1e4e6 | ||
|
|
00b10f3d9a | ||
|
|
ce2a686b97 | ||
|
|
7de9a3693f | ||
|
|
54116569c3 | ||
|
|
a21f773366 | ||
|
|
63f55f4915 | ||
|
|
9908b729c8 | ||
|
|
30d5edb205 | ||
|
|
8f4b00c263 | ||
|
|
f887b8703c | ||
|
|
0a43d82428 | ||
|
|
984ad8833a | ||
|
|
aa081f5748 | ||
|
|
226fc5f82c | ||
|
|
e848f3fd7d | ||
|
|
a5be542d3d | ||
|
|
dc8de6f21a | ||
|
|
cb2f1818fc | ||
|
|
abc88581e3 | ||
|
|
57d64279bd | ||
|
|
c2f55a2600 | ||
|
|
bdbd16c902 | ||
|
|
5f778c0d3a | ||
|
|
a16fbdae38 | ||
|
|
4b15faabb1 | ||
|
|
325dcec06b | ||
|
|
a2931d1956 | ||
|
|
6b3d2b5a80 | ||
|
|
521ee46c47 | ||
|
|
30792577cd | ||
|
|
d6a738bef7 | ||
|
|
1eb938b8e8 | ||
|
|
93963207f2 | ||
|
|
ccbca2ac95 | ||
|
|
390caeb011 | ||
|
|
fe7d3429ab | ||
|
|
2ff94ec374 | ||
|
|
accdade4cf | ||
|
|
73b02f2cda | ||
|
|
cd21d64058 | ||
|
|
b9244f1031 | ||
|
|
613f73c53f | ||
|
|
95aa7c4b68 | ||
|
|
6ecb710305 | ||
|
|
f4322666c6 | ||
|
|
8bd4540636 | ||
|
|
8183715beb | ||
|
|
a7065d158b | ||
|
|
937ff7f418 | ||
|
|
652f15d54e | ||
|
|
204219695f | ||
|
|
e0d20d2cf3 | ||
|
|
38c0fdac47 | ||
|
|
278c312876 | ||
|
|
f5752121f8 | ||
|
|
7a6818da7e | ||
|
|
423016d6e9 | ||
|
|
ef1b6b4703 | ||
|
|
749455c91d | ||
|
|
fa2d5bca57 | ||
|
|
fe9a091f11 | ||
|
|
d96b8bbc01 | ||
|
|
a5ff4a94a6 | ||
|
|
ffb34e558f | ||
|
|
9fa92c2225 | ||
|
|
b059f2eda8 | ||
|
|
5e63906a3f | ||
|
|
25cc8a96ef | ||
|
|
d234085496 | ||
|
|
9f327aeb48 | ||
|
|
406f30add4 | ||
|
|
527cd74b21 | ||
|
|
e29ed6849e | ||
|
|
b9c1c1dd37 | ||
|
|
e836845f02 | ||
|
|
71f5c441fe | ||
|
|
49d7edfe11 | ||
|
|
5e98d9e289 | ||
|
|
ce136317d8 | ||
|
|
da42c4a561 | ||
|
|
936e8d3d80 | ||
|
|
b2cf9b35f6 | ||
|
|
da6fd75125 | ||
|
|
1203f5eeb3 | ||
|
|
0678644a8f | ||
|
|
0e3df5ae4d | ||
|
|
b2e4c64cf8 | ||
|
|
788c4edeec | ||
|
|
1ea2411575 | ||
|
|
e0fa26b1a4 | ||
|
|
af991b143a | ||
|
|
332542fad8 | ||
|
|
19c8e72c74 | ||
|
|
3279dbeff7 | ||
|
|
f3f22a5698 | ||
|
|
833316835a | ||
|
|
09f2077f58 | ||
|
|
220fcc1675 | ||
|
|
075176f869 | ||
|
|
b742776bff | ||
|
|
bd6bea39bf | ||
|
|
c9531b463a | ||
|
|
04d8a4ecad | ||
|
|
4c558e45b9 | ||
|
|
1e08132cdf | ||
|
|
48e24321e8 | ||
|
|
950aeae544 | ||
|
|
1a4e022d70 | ||
|
|
985b22d4b7 | ||
|
|
8e87655a12 | ||
|
|
3e023146d2 | ||
|
|
173d966444 | ||
|
|
861c52e015 | ||
|
|
dd6e2a400b | ||
|
|
52acae5797 | ||
|
|
630e152900 | ||
|
|
57c8510a42 | ||
|
|
e1a697fee5 | ||
|
|
27da6bd752 | ||
|
|
4388a2aa68 | ||
|
|
5cfaae771d | ||
|
|
6303d42535 | ||
|
|
dd9d5d4528 | ||
|
|
f5bca9c08c | ||
|
|
1a60b63b7d | ||
|
|
42861f6683 | ||
|
|
ac81467c5c | ||
|
|
eb50b1a871 | ||
|
|
3d64a7e3d1 | ||
|
|
b17ec494b2 | ||
|
|
593ea504e7 | ||
|
|
b8171a1e9c | ||
|
|
288a3fcd8b | ||
|
|
407791113d | ||
|
|
6605743b48 | ||
|
|
1bf2d2e1f9 | ||
|
|
84c15e9d31 | ||
|
|
8f46028bd4 | ||
|
|
e9bf36232b | ||
|
|
6f3cd143ef | ||
|
|
0f6bbcaa2e | ||
|
|
db8273823d | ||
|
|
46eda64177 | ||
|
|
d0d44a51a0 | ||
|
|
82e70db47c | ||
|
|
06c581e202 | ||
|
|
2a46d71fc8 | ||
|
|
7f9ad78ac8 | ||
|
|
1c481c5ad3 | ||
|
|
9287a69624 | ||
|
|
d18da895d3 | ||
|
|
79c8fb0236 | ||
|
|
3dfb6d7931 | ||
|
|
d98ab4ddb1 | ||
|
|
6a9be01857 | ||
|
|
be3e99e2d3 | ||
|
|
acd84e0f9c | ||
|
|
f770f55a4e | ||
|
|
e548742701 | ||
|
|
ced3fab7d5 | ||
|
|
6aa17ab10a | ||
|
|
dcfb206a38 | ||
|
|
07aad17993 | ||
|
|
4af50cee63 | ||
|
|
d7715899cb | ||
|
|
3fd549f30a | ||
|
|
d28624fe5b | ||
|
|
ef1693433f | ||
|
|
003d5ccf73 | ||
|
|
9ebc4552bf | ||
|
|
59405443b5 | ||
|
|
0f8c4ed155 | ||
|
|
4486947e81 | ||
|
|
ae6ef196e7 | ||
|
|
b2d5edcdb5 | ||
|
|
2e6b2ef3c9 | ||
|
|
273a4f5ca9 | ||
|
|
c53c90f7fa | ||
|
|
a83b182c55 | ||
|
|
7ff66986c1 | ||
|
|
b895095031 | ||
|
|
fe4c7f1499 | ||
|
|
451a38ddee | ||
|
|
93fa207c5c | ||
|
|
adf52c7355 | ||
|
|
c063395312 | ||
|
|
7ab39fb92c | ||
|
|
2d838f95da | ||
|
|
71832d651a | ||
|
|
85c9fea5d8 | ||
|
|
d0e5f42b68 | ||
|
|
b551e7c1a2 | ||
|
|
cdf2e75cc3 | ||
|
|
1fc3d9224e | ||
|
|
888b38c3db | ||
|
|
f597d63bf6 | ||
|
|
3adbebd701 | ||
|
|
440b5d7110 | ||
|
|
eff5102235 | ||
|
|
e1c9d59951 | ||
|
|
f93b139098 | ||
|
|
6dd55b64d8 | ||
|
|
3e7d9fa2fe | ||
|
|
1c42b8a05f | ||
|
|
1de6428896 | ||
|
|
e5107b1eab | ||
|
|
c05fc4872e | ||
|
|
3c32585a92 | ||
|
|
aca01365e6 | ||
|
|
415acad40c | ||
|
|
a48a909997 | ||
|
|
dc37a6f9b2 | ||
|
|
abb18380a1 | ||
|
|
5f8b53be33 | ||
|
|
3bf7009877 | ||
|
|
7b5923a5eb | ||
|
|
22be176b87 | ||
|
|
c0a2ce31ee | ||
|
|
d72f000d98 | ||
|
|
d7d3111212 | ||
|
|
09aeab3f77 | ||
|
|
def7873e7e | ||
|
|
bf2e00a233 | ||
|
|
0362cfa7ee | ||
|
|
b98ea81bdb | ||
|
|
32c59e829c | ||
|
|
6a52507e3a | ||
|
|
6ef95f7a91 | ||
|
|
d6a2a7ba60 | ||
|
|
b9994c7c95 | ||
|
|
f3a49a29b7 | ||
|
|
fa7edadaa7 | ||
|
|
82f7ab8f7d | ||
|
|
45c021955a | ||
|
|
a44add160e | ||
|
|
1b0ce23bbe | ||
|
|
3e1617deaa | ||
|
|
37877185f8 | ||
|
|
adabd108e2 | ||
|
|
5783bdc513 | ||
|
|
98ff2dd76e | ||
|
|
d56f188854 | ||
|
|
edb683a62b | ||
|
|
7e6dda546e | ||
|
|
3efd0ff4fa | ||
|
|
d7d378aeef | ||
|
|
3bcb6f82af | ||
|
|
06c4a541da | ||
|
|
bbbd510fcc | ||
|
|
b13456f81f | ||
|
|
97dc444023 | ||
|
|
2d1078ee5b | ||
|
|
a6396be53e | ||
|
|
e095c7c858 | ||
|
|
07df3d28a4 | ||
|
|
5e61775561 | ||
|
|
bbd1648f05 | ||
|
|
7f916f2e9d | ||
|
|
6dcaeae369 | ||
|
|
124e081fe1 | ||
|
|
618d73efd0 | ||
|
|
20c6cbc1d2 | ||
|
|
eb79fd552a | ||
|
|
fc318f454a | ||
|
|
fdc53e4471 | ||
|
|
5d7b01bbe0 | ||
|
|
bab8cdfdef | ||
|
|
2c409e0980 | ||
|
|
099e31ae0a | ||
|
|
17ec4ad24e | ||
|
|
b54d701c83 | ||
|
|
8583e61b84 | ||
|
|
9f4cf8017f | ||
|
|
fa1a6bcd6b | ||
|
|
f427427b5e | ||
|
|
ee01be71e1 | ||
|
|
03d1c48017 | ||
|
|
ba2538c29c | ||
|
|
3446de2b8e | ||
|
|
a824bd75ef | ||
|
|
60c71580da | ||
|
|
0d5dd25db5 | ||
|
|
331c7b103a | ||
|
|
5d28b929c3 | ||
|
|
23995131af | ||
|
|
a8e2c00b98 | ||
|
|
09f978d2b6 | ||
|
|
2e5f2d208c | ||
|
|
692a21e4a7 | ||
|
|
f2ee3f055e | ||
|
|
62f053bc4d | ||
|
|
746901e6b0 | ||
|
|
cb8e336cd7 | ||
|
|
67d6f0b769 | ||
|
|
3c69fcddc8 | ||
|
|
1d05704d27 | ||
|
|
046066032a | ||
|
|
8124ba5f63 | ||
|
|
5d0dc2ded2 | ||
|
|
3d0f9fb18f | ||
|
|
6de5e0d71a | ||
|
|
2bee28938a | ||
|
|
db5eb58d91 | ||
|
|
3d44edb348 | ||
|
|
a076c1e78f | ||
|
|
119e284758 | ||
|
|
4a9f3a4f27 | ||
|
|
c8f729761e | ||
|
|
843e9de6cf | ||
|
|
f072b7b8a0 | ||
|
|
713b7e90c2 | ||
|
|
f12c4d8251 | ||
|
|
7e20812924 | ||
|
|
e4f4fd1d5a | ||
|
|
7c378814f1 | ||
|
|
7e494eb06f | ||
|
|
0b8de57c56 | ||
|
|
4356ad9bf5 | ||
|
|
cedf98de5a | ||
|
|
c309333b79 | ||
|
|
f7f7dba5ed | ||
|
|
d14407dafa | ||
|
|
fd401c317d | ||
|
|
ed1d12974f | ||
|
|
c1b059de1e | ||
|
|
70cdcc51a9 | ||
|
|
038782bcba | ||
|
|
7bc81341e1 | ||
|
|
ba98786ee3 | ||
|
|
e9965c87d3 | ||
|
|
40b061cd51 | ||
|
|
585c62673f | ||
|
|
5f9a25dfe9 | ||
|
|
9244f0f0d5 | ||
|
|
70ee42d17f | ||
|
|
6acf763db4 | ||
|
|
02920d67b7 | ||
|
|
8dbf7aa2ab | ||
|
|
b3397882a3 | ||
|
|
969be5ab9c | ||
|
|
661df357a9 | ||
|
|
08097bdf0c | ||
|
|
7dd5dbcf7c | ||
|
|
eb0b1ce975 | ||
|
|
1c491513b6 | ||
|
|
1f37de1870 | ||
|
|
ee9d12a038 | ||
|
|
a05de943da | ||
|
|
cd16eba8fd | ||
|
|
e66ded444c | ||
|
|
ccddd48db8 | ||
|
|
cce17dc0c5 | ||
|
|
ecb648a68a | ||
|
|
70b8e277d0 | ||
|
|
c1edc0901e | ||
|
|
9d1b3cc773 | ||
|
|
7a3c03c901 | ||
|
|
bc4c39404a | ||
|
|
16bb4a9ccd | ||
|
|
bf61e92518 | ||
|
|
a623552127 | ||
|
|
91713bed26 | ||
|
|
34912b29c1 | ||
|
|
da403a4407 | ||
|
|
8364cd2f2c | ||
|
|
6c3a33a6d8 | ||
|
|
99285ef1f2 | ||
|
|
cad7b96c3a | ||
|
|
754dd45ffa | ||
|
|
97db26b6a9 | ||
|
|
e18ec9bbd7 | ||
|
|
b331e4a15b | ||
|
|
22aa9a436d | ||
|
|
d114924a2c | ||
|
|
16a473b3aa | ||
|
|
db10f9be64 | ||
|
|
5352d6c7ab | ||
|
|
3c9bf992a5 | ||
|
|
1788ecf7b1 | ||
|
|
354cbe5a26 | ||
|
|
325dab6393 | ||
|
|
16e0864f38 | ||
|
|
44bb4eb521 | ||
|
|
b8fdb3e01d | ||
|
|
c95404d564 | ||
|
|
8be1a0ea36 | ||
|
|
1c6924ac67 | ||
|
|
ab744b7344 | ||
|
|
bbb31184ab | ||
|
|
910e32270b | ||
|
|
8a138f9be8 | ||
|
|
69982d43cd | ||
|
|
d7ea27cbdd | ||
|
|
5892056884 | ||
|
|
d09e77d1af | ||
|
|
3f81ea2e0e | ||
|
|
346ab5ce30 | ||
|
|
67ba115436 | ||
|
|
44129ad0df | ||
|
|
72eb17012d | ||
|
|
fa5527fc76 | ||
|
|
56e716bf86 | ||
|
|
c09cf4983b | ||
|
|
1c0161589b | ||
|
|
dbea6ba7bf | ||
|
|
3080aefa3d | ||
|
|
3e99cf4b5e | ||
|
|
b743e5cff5 | ||
|
|
c2f593f69a | ||
|
|
fc9f50c90d | ||
|
|
43832335b8 | ||
|
|
b8f5f50d39 | ||
|
|
90a59de144 | ||
|
|
493c81076b | ||
|
|
fb1cb01c5a | ||
|
|
4a9a82b664 | ||
|
|
8671e6217b | ||
|
|
8f4a5d7700 | ||
|
|
178cc8747c | ||
|
|
6f223fc1c1 | ||
|
|
05f1298044 | ||
|
|
0ba96bd1fa | ||
|
|
c9685dd297 | ||
|
|
a1d538b4eb | ||
|
|
677aee941f | ||
|
|
2637294ff2 | ||
|
|
903cc225eb | ||
|
|
d6d8e45931 | ||
|
|
fa77d57e7c | ||
|
|
bd7b72e861 | ||
|
|
fad9edf344 | ||
|
|
1637265ad3 | ||
|
|
0a2a3dfab7 | ||
|
|
89f1483ac9 | ||
|
|
1306edd085 | ||
|
|
8b07dc5c9c | ||
|
|
ae6761f508 | ||
|
|
6b710a5d89 | ||
|
|
76c5c58d54 | ||
|
|
81fae3d807 | ||
|
|
d05c19b9f4 | ||
|
|
bbd08baacd | ||
|
|
62a5b0671e | ||
|
|
b88be79814 | ||
|
|
5fcb54f713 | ||
|
|
50ae0350b2 | ||
|
|
0a8fa9921c | ||
|
|
484f50725e | ||
|
|
245cbe97c7 | ||
|
|
86acfbb4f2 | ||
|
|
79ae276bbf | ||
|
|
de8df59748 | ||
|
|
61b38bd4ff | ||
|
|
14de326e95 | ||
|
|
82a07afb21 | ||
|
|
c0a96d2747 | ||
|
|
6e60fed737 | ||
|
|
10e3652f28 | ||
|
|
b4fdfeec62 | ||
|
|
a2a372d314 | ||
|
|
7cbf3a54f1 | ||
|
|
a785a71190 | ||
|
|
695fb1b5bf | ||
|
|
9315d0e7a5 | ||
|
|
ceaff0d963 | ||
|
|
3ca113162e | ||
|
|
d5cd457f82 | ||
|
|
108e033af3 | ||
|
|
4ecbaa41fa | ||
|
|
0cca1bb91a | ||
|
|
33f9193c94 | ||
|
|
b59ae50961 | ||
|
|
d9c2928e73 | ||
|
|
db9aec2a3b | ||
|
|
c197b3f52c | ||
|
|
efc32c2930 | ||
|
|
c3bbc58a85 | ||
|
|
9feb027de5 | ||
|
|
77bbeb442e | ||
|
|
0201c786e8 | ||
|
|
028f6938b2 | ||
|
|
27d2a6066d | ||
|
|
e28edf874b | ||
|
|
effee900c4 | ||
|
|
806f743e12 | ||
|
|
35b31df7f7 | ||
|
|
2be012aa39 | ||
|
|
0a30af327d | ||
|
|
38d03b9979 | ||
|
|
1a03da9df3 | ||
|
|
a0b589eda9 | ||
|
|
b489550b7f | ||
|
|
d75c32eaaa | ||
|
|
1f424bf7dc | ||
|
|
90ff0dd047 | ||
|
|
23e8ad7397 | ||
|
|
1b930ae616 | ||
|
|
6d8534758f | ||
|
|
8f174d82d6 | ||
|
|
9ed5c78a80 | ||
|
|
b0eb3ba4f4 | ||
|
|
afc96972c8 | ||
|
|
3a7582d9a6 | ||
|
|
018b6d0fae | ||
|
|
4fbc8a3896 | ||
|
|
d647361fae | ||
|
|
530bc62baa | ||
|
|
489528dcae | ||
|
|
5a805df340 | ||
|
|
9e1639c3f1 | ||
|
|
4c424eb4b0 | ||
|
|
2aaaa3f167 | ||
|
|
d82fc7f27b | ||
|
|
881b38d061 | ||
|
|
aca566bd6a | ||
|
|
fa12a67228 | ||
|
|
e3afa373aa | ||
|
|
e79cb0edaf | ||
|
|
b122725a68 | ||
|
|
0b92f4e9ee | ||
|
|
3e816e7df8 | ||
|
|
7e9a909e0e | ||
|
|
04382115c1 | ||
|
|
96aa3223e5 | ||
|
|
9d5c70fbc9 | ||
|
|
93c06eaf43 | ||
|
|
1cb49ae44d | ||
|
|
1723d27b9c | ||
|
|
a790b49fd5 | ||
|
|
0821201dc4 | ||
|
|
1610010ad2 | ||
|
|
6f9b663ff2 | ||
|
|
5746c4672d | ||
|
|
91933b5f42 | ||
|
|
07ec5e5fdb | ||
|
|
655e5f7c3e | ||
|
|
824782d637 | ||
|
|
1d7860701f | ||
|
|
bdae188c6f | ||
|
|
d5852ab1b3 | ||
|
|
ca5a2ed942 | ||
|
|
1ecbbef46b | ||
|
|
f6afb09924 | ||
|
|
c1d0d35f8b | ||
|
|
4dd5fd4619 | ||
|
|
39d432e3cd | ||
|
|
a3f2c7bf3e | ||
|
|
5d4e324ddf | ||
|
|
d09dd75884 | ||
|
|
0efb62c11c | ||
|
|
98918b6afe | ||
|
|
7d0f234398 | ||
|
|
3d63c7093a | ||
|
|
29e55f99a5 | ||
|
|
e34432160a | ||
|
|
4af932b74b | ||
|
|
a819292073 | ||
|
|
147ccc7a58 | ||
|
|
30ce6af490 | ||
|
|
4c76d1b9a0 | ||
|
|
c155749b29 | ||
|
|
de7f14dbd7 | ||
|
|
af177f3d10 | ||
|
|
e657afbf34 | ||
|
|
1e86269ab7 | ||
|
|
4f02bcfbf4 | ||
|
|
b648db6efe | ||
|
|
639d8dd755 | ||
|
|
398eaf5b55 | ||
|
|
fedb2a9360 | ||
|
|
9ab735494e | ||
|
|
7a47fad5e3 | ||
|
|
5f39a6f8be | ||
|
|
7ca07f8be9 | ||
|
|
82fa0d762c | ||
|
|
ab5c0f90b5 | ||
|
|
32c0bcec3a | ||
|
|
87cb00203a | ||
|
|
adc15d69a2 | ||
|
|
011eed0daf | ||
|
|
78d72d7dc3 | ||
|
|
0e92097f7e | ||
|
|
fb9f31efb7 | ||
|
|
3d7595dfe3 | ||
|
|
1db30eae3a | ||
|
|
6768f13f6a | ||
|
|
72cab4342f | ||
|
|
7779f6875f | ||
|
|
8a03884500 | ||
|
|
e3589e4b5c | ||
|
|
6a7a998058 | ||
|
|
7436aa8b05 | ||
|
|
f6665f8488 | ||
|
|
1b6178a77d | ||
|
|
d651bc802b | ||
|
|
4d1b100152 | ||
|
|
1fe61569f7 | ||
|
|
5ca733c415 | ||
|
|
682f16d1b5 | ||
|
|
a475417220 | ||
|
|
2c353a25a4 | ||
|
|
1589adddf1 | ||
|
|
5be3f0b7db | ||
|
|
3862911ae6 | ||
|
|
66adf8781e | ||
|
|
7eb1e95884 | ||
|
|
bc81daee8b | ||
|
|
9c8a27ad24 | ||
|
|
06ab3de4de | ||
|
|
74bf9dcdc7 | ||
|
|
bfd6ab68b5 | ||
|
|
33d1b127c9 | ||
|
|
358461896c | ||
|
|
a0389d7120 | ||
|
|
b93f6ce4f6 | ||
|
|
c30688fe3a | ||
|
|
e964c5944d | ||
|
|
99610c8819 | ||
|
|
782b707824 | ||
|
|
fdab60cad7 | ||
|
|
158e36976b | ||
|
|
fd51bfb27b | ||
|
|
90442e3597 | ||
|
|
428397a18b | ||
|
|
6de71bcddb | ||
|
|
fbe6b2c73b | ||
|
|
5d710ecf57 | ||
|
|
257db40d57 | ||
|
|
9f0201bdd4 | ||
|
|
8ba5d660f3 | ||
|
|
dcc49077a0 | ||
|
|
8d9b96cf23 | ||
|
|
a919d27afc | ||
|
|
9cb256891f | ||
|
|
ca79e3ec0b | ||
|
|
7f11517257 | ||
|
|
cec9f59113 | ||
|
|
c4ef17ac28 | ||
|
|
98a491b1f2 | ||
|
|
2e0a4a8574 | ||
|
|
66680515a7 | ||
|
|
9f7c577564 | ||
|
|
4624bb3d7c | ||
|
|
2a29778ae2 | ||
|
|
28b4e9962d | ||
|
|
b4c8e0834d | ||
|
|
997bb65e54 | ||
|
|
84797482e9 | ||
|
|
78a46ce724 | ||
|
|
ac77129041 | ||
|
|
ba068a0f58 | ||
|
|
7331b3cc95 | ||
|
|
7177ec0631 | ||
|
|
25ccb2426c | ||
|
|
233f0437d9 | ||
|
|
e399136cb6 | ||
|
|
079b713097 | ||
|
|
a2de0115b3 | ||
|
|
1644572be2 | ||
|
|
0da9a1ea75 | ||
|
|
1b9df8aca6 | ||
|
|
fcd33786ca | ||
|
|
2df61a30eb | ||
|
|
342a20ef8e | ||
|
|
eaefdb386f | ||
|
|
7cfc571f56 | ||
|
|
ed39519014 | ||
|
|
8958dbaa09 | ||
|
|
5bb223a7bf | ||
|
|
9f5d316c7a | ||
|
|
95a80fd2cd | ||
|
|
6919c37445 | ||
|
|
2d2695cd6e | ||
|
|
1ffc58a69a | ||
|
|
ccda4119a8 | ||
|
|
ecce4663d3 | ||
|
|
fb81cfe3c4 | ||
|
|
638aaa9e53 | ||
|
|
032c0878b8 | ||
|
|
9d4d5f6077 | ||
|
|
32fb58656a | ||
|
|
deb79a9c44 | ||
|
|
09e73f8fb6 | ||
|
|
be2b48183f | ||
|
|
bc2407abeb | ||
|
|
82acb87fae | ||
|
|
8ec0d87de0 | ||
|
|
8cd3bc65bf | ||
|
|
87a9445d56 | ||
|
|
1728355498 | ||
|
|
15955bfcd0 | ||
|
|
6fc0a2102f | ||
|
|
9b2665f0c1 | ||
|
|
6c11de4b55 | ||
|
|
b48cbdbc0c | ||
|
|
3b5f6cd6b2 | ||
|
|
cfc5faee2a | ||
|
|
eaf3332599 | ||
|
|
b57d371626 | ||
|
|
a38a5e8bb4 | ||
|
|
b74e8c91bd | ||
|
|
77d896eb89 | ||
|
|
f1cd16e367 | ||
|
|
81bed0aad8 | ||
|
|
bf20358440 | ||
|
|
9616b3f717 | ||
|
|
50a754f470 | ||
|
|
b0496d8294 | ||
|
|
e0c840cd02 | ||
|
|
b0eae8c1b7 | ||
|
|
a5ee1638b8 | ||
|
|
2e0db7f8d8 | ||
|
|
341b81c0a5 | ||
|
|
52ee070fe0 | ||
|
|
9c3f0450bb | ||
|
|
00f2703bbb | ||
|
|
e576da1457 | ||
|
|
2d2ba37b46 | ||
|
|
a6a6f7bb50 | ||
|
|
e341707b0f | ||
|
|
7014b52596 | ||
|
|
690dc55ea2 | ||
|
|
0fa3445ddb | ||
|
|
ac16c5518a | ||
|
|
5d291cb64d | ||
|
|
7ec83c42f8 | ||
|
|
5734d7c2bf | ||
|
|
e122f1d749 | ||
|
|
80807879de | ||
|
|
f775faf26d | ||
|
|
251eee4664 | ||
|
|
8e82bce17a | ||
|
|
85150c0289 | ||
|
|
b8c9d3bd09 | ||
|
|
7687cafe8c | ||
|
|
e0a80d34d9 | ||
|
|
7e7a6b1526 | ||
|
|
e4e9243f8d | ||
|
|
f20bfacb94 | ||
|
|
851df7458f | ||
|
|
3a6c3315ab | ||
|
|
85eb221e4c | ||
|
|
3ae151635d | ||
|
|
ec9856b784 | ||
|
|
d4c497d826 | ||
|
|
4cec88c029 | ||
|
|
f4a7e8eae6 | ||
|
|
7208e37f8c | ||
|
|
6cf7599bcd | ||
|
|
e9a10ca712 | ||
|
|
7cf2b28b78 | ||
|
|
2c247ea2c6 | ||
|
|
a5fa419fbd | ||
|
|
ce6637cd8f |
@@ -1,13 +1,16 @@
|
||||
FROM ghcr.io/commaai/openpilot-base:latest
|
||||
|
||||
RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa libegl1-mesa
|
||||
RUN pip install ipython jupyter jupyterlab
|
||||
RUN apt update && apt install -y vim net-tools usbutils htop ripgrep tmux wget mesa-utils xvfb libxtst6 libxv1 libglu1-mesa gdb bash-completion
|
||||
RUN python3 -m ensurepip --upgrade
|
||||
RUN pip3 install ipython jupyter jupyterlab
|
||||
|
||||
RUN cd /tmp && \
|
||||
ARCH=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) && \
|
||||
curl -L -o virtualgl.deb "https://downloads.sourceforge.net/project/virtualgl/3.1/virtualgl_3.1_$ARCH.deb" && \
|
||||
curl -L -o virtualgl.deb "https://github.com/VirtualGL/virtualgl/releases/download/3.1.1/virtualgl_3.1.1_$ARCH.deb" && \
|
||||
dpkg -i virtualgl.deb
|
||||
|
||||
RUN usermod -aG video batman
|
||||
|
||||
USER batman
|
||||
|
||||
RUN cd $HOME && \
|
||||
|
||||
@@ -14,11 +14,12 @@
|
||||
"force_color_prompt": "1"
|
||||
},
|
||||
"runArgs": [
|
||||
"--volume=/dev:/dev",
|
||||
"--volume=/tmp/.X11-unix:/tmp/.X11-unix",
|
||||
"--volume=${localWorkspaceFolder}/.devcontainer/.host/.Xauthority:/home/batman/.Xauthority",
|
||||
"--volume=${localEnv:HOME}/.comma:/home/batman/.comma",
|
||||
"--volume=${localEnv:HOME}/.azure:/home/batman/.azure",
|
||||
"--volume=/tmp/comma_download_cache:/tmp/comma_download_cache",
|
||||
"--volume=/tmp/devcontainer_scons_cache:/tmp/scons_cache",
|
||||
"--shm-size=1G",
|
||||
"--add-host=host.docker.internal:host-gateway", // required to use host.docker.internal on linux
|
||||
"--publish=0.0.0.0:8070-8079:8070-8079" // body ZMQ services
|
||||
@@ -29,7 +30,9 @@
|
||||
"installOhMyZsh": false,
|
||||
"upgradePackages": false,
|
||||
"username": "batman"
|
||||
}
|
||||
},
|
||||
"ghcr.io/devcontainers-contrib/features/gh-cli:1": {},
|
||||
"ghcr.io/devcontainers/features/azure-cli:1": {}
|
||||
},
|
||||
"containerUser": "batman",
|
||||
"remoteUser": "batman",
|
||||
@@ -43,5 +46,8 @@
|
||||
"lharri73.dbc"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"mounts": [
|
||||
"type=volume,source=scons_cache,target=/tmp/scons_cache"
|
||||
]
|
||||
}
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/pc_bug_report.yml
vendored
2
.github/ISSUE_TEMPLATE/pc_bug_report.yml
vendored
@@ -24,7 +24,7 @@ body:
|
||||
id: os-version
|
||||
attributes:
|
||||
label: OS Version
|
||||
placeholder: Ubuntu 20.04
|
||||
placeholder: Ubuntu 24.04
|
||||
validations:
|
||||
required: true
|
||||
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE/car_port.md
vendored
2
.github/PULL_REQUEST_TEMPLATE/car_port.md
vendored
@@ -8,7 +8,7 @@ assignees: ''
|
||||
|
||||
**Checklist**
|
||||
|
||||
- [ ] added entry to CarInfo in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
||||
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
||||
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py)
|
||||
- [ ] route with openpilot:
|
||||
- [ ] route with stock system:
|
||||
|
||||
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -44,7 +44,7 @@ Explain how you tested this bug fix.
|
||||
|
||||
**Checklist**
|
||||
|
||||
- [ ] added entry to CarInfo in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
||||
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs
|
||||
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py)
|
||||
- [ ] route with openpilot:
|
||||
- [ ] route with stock system:
|
||||
|
||||
8
.github/workflows/auto-cache/action.yaml
vendored
8
.github/workflows/auto-cache/action.yaml
vendored
@@ -19,14 +19,14 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- name: setup namespace cache
|
||||
if: ${{ contains(runner.name, 'nsc') }}
|
||||
if: ${{ contains(runner.name, 'nsc') }}
|
||||
uses: namespacelabs/nscloud-cache-action@v1
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
|
||||
- name: setup github cache
|
||||
if: ${{ !contains(runner.name, 'nsc') && inputs.save != 'false' }}
|
||||
uses: 'actions/cache@v3'
|
||||
uses: 'actions/cache@v4'
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ inputs.key }}
|
||||
@@ -34,7 +34,7 @@ runs:
|
||||
|
||||
- name: setup github cache
|
||||
if: ${{ !contains(runner.name, 'nsc') && inputs.save == 'false' }}
|
||||
uses: 'actions/cache/restore@v3'
|
||||
uses: 'actions/cache/restore@v4'
|
||||
with:
|
||||
path: ${{ inputs.path }}
|
||||
key: ${{ inputs.key }}
|
||||
@@ -46,4 +46,4 @@ runs:
|
||||
run: |
|
||||
mkdir -p ${{ inputs.path }}
|
||||
sudo chmod -R 777 ${{ inputs.path }}
|
||||
sudo chown -R $USER ${{ inputs.path }}
|
||||
sudo chown -R $USER ${{ inputs.path }}
|
||||
|
||||
202
.github/workflows/auto_pr_review.yaml
vendored
202
.github/workflows/auto_pr_review.yaml
vendored
@@ -5,7 +5,7 @@ on:
|
||||
|
||||
jobs:
|
||||
labeler:
|
||||
name: apply labels
|
||||
name: review
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
@@ -14,17 +14,17 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
# Label PRs
|
||||
- uses: actions/labeler@v5.0.0
|
||||
with:
|
||||
dot: true
|
||||
configuration-path: .github/labeler.yaml
|
||||
|
||||
pr_branch_check:
|
||||
name: check branch
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
steps:
|
||||
- uses: Vankka/pr-target-branch-action@69ab6dd5c221de3548b3b6c4d102c1f4913d3baa
|
||||
# Check PR target branch
|
||||
- name: check branch
|
||||
uses: Vankka/pr-target-branch-action@def32ec9d93514138d6ac0132ee62e120a72aed5
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
@@ -34,174 +34,20 @@ jobs:
|
||||
already-exists-action: close_this
|
||||
already-exists-comment: "Your PR should be made against the `master` branch"
|
||||
|
||||
check-pr-template:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
issues: write
|
||||
pull-requests: write
|
||||
actions: read
|
||||
if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot'
|
||||
steps:
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
// Comment to add to the PR if no template has been used
|
||||
const NO_TEMPLATE_MESSAGE =
|
||||
"It looks like you didn't use one of the Pull Request templates. Please check [the contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md). \
|
||||
Also make sure that you didn't modify any of the checkboxes or headings within the template.";
|
||||
// body data for future requests
|
||||
const body_data = {
|
||||
issue_number: context.issue.number,
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
};
|
||||
|
||||
// Utility function to extract all headings
|
||||
const extractHeadings = (markdown) => {
|
||||
const headingRegex = /^(#{1,6})\s+(.+)$/gm;
|
||||
const boldTextRegex = /^(?:\*\*|__)(.+?)(?:\*\*|__)\s*$/gm;
|
||||
const headings = [];
|
||||
let headingMatch;
|
||||
while ((headingMatch = headingRegex.exec(markdown))) {
|
||||
headings.push(headingMatch[2].trim());
|
||||
}
|
||||
let boldMatch;
|
||||
while ((boldMatch = boldTextRegex.exec(markdown))) {
|
||||
headings.push(boldMatch[1].trim());
|
||||
}
|
||||
return headings;
|
||||
};
|
||||
|
||||
// Utility function to extract all check box descriptions
|
||||
const extractCheckBoxTexts = (markdown) => {
|
||||
const checkboxRegex = /^\s*-\s*\[( |x)\]\s+(.+)$/gm;
|
||||
const checkboxes = [];
|
||||
let match;
|
||||
while ((match = checkboxRegex.exec(markdown))) {
|
||||
checkboxes.push(match[2].trim());
|
||||
}
|
||||
return checkboxes;
|
||||
};
|
||||
|
||||
// Utility function to check if a list is a subset of another list
|
||||
isSubset = (subset, superset) => {
|
||||
return subset.every((item) => superset.includes(item));
|
||||
};
|
||||
|
||||
// Utility function to check if a list of checkboxes is a subset of another list of checkboxes
|
||||
isCheckboxSubset = (templateCheckBoxTexts, prTextCheckBoxTexts) => {
|
||||
// Check if each template checkbox text is a substring of at least one PR checkbox text
|
||||
// (user should be allowed to add additional text)
|
||||
return templateCheckBoxTexts.every((item) => prTextCheckBoxTexts.some((element) => element.includes(item)))
|
||||
}
|
||||
|
||||
// Get filenames of all currently checked-in PR templates
|
||||
const template_contents = await github.rest.repos.getContent({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
path: ".github/PULL_REQUEST_TEMPLATE",
|
||||
});
|
||||
var template_filenames = [];
|
||||
for (const content of template_contents.data) {
|
||||
template_filenames.push(content.path);
|
||||
}
|
||||
console.debug("Received template filenames: " + template_filenames);
|
||||
// Retrieve templates
|
||||
var templates = [];
|
||||
for (const template_filename of template_filenames) {
|
||||
const template_response = await github.rest.repos.getContent({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
path: template_filename,
|
||||
});
|
||||
// Convert Base64 content back
|
||||
const decoded_template = atob(template_response.data.content);
|
||||
const headings = extractHeadings(decoded_template);
|
||||
const checkboxes = extractCheckBoxTexts(decoded_template);
|
||||
if (!headings.length && !checkboxes.length) {
|
||||
console.warn(
|
||||
"Invalid template! Contains neither headings nor checkboxes, ignoring it: \n" +
|
||||
decoded_template
|
||||
);
|
||||
} else {
|
||||
templates.push({ headings: headings, checkboxes: checkboxes });
|
||||
}
|
||||
}
|
||||
// Retrieve the PR Body
|
||||
const pull_request = await github.rest.issues.get({
|
||||
...body_data,
|
||||
});
|
||||
const pull_request_text = pull_request.data.body;
|
||||
console.debug("Received Pull Request body: \n" + pull_request_text);
|
||||
|
||||
/* Check if the PR Body matches one of the templates
|
||||
A template is defined by all headings and checkboxes it contains
|
||||
We extract all Headings and Checkboxes from the PR text and check if any of the templates is a subset of that
|
||||
*/
|
||||
const pr_headings = extractHeadings(pull_request_text);
|
||||
const pr_checkboxes = extractCheckBoxTexts(pull_request_text);
|
||||
console.debug("Found Headings in PR body:\n" + pr_headings);
|
||||
console.debug("Found Checkboxes in PR body:\n" + pr_checkboxes);
|
||||
var template_found = false;
|
||||
// Iterate over each template to check if it applies
|
||||
for (const template of templates) {
|
||||
console.log(
|
||||
"Checking for headings: [" +
|
||||
template.headings +
|
||||
"] and checkboxes: [" +
|
||||
template.checkboxes + "]"
|
||||
);
|
||||
if (
|
||||
isCheckboxSubset(template.checkboxes, pr_checkboxes) &&
|
||||
isSubset(template.headings, pr_headings)
|
||||
) {
|
||||
console.debug("Found matching template!");
|
||||
template_found = true;
|
||||
}
|
||||
}
|
||||
|
||||
// List comments from previous runs
|
||||
var existing_comments = [];
|
||||
const comments = await github.rest.issues.listComments({
|
||||
...body_data,
|
||||
});
|
||||
for (const comment of comments.data) {
|
||||
if (comment.body === NO_TEMPLATE_MESSAGE) {
|
||||
existing_comments.push(comment);
|
||||
}
|
||||
}
|
||||
|
||||
// Add a comment to the PR that it is not using a the template (but only if this comment does not exist already)
|
||||
if (!template_found) {
|
||||
var comment_already_sent = false;
|
||||
|
||||
// Add an 'in-bot-review' label since this PR doesn't have the template
|
||||
github.rest.issues.addLabels({
|
||||
...body_data,
|
||||
labels: ["in-bot-review"],
|
||||
});
|
||||
|
||||
if (existing_comments.length < 1) {
|
||||
github.rest.issues.createComment({
|
||||
...body_data,
|
||||
body: NO_TEMPLATE_MESSAGE,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// If template has been found, delete any old comment about missing template
|
||||
for (const existing_comment of existing_comments) {
|
||||
github.rest.issues.deleteComment({
|
||||
...body_data,
|
||||
comment_id: existing_comment.id,
|
||||
});
|
||||
}
|
||||
// Remove the 'in-bot-review' label after the review is done and the PR has passed
|
||||
github.rest.issues.removeLabel({
|
||||
...body_data,
|
||||
name: "in-bot-review",
|
||||
}).catch((error) => {
|
||||
console.log("Label 'in-bot-review' not found, ignoring");
|
||||
});
|
||||
}
|
||||
|
||||
# Welcome comment
|
||||
- name: comment
|
||||
uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6
|
||||
if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot'
|
||||
with:
|
||||
message: |
|
||||
<!-- _(run_id **${{ github.run_id }}**)_ -->
|
||||
Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following:
|
||||
* Convert your PR to a draft unless it's ready to review
|
||||
* Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md)
|
||||
* Before marking as "ready for review", ensure:
|
||||
* the goal is clearly stated in the description
|
||||
* all the tests are passing
|
||||
* the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged)
|
||||
* include a route or your device' dongle ID if relevant
|
||||
comment_tag: run_id
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
2
.github/workflows/badges.yaml
vendored
2
.github/workflows/badges.yaml
vendored
@@ -12,7 +12,7 @@ env:
|
||||
jobs:
|
||||
badges:
|
||||
name: create badges
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
123
.github/workflows/ci_weekly_report.yaml
vendored
Normal file
123
.github/workflows/ci_weekly_report.yaml
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
name: weekly CI test report
|
||||
on:
|
||||
schedule:
|
||||
- cron: '37 9 * * 1' # 9:37AM UTC -> 2:37AM PST every monday
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
ci_runs:
|
||||
description: 'The amount of runs to trigger in CI test report'
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
setup:
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
ci_runs: ${{ steps.ci_runs_setup.outputs.value }}
|
||||
steps:
|
||||
- id: ci_runs_setup
|
||||
run: |
|
||||
CI_RUNS=${{ inputs.ci_runs || '50' }}
|
||||
mylist="value=["
|
||||
|
||||
for i in $(seq 1 $CI_RUNS);
|
||||
do
|
||||
if [ $i != $CI_RUNS ]; then
|
||||
mylist+="\"$i\", "
|
||||
else
|
||||
mylist+="\"$i\"]"
|
||||
fi
|
||||
done
|
||||
|
||||
echo "$mylist" >> $GITHUB_OUTPUT
|
||||
echo "Number of CI runs for report: $CI_RUNS"
|
||||
ci_matrix_run:
|
||||
needs: [ setup ]
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
value: ${{fromJSON(needs.setup.outputs.ci_runs)}}
|
||||
uses: commaai/openpilot/.github/workflows/ci_weekly_run.yaml@master
|
||||
with:
|
||||
run_number: ${{ matrix.value }}
|
||||
|
||||
report:
|
||||
needs: [ci_matrix_run]
|
||||
runs-on: ubuntu-latest
|
||||
if: always()
|
||||
steps:
|
||||
- name: Get job results
|
||||
uses: actions/github-script@v7
|
||||
id: get-job-results
|
||||
with:
|
||||
script: |
|
||||
const jobs = await github
|
||||
.paginate("GET /repos/{owner}/{repo}/actions/runs/{run_id}/attempts/{attempt}/jobs", {
|
||||
owner: "commaai",
|
||||
repo: "${{ github.event.repository.name }}",
|
||||
run_id: "${{ github.run_id }}",
|
||||
attempt: "${{ github.run_attempt }}",
|
||||
})
|
||||
var report = {}
|
||||
jobs.slice(1, jobs.length-1).forEach(job => {
|
||||
const jobName = job.name.split('/')[2].trim();
|
||||
report[jobName] = report[jobName] || { successes: [], failures: [], cancelled: [] };
|
||||
switch (job.conclusion) {
|
||||
case "success":
|
||||
report[jobName].successes.push(job.html_url); break;
|
||||
case "failure":
|
||||
report[jobName].failures.push(job.html_url); break;
|
||||
case "cancelled":
|
||||
report[jobName].cancelled.push(job.html_url); break;
|
||||
}
|
||||
});
|
||||
return JSON.stringify(report);
|
||||
|
||||
- name: Add job results to summary
|
||||
env:
|
||||
JOB_RESULTS: ${{ fromJSON(steps.get-job-results.outputs.result) }}
|
||||
run: |
|
||||
echo $JOB_RESULTS > job_results.json
|
||||
generate_html_table() {
|
||||
echo "<table>"
|
||||
echo "<thead>"
|
||||
echo " <tr>"
|
||||
echo " <th>Job</th>"
|
||||
echo " <th>Succeeded ✅</th>"
|
||||
echo " <th>Failed ❌</th>"
|
||||
echo " <th>Cancelled (timed out) ⏰</th>"
|
||||
echo " </tr>"
|
||||
echo "</thead>"
|
||||
jq -r '
|
||||
"<tbody>",
|
||||
keys[] as $job |
|
||||
"<tr>",
|
||||
" <td>\($job)</td>",
|
||||
" <td>",
|
||||
" <details>",
|
||||
" <summary>(\(.[$job].successes | length))</summary>",
|
||||
" \(.[$job].successes[])<br>",
|
||||
" </details>",
|
||||
" </td>",
|
||||
" <td>",
|
||||
" <details>",
|
||||
" <summary>(\(.[$job].failures | length))</summary>",
|
||||
" \(.[$job].failures[])<br>",
|
||||
" </details>",
|
||||
" </td>",
|
||||
" <td>",
|
||||
" <details>",
|
||||
" <summary>(\(.[$job].cancelled | length))</summary>",
|
||||
" \(.[$job].cancelled[])<br>",
|
||||
" </details>",
|
||||
" </td>",
|
||||
"</tr>"
|
||||
' job_results.json
|
||||
echo "</tbody>"
|
||||
echo "</table>"
|
||||
}
|
||||
echo "# CI Job Summary" >> $GITHUB_STEP_SUMMARY
|
||||
generate_html_table >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
21
.github/workflows/ci_weekly_run.yaml
vendored
Normal file
21
.github/workflows/ci_weekly_run.yaml
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
name: weekly CI test run
|
||||
on:
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_number:
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ci-run-${{ inputs.run_number }}-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
selfdrive_tests:
|
||||
uses: commaai/openpilot/.github/workflows/selfdrive_tests.yaml@master
|
||||
with:
|
||||
run_number: ${{ inputs.run_number }}
|
||||
tools_tests:
|
||||
uses: commaai/openpilot/.github/workflows/tools_tests.yaml@master
|
||||
with:
|
||||
run_number: ${{ inputs.run_number }}
|
||||
@@ -14,7 +14,7 @@ runs:
|
||||
${{ env.RUN }} "rm -rf /tmp/scons_cache/* && \
|
||||
scons -j$(nproc) --cache-populate"
|
||||
- name: Save scons cache
|
||||
uses: actions/cache/save@v3
|
||||
uses: actions/cache/save@v4
|
||||
if: github.ref == 'refs/heads/master'
|
||||
with:
|
||||
path: .ci_cache/scons_cache
|
||||
|
||||
12
.github/workflows/docs.yaml
vendored
12
.github/workflows/docs.yaml
vendored
@@ -5,9 +5,14 @@ on:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_number:
|
||||
default: '1'
|
||||
required: true
|
||||
type: string
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
||||
group: docs-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
|
||||
|
||||
env:
|
||||
@@ -20,8 +25,9 @@ env:
|
||||
jobs:
|
||||
docs:
|
||||
name: build docs
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 45
|
||||
if: false # TODO: replace this with the new docs
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
|
||||
4
.github/workflows/prebuilt.yaml
vendored
4
.github/workflows/prebuilt.yaml
vendored
@@ -11,7 +11,7 @@ env:
|
||||
jobs:
|
||||
build_prebuilt:
|
||||
name: build prebuilt
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
env:
|
||||
PUSH_IMAGE: true
|
||||
@@ -22,7 +22,7 @@ jobs:
|
||||
steps:
|
||||
- name: Wait for green check mark
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
uses: lewagon/wait-on-check-action@595dabb3acf442d47e29c9ec9ba44db0c6bdd18f
|
||||
uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc
|
||||
with:
|
||||
ref: master
|
||||
wait-interval: 30
|
||||
|
||||
4
.github/workflows/release.yaml
vendored
4
.github/workflows/release.yaml
vendored
@@ -12,7 +12,7 @@ jobs:
|
||||
ImageOS: ubuntu20
|
||||
container:
|
||||
image: ghcr.io/commaai/openpilot-base:latest
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
permissions:
|
||||
checks: read
|
||||
@@ -24,7 +24,7 @@ jobs:
|
||||
sudo apt-get install -y libyaml-dev
|
||||
- name: Wait for green check mark
|
||||
if: ${{ github.event_name != 'workflow_dispatch' }}
|
||||
uses: lewagon/wait-on-check-action@595dabb3acf442d47e29c9ec9ba44db0c6bdd18f
|
||||
uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc
|
||||
with:
|
||||
ref: master
|
||||
wait-interval: 30
|
||||
|
||||
17
.github/workflows/repo-maintenance.yaml
vendored
17
.github/workflows/repo-maintenance.yaml
vendored
@@ -8,7 +8,7 @@ on:
|
||||
jobs:
|
||||
bump_submodules:
|
||||
name: bump_submodules
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/commaai/openpilot-base:latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
@@ -22,8 +22,9 @@ jobs:
|
||||
git -c submodule."tinygrad".update=none submodule update --remote
|
||||
git add .
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5
|
||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
||||
with:
|
||||
author: Vehicle Researcher <user@comma.ai>
|
||||
token: ${{ secrets.ACTIONS_CREATE_PR_PAT }}
|
||||
commit-message: bump submodules
|
||||
title: '[bot] Bump submodules'
|
||||
@@ -34,23 +35,25 @@ jobs:
|
||||
labels: bot
|
||||
package_updates:
|
||||
name: package_updates
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: ghcr.io/commaai/openpilot-base:latest
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: poetry lock
|
||||
- name: uv lock
|
||||
run: |
|
||||
pip install poetry
|
||||
poetry lock
|
||||
python3 -m ensurepip --upgrade
|
||||
pip3 install uv
|
||||
uv lock --upgrade
|
||||
- name: pre-commit autoupdate
|
||||
run: |
|
||||
git config --global --add safe.directory '*'
|
||||
pre-commit autoupdate
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@5b4a9f6a9e2af26e5f02351490b90d01eb8ec1e5
|
||||
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
|
||||
with:
|
||||
author: Vehicle Researcher <user@comma.ai>
|
||||
token: ${{ secrets.ACTIONS_CREATE_PR_PAT }}
|
||||
commit-message: Update Python packages and pre-commit hooks
|
||||
title: '[bot] Update Python packages and pre-commit hooks'
|
||||
|
||||
260
.github/workflows/selfdrive_tests.yaml
vendored
260
.github/workflows/selfdrive_tests.yaml
vendored
@@ -6,9 +6,15 @@ on:
|
||||
- master
|
||||
pull_request:
|
||||
workflow_dispatch:
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_number:
|
||||
default: '1'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
||||
group: selfdrive-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
|
||||
|
||||
env:
|
||||
@@ -26,7 +32,9 @@ env:
|
||||
jobs:
|
||||
build_release:
|
||||
name: build release
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
env:
|
||||
STRIPPED_DIR: /tmp/releasepilot
|
||||
steps:
|
||||
@@ -47,116 +55,82 @@ jobs:
|
||||
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
|
||||
run: |
|
||||
cd $STRIPPED_DIR
|
||||
${{ env.RUN }} "python selfdrive/manager/build.py"
|
||||
${{ env.RUN }} "python system/manager/build.py"
|
||||
- name: Run tests
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
cd $STRIPPED_DIR
|
||||
${{ env.RUN }} "release/check-dirty.sh && \
|
||||
MAX_EXAMPLES=5 $PYTEST selfdrive/car"
|
||||
MAX_EXAMPLES=5 $PYTEST -m 'not slow' selfdrive/car"
|
||||
- name: pre-commit
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
cd $GITHUB_WORKSPACE
|
||||
cp .pre-commit-config.yaml $STRIPPED_DIR
|
||||
cp pyproject.toml $STRIPPED_DIR
|
||||
cp poetry.lock $STRIPPED_DIR
|
||||
cd $STRIPPED_DIR
|
||||
${{ env.RUN }} "unset PYTHONWARNINGS && SKIP=check-added-large-files pre-commit run --all && chmod -R 777 /tmp/pre-commit"
|
||||
${{ env.RUN }} "unset PYTHONWARNINGS && SKIP=check-added-large-files,check-hooks-apply,check-useless-excludes pre-commit run --all && chmod -R 777 /tmp/pre-commit"
|
||||
|
||||
build:
|
||||
strategy:
|
||||
matrix:
|
||||
arch: ${{ fromJson(
|
||||
((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
|
||||
runs-on: ${{ (matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8' || 'ubuntu-20.04' }}
|
||||
arch: ${{ fromJson('["x86_64"]') }} # TODO: Re-add build test for aarch64 once we switched to ubuntu-2404
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup docker push
|
||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
||||
run: |
|
||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||
: # (TODO: Re-add this once we test other archs) echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
|
||||
$DOCKER_LOGIN
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
with:
|
||||
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
|
||||
- uses: ./.github/workflows/compile-openpilot
|
||||
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 15 || 30) }} # allow more time when we missed the scons cache
|
||||
|
||||
docker_push:
|
||||
name: docker push
|
||||
strategy:
|
||||
matrix:
|
||||
arch: ${{ fromJson( (github.repository == 'commaai/openpilot') && '["x86_64", "aarch64"]' || '["x86_64"]' ) }}
|
||||
runs-on: ${{ (matrix.arch == 'aarch64') && 'namespace-profile-arm64-2x8' || 'ubuntu-20.04' }}
|
||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
||||
build_mac:
|
||||
name: build macos
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- name: Setup to push to repo
|
||||
run: |
|
||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||
echo "TARGET_ARCHITECTURE=${{ matrix.arch }}" >> "$GITHUB_ENV"
|
||||
$DOCKER_LOGIN
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
with:
|
||||
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
|
||||
|
||||
docker_push_multiarch:
|
||||
name: docker push multiarch tag
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.ref == 'refs/heads/master' && github.event_name != 'pull_request' && github.repository == 'commaai/openpilot'
|
||||
needs: [docker_push]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
- name: Setup docker
|
||||
run: |
|
||||
$DOCKER_LOGIN
|
||||
- name: Merge x64 and arm64 tags
|
||||
run: |
|
||||
export PUSH_IMAGE=true
|
||||
scripts/retry.sh selfdrive/test/docker_tag_multiarch.sh base x86_64 aarch64
|
||||
- run: git lfs pull
|
||||
- name: Install dependencies
|
||||
run: ./tools/mac_setup.sh
|
||||
env:
|
||||
SKIP_PROMPT: 1
|
||||
# package install has DeprecationWarnings
|
||||
PYTHONWARNINGS: default
|
||||
- name: Test openpilot environment
|
||||
run: . .venv/bin/activate && scons -h
|
||||
|
||||
static_analysis:
|
||||
name: static analysis
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }}
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-pre-commit
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: pre-commit
|
||||
timeout-minutes: 4
|
||||
run: ${{ env.RUN }} "unset PYTHONWARNINGS && pre-commit run --all && chmod -R 777 /tmp/pre-commit"
|
||||
|
||||
valgrind:
|
||||
name: valgrind
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Run valgrind
|
||||
timeout-minutes: 1
|
||||
run: |
|
||||
${{ env.RUN }} "python selfdrive/test/test_valgrind_replay.py"
|
||||
- name: Print logs
|
||||
if: always()
|
||||
run: cat selfdrive/test/valgrind_logs.txt
|
||||
|
||||
unit_tests:
|
||||
name: unit tests
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }}
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -171,13 +145,12 @@ jobs:
|
||||
timeout-minutes: 15
|
||||
run: |
|
||||
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
||||
export MAPBOX_TOKEN='pk.eyJ1Ijoiam5ld2IiLCJhIjoiY2xxNW8zZXprMGw1ZzJwbzZneHd2NHljbSJ9.gV7VPRfbXFetD-1OVF0XZg' && \
|
||||
$PYTEST --timeout 60 -m 'not slow' && \
|
||||
./selfdrive/ui/tests/create_test_translations.sh && \
|
||||
QT_QPA_PLATFORM=offscreen ./selfdrive/ui/tests/test_translations && \
|
||||
./selfdrive/ui/tests/test_translations.py"
|
||||
pytest ./selfdrive/ui/tests/test_translations.py"
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
env:
|
||||
@@ -186,8 +159,8 @@ jobs:
|
||||
process_replay:
|
||||
name: process replay
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }}
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -197,10 +170,10 @@ jobs:
|
||||
docker_hub_pat: ${{ secrets.DOCKER_HUB_PAT }}
|
||||
- name: Cache test routes
|
||||
id: dependency-cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .ci_cache/comma_download_cache
|
||||
key: proc-replay-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/ref_commit') }}
|
||||
key: proc-replay-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/ref_commit', 'selfdrive/test/process_replay/test_regen.py') }}
|
||||
- name: Build openpilot
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
@@ -215,7 +188,7 @@ jobs:
|
||||
id: print-diff
|
||||
if: always()
|
||||
run: cat selfdrive/test/process_replay/diff.txt
|
||||
- uses: actions/upload-artifact@v3
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
with:
|
||||
@@ -225,66 +198,20 @@ jobs:
|
||||
if: ${{ failure() && steps.print-diff.outcome == 'success' && github.repository == 'commaai/openpilot' && env.AZURE_TOKEN != '' }}
|
||||
run: |
|
||||
${{ env.RUN }} "unset PYTHONWARNINGS && AZURE_TOKEN='$AZURE_TOKEN' python selfdrive/test/process_replay/test_processes.py -j$(nproc) --upload-only"
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
|
||||
regen:
|
||||
name: regen
|
||||
runs-on: 'ubuntu-20.04'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Cache test routes
|
||||
id: dependency-cache
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .ci_cache/comma_download_cache
|
||||
key: regen-${{ hashFiles('.github/workflows/selfdrive_tests.yaml', 'selfdrive/test/process_replay/test_regen.py') }}
|
||||
- name: Build base Docker image
|
||||
run: eval "$BUILD"
|
||||
- name: Build openpilot
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Run regen
|
||||
timeout-minutes: 30
|
||||
run: |
|
||||
${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \
|
||||
chmod -R 777 /tmp/comma_download_cache"
|
||||
|
||||
test_modeld:
|
||||
name: model tests
|
||||
runs-on: ubuntu-20.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build base Docker image
|
||||
run: eval "$BUILD"
|
||||
- name: Build openpilot
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
# PYTHONWARNINGS triggers a SyntaxError in onnxruntime
|
||||
- name: Run model replay with ONNX
|
||||
timeout-minutes: 4
|
||||
run: |
|
||||
${{ env.RUN }} "unset PYTHONWARNINGS && \
|
||||
ONNXCPU=1 NO_NAV=1 coverage run selfdrive/test/process_replay/model_replay.py && \
|
||||
coverage combine && \
|
||||
coverage xml"
|
||||
- name: Run unit tests
|
||||
ONNXCPU=1 NO_NAV=1 coverage run selfdrive/test/process_replay/model_replay.py && \
|
||||
coverage combine && coverage xml"
|
||||
- name: Run regen
|
||||
timeout-minutes: 4
|
||||
run: |
|
||||
${{ env.RUN }} "unset PYTHONWARNINGS && \
|
||||
$PYTEST selfdrive/modeld"
|
||||
${{ env.RUN }} "ONNXCPU=1 $PYTEST selfdrive/test/process_replay/test_regen.py && \
|
||||
chmod -R 777 /tmp/comma_download_cache"
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
name: ${{ github.job }}
|
||||
env:
|
||||
@@ -293,12 +220,12 @@ jobs:
|
||||
test_cars:
|
||||
name: cars
|
||||
runs-on: ${{ ((github.repository == 'commaai/openpilot') &&
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-20.04' }}
|
||||
((github.event_name != 'pull_request') ||
|
||||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-amd64-8x16' || 'ubuntu-latest' }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
job: [0, 1, 2, 3, 4]
|
||||
job: [0, 1]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -313,15 +240,15 @@ jobs:
|
||||
- name: Build openpilot
|
||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Test car models
|
||||
timeout-minutes: 10
|
||||
timeout-minutes: 20
|
||||
run: |
|
||||
${{ env.RUN }} "$PYTEST selfdrive/car/tests/test_models.py && \
|
||||
chmod -R 777 /tmp/comma_download_cache"
|
||||
env:
|
||||
NUM_JOBS: 5
|
||||
NUM_JOBS: 2
|
||||
JOB_ID: ${{ matrix.job }}
|
||||
- name: "Upload coverage to Codecov"
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
with:
|
||||
name: ${{ github.job }}-${{ matrix.job }}
|
||||
env:
|
||||
@@ -329,7 +256,7 @@ jobs:
|
||||
|
||||
car_docs_diff:
|
||||
name: PR comments
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
@@ -340,7 +267,7 @@ jobs:
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Get base car info
|
||||
run: |
|
||||
${{ env.RUN }} "scons -j$(nproc) && python selfdrive/debug/dump_car_info.py --path /tmp/openpilot_cache/base_car_info"
|
||||
${{ env.RUN }} "scons -j$(nproc) && python 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:
|
||||
@@ -352,19 +279,19 @@ jobs:
|
||||
run: |
|
||||
cd current
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
output=$(${{ env.RUN }} "python selfdrive/debug/print_docs_diff.py --path /tmp/openpilot_cache/base_car_info")
|
||||
output=$(${{ env.RUN }} "python 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@1769778a0c5bd330272d749d12c036d65e70d39d
|
||||
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@b95e16d2859ad843a14218d1028da5b2c4cbc4b4
|
||||
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043
|
||||
with:
|
||||
comment-id: ${{ steps.fc.outputs.comment-id }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
@@ -372,7 +299,7 @@ jobs:
|
||||
edit-mode: replace
|
||||
- name: Delete comment
|
||||
if: ${{ steps.fc.outputs.comment-id != '' && steps.save_diff.outputs.diff == '' && env.AZURE_TOKEN != '' }}
|
||||
uses: actions/github-script@v6
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.deleteComment({
|
||||
@@ -383,7 +310,7 @@ jobs:
|
||||
|
||||
create_ui_report:
|
||||
name: Create UI Report
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
@@ -395,10 +322,59 @@ jobs:
|
||||
run: >
|
||||
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
|
||||
source selfdrive/test/setup_xvfb.sh &&
|
||||
export MAPBOX_TOKEN='pk.eyJ1Ijoiam5ld2IiLCJhIjoiY2xxNW8zZXprMGw1ZzJwbzZneHd2NHljbSJ9.gV7VPRfbXFetD-1OVF0XZg' &&
|
||||
python selfdrive/ui/tests/test_ui/run.py"
|
||||
- name: Upload Test Report
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: report
|
||||
path: selfdrive/ui/tests/test_ui/report
|
||||
name: report-${{ inputs.run_number }}
|
||||
path: selfdrive/ui/tests/test_ui/report_${{ inputs.run_number }}
|
||||
- name: Get changes to selfdrive/ui
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
id: changed-files
|
||||
uses: tj-actions/changed-files@v44
|
||||
with:
|
||||
files: |
|
||||
selfdrive/ui/**
|
||||
- name: Checkout ci-artifacts
|
||||
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
repository: commaai/ci-artifacts
|
||||
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
|
||||
path: ${{ github.workspace }}/ci-artifacts
|
||||
ref: master
|
||||
- name: Push Screenshots
|
||||
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
|
||||
working-directory: ${{ github.workspace }}/ci-artifacts
|
||||
run: |
|
||||
git checkout -b openpilot/pr-${{ github.event.pull_request.number }}
|
||||
git config user.name "GitHub Actions Bot"
|
||||
git config user.email "<>"
|
||||
sudo mv ${{ github.workspace }}/selfdrive/ui/tests/test_ui/report/screenshots/* .
|
||||
git add .
|
||||
git commit -m "screenshots for PR #${{ github.event.pull_request.number }}"
|
||||
git push origin openpilot/pr-${{ github.event.pull_request.number }} --force
|
||||
- name: Comment Screenshots on PR
|
||||
if: ${{ github.event_name == 'pull_request' && steps.changed-files.outputs.any_changed == 'true' }}
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
message: |
|
||||
<!-- _(run_id_screenshots **${{ github.run_id }}**)_ -->
|
||||
## UI Screenshots
|
||||
<table>
|
||||
<tr>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/homescreen.png"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad.png"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_map.png"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/onroad_sidebar.png"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_network.png"></td>
|
||||
<td><img src="https://raw.githubusercontent.com/commaai/ci-artifacts/openpilot/pr-${{ github.event.pull_request.number }}/settings_device.png"></td>
|
||||
</tr>
|
||||
</table>
|
||||
comment_tag: run_id_screenshots
|
||||
pr_number: ${{ github.event.pull_request.number }}
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
@@ -4,7 +4,7 @@ runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: ./.github/workflows/auto-cache
|
||||
with:
|
||||
with:
|
||||
path: .ci_cache/pre-commit
|
||||
key: pre-commit-${{ hashFiles('**/.pre-commit-config.yaml') }}
|
||||
restore-keys: |
|
||||
|
||||
2
.github/workflows/setup/action.yaml
vendored
2
.github/workflows/setup/action.yaml
vendored
@@ -60,4 +60,4 @@ runs:
|
||||
find . -type f -not -executable -not -perm 644 -exec chmod 644 {} \;
|
||||
# build our docker image
|
||||
- shell: bash
|
||||
run: eval ${{ env.BUILD }}
|
||||
run: eval ${{ env.BUILD }}
|
||||
|
||||
11
.github/workflows/stale.yaml
vendored
11
.github/workflows/stale.yaml
vendored
@@ -5,22 +5,23 @@ on:
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
DAYS_BEFORE_PR_CLOSE: 7
|
||||
DAYS_BEFORE_PR_STALE: 30
|
||||
DAYS_BEFORE_PR_CLOSE: 3
|
||||
DAYS_BEFORE_PR_STALE: 14
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/stale@v8
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
exempt-milestones: true
|
||||
exempt-all-milestones: true
|
||||
|
||||
# pull request config
|
||||
stale-pr-message: 'This PR has had no activity for ${{ env.DAYS_BEFORE_PR_STALE }} days. It will be automatically closed in ${{ env.DAYS_BEFORE_PR_CLOSE }} days if there is no activity.'
|
||||
close-pr-message: 'This PR has been automatically closed due to inactivity. Feel free to re-open once activity resumes.'
|
||||
stale-pr-label: stale
|
||||
delete-branch: ${{ github.event.pull_request.head.repo.full_name == 'commaai/openpilot' }} # only delete branches on the main repo
|
||||
exempt-pr-labels: "ignore stale,needs testing,car port" # if wip or it needs testing from the community, don't mark as stale
|
||||
exempt-pr-labels: "ignore stale,needs testing,car port,car" # if wip or it needs testing from the community, don't mark as stale
|
||||
days-before-pr-stale: ${{ env.DAYS_BEFORE_PR_STALE }}
|
||||
days-before-pr-close: ${{ env.DAYS_BEFORE_PR_CLOSE }}
|
||||
|
||||
|
||||
94
.github/workflows/tools_tests.yaml
vendored
94
.github/workflows/tools_tests.yaml
vendored
@@ -5,9 +5,14 @@ on:
|
||||
branches:
|
||||
- master
|
||||
pull_request:
|
||||
|
||||
workflow_call:
|
||||
inputs:
|
||||
run_number:
|
||||
default: '1'
|
||||
required: true
|
||||
type: string
|
||||
concurrency:
|
||||
group: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.run_id || github.head_ref || github.ref }}-${{ github.workflow }}-${{ github.event_name }}
|
||||
group: tools-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
|
||||
|
||||
env:
|
||||
@@ -20,41 +25,60 @@ env:
|
||||
|
||||
|
||||
jobs:
|
||||
plotjuggler:
|
||||
name: plotjuggler
|
||||
runs-on: ubuntu-20.04
|
||||
timeout-minutes: 45
|
||||
simulator_driving:
|
||||
name: simulator driving
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 20
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
timeout-minutes: 5
|
||||
run: ${{ env.RUN }} "scons -j$(nproc) cereal/ common/ --minimal"
|
||||
- name: Test PlotJuggler
|
||||
timeout-minutes: 2
|
||||
run: |
|
||||
${{ env.RUN }} "pytest tools/plotjuggler/"
|
||||
${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Run bridge test
|
||||
run: |
|
||||
${{ env.RUN }} "source selfdrive/test/setup_xvfb.sh && \
|
||||
source selfdrive/test/setup_vsound.sh && \
|
||||
CI=1 pytest tools/sim/tests/test_metadrive_bridge.py"
|
||||
|
||||
simulator:
|
||||
name: simulator
|
||||
test_compatibility:
|
||||
name: test 20.04 + 3.11
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Setup to push to repo
|
||||
if: github.ref == 'refs/heads/master' && github.repository == 'commaai/openpilot'
|
||||
run: |
|
||||
echo "PUSH_IMAGE=true" >> "$GITHUB_ENV"
|
||||
$DOCKER_LOGIN
|
||||
- name: Build and push sim image
|
||||
run: |
|
||||
selfdrive/test/docker_build.sh sim
|
||||
- name: Installing ubuntu dependencies
|
||||
run: INSTALL_EXTRA_PACKAGES=no tools/install_ubuntu_dependencies.sh
|
||||
- name: Installing python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: '3.11.4'
|
||||
- name: Installing pip
|
||||
run: pip install pip==24.0
|
||||
- name: Installing uv
|
||||
run: pip install uv
|
||||
- name: git LFS
|
||||
run: git lfs pull
|
||||
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
|
||||
- name: Getting scons cache
|
||||
uses: 'actions/cache@v4'
|
||||
with:
|
||||
path: /tmp/scons_cache
|
||||
key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||
restore-keys: |
|
||||
scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}
|
||||
scons-${{ runner.arch }}-ubuntu2004
|
||||
- name: Building openpilot
|
||||
run: uv run scons -u -j$(nproc)
|
||||
- name: Saving scons cache
|
||||
uses: actions/cache/save@v4
|
||||
if: github.ref == 'refs/heads/master'
|
||||
with:
|
||||
path: /tmp/scons_cache
|
||||
key: scons-${{ runner.arch }}-ubuntu2004-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
|
||||
|
||||
devcontainer:
|
||||
name: devcontainer
|
||||
@@ -70,7 +94,7 @@ jobs:
|
||||
- name: Setup Dev Container CLI
|
||||
run: npm install -g @devcontainers/cli
|
||||
- name: Build dev container image
|
||||
run: devcontainer build --workspace-folder .
|
||||
run: ./scripts/retry.sh devcontainer build --workspace-folder .
|
||||
- name: Run dev container
|
||||
run: |
|
||||
mkdir -p /tmp/devcontainer_scons_cache/
|
||||
@@ -79,24 +103,6 @@ jobs:
|
||||
- name: Test environment
|
||||
run: |
|
||||
devcontainer exec --workspace-folder . scons -j$(nproc) cereal/ common/
|
||||
devcontainer exec --workspace-folder . pip install pip-install-test
|
||||
devcontainer exec --workspace-folder . pip3 install pip-install-test
|
||||
devcontainer exec --workspace-folder . touch /home/batman/.comma/auth.json
|
||||
devcontainer exec --workspace-folder . sudo touch /root/test.txt
|
||||
|
||||
notebooks:
|
||||
name: notebooks
|
||||
runs-on: ubuntu-20.04
|
||||
if: github.repository == 'commaai/openpilot'
|
||||
timeout-minutes: 45
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
- uses: ./.github/workflows/setup-with-retry
|
||||
- name: Build openpilot
|
||||
timeout-minutes: ${{ ((steps.restore-scons-cache.outputs.cache-hit == 'true') && 10 || 30) }} # allow more time when we missed the scons cache
|
||||
run: ${{ env.RUN }} "scons -j$(nproc)"
|
||||
- name: Test notebooks
|
||||
timeout-minutes: 3
|
||||
run: |
|
||||
${{ env.RUN }} "pip install nbmake && pytest --nbmake tools/car_porting/examples/"
|
||||
30
.gitignore
vendored
30
.gitignore
vendored
@@ -40,8 +40,10 @@ compile_commands.json
|
||||
compare_runtime*.html
|
||||
|
||||
persist
|
||||
board/obj/
|
||||
selfdrive/boardd/boardd
|
||||
selfdrive/pandad/pandad
|
||||
cereal/services.h
|
||||
cereal/gen
|
||||
cereal/messaging/bridge
|
||||
selfdrive/logcatd/logcatd
|
||||
selfdrive/mapd/default_speeds_by_region.json
|
||||
system/proclogd/proclogd
|
||||
@@ -52,16 +54,11 @@ selfdrive/car/tests/cars_dump
|
||||
system/camerad/camerad
|
||||
system/camerad/test/ae_gray_test
|
||||
selfdrive/modeld/_modeld
|
||||
selfdrive/modeld/_navmodeld
|
||||
selfdrive/modeld/_dmonitoringmodeld
|
||||
/src/
|
||||
|
||||
one
|
||||
notebooks
|
||||
xx
|
||||
yy
|
||||
hyperthneed
|
||||
panda_jungle
|
||||
provisioning
|
||||
|
||||
.coverage*
|
||||
@@ -87,3 +84,22 @@ build/
|
||||
|
||||
poetry.toml
|
||||
Pipfile
|
||||
|
||||
### VisualStudioCode ###
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
!.vscode/*.code-snippets
|
||||
|
||||
# Local History for Visual Studio Code
|
||||
.history/
|
||||
|
||||
# Built Visual Studio Code Extensions
|
||||
*.vsix
|
||||
|
||||
### VisualStudioCode Patch ###
|
||||
# Ignore all local history of files
|
||||
.history
|
||||
.ionide
|
||||
6
.gitmodules
vendored
6
.gitmodules
vendored
@@ -4,9 +4,9 @@
|
||||
[submodule "opendbc"]
|
||||
path = opendbc
|
||||
url = ../../sunnyhaibin/opendbc.git
|
||||
[submodule "cereal"]
|
||||
path = cereal
|
||||
url = ../../sunnyhaibin/cereal.git
|
||||
[submodule "msgq"]
|
||||
path = msgq_repo
|
||||
url = ../../commaai/msgq.git
|
||||
[submodule "rednose_repo"]
|
||||
path = rednose_repo
|
||||
url = ../../commaai/rednose.git
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[lfs]
|
||||
url = https://gitlab.com/commaai/openpilot-lfs.git/info/lfs
|
||||
pushurl = ssh://git@gitlab.com/commaai/openpilot-lfs.git
|
||||
url = https://gitlab.com/sunnypilot/public/sunnypilot-lfs.git/info/lfs
|
||||
pushurl = ssh://git@gitlab.com/sunnypilot/public/sunnypilot-lfs.git
|
||||
locksverify = false
|
||||
|
||||
4
.lfsconfig-comma
Normal file
4
.lfsconfig-comma
Normal file
@@ -0,0 +1,4 @@
|
||||
[lfs]
|
||||
url = https://gitlab.com/commaai/openpilot-lfs.git/info/lfs
|
||||
pushurl = ssh://git@gitlab.com/commaai/openpilot-lfs.git
|
||||
locksverify = false
|
||||
@@ -5,7 +5,7 @@ repos:
|
||||
- id: check-hooks-apply
|
||||
- id: check-useless-excludes
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.5.0
|
||||
rev: v4.6.0
|
||||
hooks:
|
||||
- id: check-ast
|
||||
exclude: '^(third_party)/'
|
||||
@@ -19,24 +19,24 @@ repos:
|
||||
- id: check-executables-have-shebangs
|
||||
- id: check-shebang-scripts-are-executable
|
||||
- id: check-added-large-files
|
||||
exclude: '(docs/CARS.md)|(poetry.lock)|(third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h)'
|
||||
exclude: '(docs/CARS.md)|(uv.lock)|(third_party/acados/include/blasfeo/include/blasfeo_d_kernel.h)'
|
||||
args:
|
||||
- --maxkb=120
|
||||
- --enforce-all
|
||||
- repo: https://github.com/codespell-project/codespell
|
||||
rev: v2.2.6
|
||||
rev: v2.3.0
|
||||
hooks:
|
||||
- id: codespell
|
||||
exclude: '^(third_party/)|(body/)|(cereal/)|(panda/)|(opendbc/)|(rednose/)|(rednose_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)'
|
||||
exclude: '^(third_party/)|(body/)|(msgq/)|(panda/)|(opendbc/)|(rednose/)|(rednose_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(selfdrive/ui/translations/.*.ts)|(uv.lock)'
|
||||
args:
|
||||
# if you've got a short variable name that's getting flagged, add it here
|
||||
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints
|
||||
- -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup,bumb,nd,sie,preints,whit,indexIn
|
||||
- --builtins clear,rare,informal,usage,code,names,en-GB_to_en-US
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
rev: v0.2.2
|
||||
rev: v0.5.0
|
||||
hooks:
|
||||
- id: ruff
|
||||
exclude: '^(third_party/)|(cereal/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: mypy
|
||||
@@ -47,7 +47,7 @@ repos:
|
||||
args:
|
||||
- --local-partial-types
|
||||
- --explicit-package-bases
|
||||
exclude: '^(third_party/)|(cereal/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)|(xx/)'
|
||||
exclude: '^(third_party/)|(body/)|(msgq/)|(opendbc/)|(panda/)|(rednose/)|(rednose_repo/)|(tinygrad/)|(tinygrad_repo/)|(teleoprtc/)|(teleoprtc_repo/)'
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: cppcheck
|
||||
@@ -55,18 +55,20 @@ repos:
|
||||
entry: cppcheck
|
||||
language: system
|
||||
types: [c++]
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(tools/)|(selfdrive/modeld/thneed/debug/)|(selfdrive/modeld/test/)|(selfdrive/camerad/test/)|(installer/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(tools/)|(selfdrive/modeld/thneed/debug/)|(selfdrive/modeld/test/)|(selfdrive/camerad/test/)|(installer/)'
|
||||
args:
|
||||
- --error-exitcode=1
|
||||
- --language=c++
|
||||
- --quiet
|
||||
- --force
|
||||
- -j8
|
||||
- --library=qt
|
||||
- --include=third_party/kaitai/kaitaistream.h
|
||||
- repo: https://github.com/cpplint/cpplint
|
||||
rev: 1.6.1
|
||||
hooks:
|
||||
- id: cpplint
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
args:
|
||||
- --quiet
|
||||
- --counting=total
|
||||
@@ -75,10 +77,10 @@ repos:
|
||||
# relevant rules are whitelisted, see all options with: cpplint --filter=
|
||||
- --filter=-build,-legal,-readability,-runtime,-whitespace,+build/include_subdir,+build/forward_decl,+build/include_what_you_use,+build/deprecated,+whitespace/comma,+whitespace/line_length,+whitespace/empty_if_body,+whitespace/empty_loop_body,+whitespace/empty_conditional_body,+whitespace/forcolon,+whitespace/parens,+whitespace/semicolon,+whitespace/tab,+readability/braces
|
||||
- repo: https://github.com/MarcoGorelli/cython-lint
|
||||
rev: v0.16.0
|
||||
rev: v0.16.2
|
||||
hooks:
|
||||
- id: cython-lint
|
||||
exclude: '^(third_party/)|(cereal/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
exclude: '^(third_party/)|(msgq/)|(body/)|(rednose/)|(rednose_repo/)|(opendbc/)|(panda/)|(generated/)'
|
||||
args:
|
||||
- --max-line-length=240
|
||||
- --ignore=E111, E302, E305
|
||||
@@ -86,18 +88,11 @@ repos:
|
||||
hooks:
|
||||
- id: test_translations
|
||||
name: test translations
|
||||
entry: selfdrive/ui/tests/test_translations.py
|
||||
language: script
|
||||
entry: pytest selfdrive/ui/tests/test_translations.py
|
||||
language: system
|
||||
pass_filenames: false
|
||||
files: 'selfdrive/ui/translations/*'
|
||||
- repo: https://github.com/python-poetry/poetry
|
||||
rev: '1.8.0'
|
||||
hooks:
|
||||
- id: poetry-check
|
||||
name: validate poetry lock
|
||||
args:
|
||||
- --lock
|
||||
files: '^selfdrive/ui/translations/'
|
||||
- repo: https://github.com/python-jsonschema/check-jsonschema
|
||||
rev: 0.28.0
|
||||
rev: 0.28.6
|
||||
hooks:
|
||||
- id: check-github-workflows
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
3.11.4
|
||||
1
.vscode/launch.json
vendored
1
.vscode/launch.json
vendored
@@ -7,7 +7,6 @@
|
||||
"description": "Select the process to debug",
|
||||
"options": [
|
||||
"selfdrive/controls/controlsd.py",
|
||||
"selfdrive/navd/navd.py",
|
||||
"system/timed/timed.py",
|
||||
"tools/sim/run_bridge.py"
|
||||
]
|
||||
|
||||
15
.vscode/settings.json
vendored
15
.vscode/settings.json
vendored
@@ -12,5 +12,16 @@
|
||||
"**/.git": true,
|
||||
"**/.venv": true,
|
||||
"**/__pycache__": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"python.analysis.exclude": [
|
||||
"**/.git",
|
||||
"**/.venv",
|
||||
"**/__pycache__",
|
||||
// exclude directories that should be using the symlinked version
|
||||
"common/**",
|
||||
"selfdrive/**",
|
||||
"system/**",
|
||||
"third_party/**",
|
||||
"tools/**",
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,15 +1,83 @@
|
||||
sunnypilot - 0.9.7.0 (2024-xx-xx)
|
||||
sunnypilot - 0.9.8.0 (2024-xx-xx)
|
||||
========================
|
||||
* Always on driver monitoring toggle
|
||||
|
||||
sunnypilot - 0.9.7.1 (2024-06-13)
|
||||
========================
|
||||
* New driving model
|
||||
* Support for many hybrid Ford models
|
||||
* Inputs the past curvature for smoother and more accurate lateral control
|
||||
* Simplified neural network architecture in the model's last layers
|
||||
* Minor fixes to desire augmentation and weight decay
|
||||
* New driver monitoring model
|
||||
* Improved end-to-end bit for phone detection
|
||||
* Adjust driving personality with the follow distance button
|
||||
* Support for hybrid variants of supported Ford models
|
||||
* Fingerprinting without the OBD-II port on all cars
|
||||
* Improved fuzzy fingerprinting for Ford and Volkswagen
|
||||
************************
|
||||
* UPDATED: Synced with commaai's openpilot
|
||||
* master commit 56e343b (February 27, 2024)
|
||||
* master commit f8cb04e (June 10, 2024)
|
||||
* NEW❗: sunnylink (Alpha early access)
|
||||
* NEW❗: Config/Settings Backup
|
||||
* Remotely back up and restore sunnypilot settings easily
|
||||
* Device registration with sunnylink ensures a secure, integrated experience across services
|
||||
* AES encryption derived from the device's RSA private key is used for utmost security
|
||||
* Settings are encrypted on-device, transmitted securely via HTTPS, and stored encrypted on sunnylink
|
||||
* Prevents loss of settings after device resets, offering peace of mind through end-to-end encryption
|
||||
* Early alpha access to all current and previous GitHub Sponsors and Patreon supporters
|
||||
* GitHub account pairing from device settings scanning QR code
|
||||
* Pairing your account will allow you to access features via our API (still WIP but accessible if you dig a little on our code 😉)
|
||||
* Allow inheritance of your sponsorship status, allowing you to get extra features and early access whenever applicable
|
||||
* NEW❗: iOS Siri Shortcuts Navigation support thanks to twilsonco and mike86437!
|
||||
* iOS and macOS Shortcuts to quickly set navigation destinations from your iOS device
|
||||
* comma Prime support
|
||||
* Personal Mapbox/Amap/Google Maps token support
|
||||
* Instructions on how to set up your iOS Siri Shortcuts: https://routinehub.co/shortcut/17677/
|
||||
* NEW❗: Forced Offroad mode
|
||||
* Force sunnypilot in the offroad state even when the car is on
|
||||
* When Forced Offroad mode is on, allows changing offroad-only settings even when the car is turned on
|
||||
* To engage/disengage Force Offroad, go to Settings -> Device panel
|
||||
* UPDATED: Auto Lane Change Timer -> Auto Lane Change by Blinker
|
||||
* NEW❗: New "Off" option to disable lane change by blinker
|
||||
* UPDATED: Pause Lateral Below Speed with Blinker
|
||||
* NEW❗: Customizable Pause Lateral Speed
|
||||
* Pause lateral actuation with blinker when traveling below the desired speed selected. Default is 20 MPH or 32 km/h.
|
||||
* UPDATED: Hyundai CAN Longitudinal
|
||||
* Auto-enable radar tracks on platforms with applicable Mando radar
|
||||
* UPDATED: Hyundai CAN-FD Camera-based SCC
|
||||
* NEW❗: Parse lead info for camera-based SCC platforms with longitudinal support
|
||||
* Improve lead tracking when using openpilot longitudinal
|
||||
* RE-ENABLED: Map-based Turn Speed Control (M-TSC) for supported platforms
|
||||
* openpilot Longitudinal Control available cars
|
||||
* Custom Stock Longitudinal Control available cars
|
||||
* UPDATED: Continued support for comma Pedal
|
||||
* In response to the official deprecation of support for comma Pedal in the upstream, sunnypilot will continue maintaining software support for comma Pedal
|
||||
* UPDATED: Driving Model Selector v4
|
||||
* NEW❗: Driving Model additions
|
||||
* North Dakota (April 29, 2024) - NDv2
|
||||
* WD40 (April 09, 2024) - WD40
|
||||
* Duck Amigo (March 18, 2024) - DA
|
||||
* Recertified Herbalist (March 01, 2024) - CHLR
|
||||
* Legacy Driving Models with Navigate on openpilot (NoO) support
|
||||
* Includes Duck Amigo and all preceding models
|
||||
* UPDATED: Bumping mapd by [@pfeiferj](https://github.com/pfeiferj) to version [v1.9.0](https://github.com/pfeiferj/mapd/releases/tag/v1.9.0) thanks to pfeiferj!
|
||||
* UPDATED: Reset Mapbox Access Token -> Reset Access Tokens for Map Services
|
||||
* Reset self-service access tokens for Mapbox, Amap, and Google Maps
|
||||
* UPDATED: Upstream native support for Gap Adjust Cruise
|
||||
* UPDATED: Neural Network Lateral Control (NNLC)
|
||||
* Due to upstream changes with platform simplifications, most platforms will match and fallback to combined platform model
|
||||
* This will be updated when the new mapping of platforms are restructured (thanks @twilsonco 😉)
|
||||
* UI Updates
|
||||
* Display Metrics Below Chevron
|
||||
* NEW❗: Metrics is now being displayed below the chevron instead of above
|
||||
* NEW❗: Display both Distance and Speed simultaneously
|
||||
* NEW❗: View sunnylink connectivity status on the left sidebar!
|
||||
|
||||
sunnypilot - 0.9.6.2 (2024-05-29)
|
||||
========================
|
||||
* REMOVED: Screen Recorder
|
||||
* Screen Recorder is removed due to unnecessary resource usage
|
||||
* An improved version will be available in the near future. Stay tuned!
|
||||
|
||||
sunnypilot - 0.9.6.1 (2024-02-27)
|
||||
========================
|
||||
|
||||
@@ -8,21 +8,6 @@ ENV PYTHONPATH ${OPENPILOT_PATH}:${PYTHONPATH}
|
||||
RUN mkdir -p ${OPENPILOT_PATH}
|
||||
WORKDIR ${OPENPILOT_PATH}
|
||||
|
||||
COPY SConstruct ${OPENPILOT_PATH}
|
||||
|
||||
COPY ./openpilot ${OPENPILOT_PATH}/openpilot
|
||||
COPY ./third_party ${OPENPILOT_PATH}/third_party
|
||||
COPY ./site_scons ${OPENPILOT_PATH}/site_scons
|
||||
COPY ./rednose ${OPENPILOT_PATH}/rednose
|
||||
COPY ./rednose_repo/site_scons ${OPENPILOT_PATH}/rednose_repo/site_scons
|
||||
COPY ./tools ${OPENPILOT_PATH}/tools
|
||||
COPY ./release ${OPENPILOT_PATH}/release
|
||||
COPY ./common ${OPENPILOT_PATH}/common
|
||||
COPY ./opendbc ${OPENPILOT_PATH}/opendbc
|
||||
COPY ./cereal ${OPENPILOT_PATH}/cereal
|
||||
COPY ./panda ${OPENPILOT_PATH}/panda
|
||||
COPY ./selfdrive ${OPENPILOT_PATH}/selfdrive
|
||||
COPY ./system ${OPENPILOT_PATH}/system
|
||||
COPY ./body ${OPENPILOT_PATH}/body
|
||||
COPY . ${OPENPILOT_PATH}/
|
||||
|
||||
RUN scons --cache-readonly -j$(nproc)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:20.04
|
||||
FROM ubuntu:24.04
|
||||
|
||||
ENV PYTHONUNBUFFERED 1
|
||||
|
||||
@@ -13,14 +13,10 @@ ENV LANGUAGE en_US:en
|
||||
ENV LC_ALL en_US.UTF-8
|
||||
|
||||
COPY tools/install_ubuntu_dependencies.sh /tmp/tools/
|
||||
RUN cd /tmp && \
|
||||
tools/install_ubuntu_dependencies.sh && \
|
||||
rm -rf /var/lib/apt/lists/* && \
|
||||
rm -rf /tmp/* && \
|
||||
# remove unused architectures from gcc for panda
|
||||
cd /usr/lib/gcc/arm-none-eabi/9.2.1 && \
|
||||
rm -rf arm/ && \
|
||||
rm -rf thumb/nofp thumb/v6* thumb/v8* thumb/v7+fp thumb/v7-r+fp.sp
|
||||
RUN INSTALL_EXTRA_PACKAGES=no /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 \
|
||||
@@ -34,23 +30,28 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
|
||||
gcc-arm-none-eabi \
|
||||
tmux \
|
||||
vim \
|
||||
lsb-core \
|
||||
libx11-6 \
|
||||
wget \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
ARG INTEL_DRIVER=l_opencl_p_18.1.0.015.tgz
|
||||
ARG INTEL_DRIVER_URL=https://registrationcenter-download.intel.com/akdlm/irc_nas/vcp/15532
|
||||
RUN mkdir -p /tmp/opencl-driver-intel
|
||||
|
||||
RUN cd /tmp/opencl-driver-intel && \
|
||||
echo INTEL_DRIVER is $INTEL_DRIVER && \
|
||||
curl -O $INTEL_DRIVER_URL/$INTEL_DRIVER && \
|
||||
tar -xzf $INTEL_DRIVER && \
|
||||
for i in $(basename $INTEL_DRIVER .tgz)/rpm/*.rpm; do alien --to-deb $i; done && \
|
||||
dpkg -i *.deb && \
|
||||
rm -rf $INTEL_DRIVER $(basename $INTEL_DRIVER .tgz) *.deb && \
|
||||
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/opencl_compilers_and_libraries_18.1.0.015/linux/compiler/lib/intel64_lin/libintelocl.so > /etc/OpenCL/vendors/intel.icd && \
|
||||
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
|
||||
|
||||
@@ -61,26 +62,23 @@ ENV QTWEBENGINE_DISABLE_SANDBOX 1
|
||||
RUN dbus-uuidgen > /etc/machine-id
|
||||
|
||||
ARG USER=batman
|
||||
ARG USER_UID=1000
|
||||
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
|
||||
|
||||
ENV POETRY_VIRTUALENVS_CREATE=false
|
||||
ENV PYENV_VERSION=3.11.4
|
||||
ENV PYENV_ROOT="/home/$USER/pyenv"
|
||||
ENV PATH="$PYENV_ROOT/bin:$PYENV_ROOT/shims:$PATH"
|
||||
|
||||
COPY --chown=$USER pyproject.toml poetry.lock .python-version /tmp/
|
||||
COPY --chown=$USER pyproject.toml uv.lock /tmp/
|
||||
COPY --chown=$USER tools/install_python_dependencies.sh /tmp/tools/
|
||||
|
||||
ENV VIRTUAL_ENV=/home/$USER/.venv
|
||||
ENV PATH="$VIRTUAL_ENV/bin:$PATH"
|
||||
RUN cd /tmp && \
|
||||
tools/install_python_dependencies.sh && \
|
||||
mkdir -p $VIRTUAL_ENV && \
|
||||
cp -r /tmp/.venv/* $VIRTUAL_ENV && \
|
||||
rm -rf /tmp/* && \
|
||||
rm -rf /home/$USER/.cache && \
|
||||
find /home/$USER/pyenv -type d -name ".git" | xargs rm -rf && \
|
||||
rm -rf /home/$USER/pyenv/versions/3.11.4/lib/python3.11/test
|
||||
rm -rf /home/$USER/.cache
|
||||
|
||||
USER root
|
||||
RUN sudo git config --global --add safe.directory /tmp/openpilot
|
||||
RUN sudo git config --global --add safe.directory /tmp/openpilot
|
||||
|
||||
37
Jenkinsfile
vendored
37
Jenkinsfile
vendored
@@ -26,7 +26,6 @@ export SOURCE_DIR=${env.SOURCE_DIR}
|
||||
export GIT_BRANCH=${env.GIT_BRANCH}
|
||||
export GIT_COMMIT=${env.GIT_COMMIT}
|
||||
export AZURE_TOKEN='${env.AZURE_TOKEN}'
|
||||
export MAPBOX_TOKEN='${env.MAPBOX_TOKEN}'
|
||||
# only use 1 thread for tici tests since most require HIL
|
||||
export PYTEST_ADDOPTS="-n 0"
|
||||
|
||||
@@ -40,6 +39,7 @@ if [ -f /TICI ]; then
|
||||
rm -rf /tmp/tmp*
|
||||
rm -rf ~/.commacache
|
||||
rm -rf /dev/shm/*
|
||||
rm -rf /dev/tmp/tmp*
|
||||
|
||||
if ! systemctl is-active --quiet systemd-resolved; then
|
||||
echo "restarting resolved"
|
||||
@@ -134,10 +134,8 @@ def pcStage(String stageName, Closure body) {
|
||||
def setupCredentials() {
|
||||
withCredentials([
|
||||
string(credentialsId: 'azure_token', variable: 'AZURE_TOKEN'),
|
||||
string(credentialsId: 'mapbox_token', variable: 'MAPBOX_TOKEN')
|
||||
]) {
|
||||
env.AZURE_TOKEN = "${AZURE_TOKEN}"
|
||||
env.MAPBOX_TOKEN = "${MAPBOX_TOKEN}"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -182,7 +180,7 @@ node {
|
||||
deviceStage("onroad", "tici-needs-can", [], [
|
||||
// TODO: ideally, this test runs in master-ci, but it takes 5+m to build it
|
||||
//["build master-ci", "cd $SOURCE_DIR/release && TARGET_DIR=$TEST_DIR $SOURCE_DIR/scripts/retry.sh ./build_devel.sh"],
|
||||
["build openpilot", "cd selfdrive/manager && ./build.py"],
|
||||
["build openpilot", "cd system/manager && ./build.py"],
|
||||
["check dirty", "release/check-dirty.sh"],
|
||||
["onroad tests", "pytest selfdrive/test/test_onroad.py -s"],
|
||||
["time to onroad", "pytest selfdrive/test/test_time_to_onroad.py"],
|
||||
@@ -190,53 +188,54 @@ node {
|
||||
},
|
||||
'HW + Unit Tests': {
|
||||
deviceStage("tici-hardware", "tici-common", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"],
|
||||
["test power draw", "pytest -s system/hardware/tici/tests/test_power_draw.py"],
|
||||
["test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py"],
|
||||
["test pigeond", "pytest system/sensord/tests/test_pigeond.py"],
|
||||
["test manager", "pytest selfdrive/manager/test/test_manager.py"],
|
||||
["test pigeond", "pytest system/ubloxd/tests/test_pigeond.py"],
|
||||
["test manager", "pytest system/manager/test/test_manager.py"],
|
||||
])
|
||||
},
|
||||
'loopback': {
|
||||
deviceStage("loopback", "tici-loopback", ["UNSAFE=1"], [
|
||||
["build openpilot", "cd selfdrive/manager && ./build.py"],
|
||||
["test boardd loopback", "pytest selfdrive/boardd/tests/test_boardd_loopback.py"],
|
||||
["build openpilot", "cd system/manager && ./build.py"],
|
||||
["test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"],
|
||||
])
|
||||
},
|
||||
'camerad': {
|
||||
deviceStage("AR0231", "tici-ar0231", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test camerad", "pytest system/camerad/test/test_camerad.py"],
|
||||
["test exposure", "pytest system/camerad/test/test_exposure.py"],
|
||||
])
|
||||
deviceStage("OX03C10", "tici-ox03c10", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test camerad", "pytest system/camerad/test/test_camerad.py"],
|
||||
["test exposure", "pytest system/camerad/test/test_exposure.py"],
|
||||
])
|
||||
},
|
||||
'sensord': {
|
||||
deviceStage("LSM + MMC", "tici-lsmc", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test sensord", "pytest system/sensord/tests/test_sensord.py"],
|
||||
])
|
||||
deviceStage("BMX + LSM", "tici-bmx-lsm", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["test sensord", "pytest system/sensord/tests/test_sensord.py"],
|
||||
])
|
||||
},
|
||||
'replay': {
|
||||
deviceStage("model-replay", "tici-replay", ["UNSAFE=1"], [
|
||||
["build", "cd selfdrive/manager && ./build.py"],
|
||||
["build", "cd system/manager && ./build.py"],
|
||||
["model replay", "selfdrive/test/process_replay/model_replay.py"],
|
||||
])
|
||||
},
|
||||
'tizi': {
|
||||
deviceStage("tizi", "tizi", ["UNSAFE=1"], [
|
||||
["build openpilot", "cd selfdrive/manager && ./build.py"],
|
||||
["test boardd loopback", "SINGLE_PANDA=1 pytest selfdrive/boardd/tests/test_boardd_loopback.py"],
|
||||
["test pandad", "pytest selfdrive/boardd/tests/test_pandad.py"],
|
||||
["build openpilot", "cd system/manager && ./build.py"],
|
||||
["test pandad loopback", "SINGLE_PANDA=1 pytest selfdrive/pandad/tests/test_pandad_loopback.py"],
|
||||
["test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"],
|
||||
["test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"],
|
||||
["test amp", "pytest system/hardware/tici/tests/test_amplifier.py"],
|
||||
["test hw", "pytest system/hardware/tici/tests/test_hardware.py"],
|
||||
["test qcomgpsd", "pytest system/qcomgpsd/tests/test_qcomgpsd.py"],
|
||||
@@ -249,4 +248,4 @@ node {
|
||||
currentBuild.result = 'FAILED'
|
||||
throw e
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
25
RELEASES.md
25
RELEASES.md
@@ -1,7 +1,19 @@
|
||||
Version 0.9.7 (2024-XX-XX)
|
||||
Version 0.9.8 (2024-XX-XX)
|
||||
========================
|
||||
* Added toggle to enable driver monitoring even when openpilot is not engaged
|
||||
|
||||
Version 0.9.7 (2024-06-13)
|
||||
========================
|
||||
* New driving model
|
||||
* Support for many hybrid Ford models
|
||||
* Inputs the past curvature for smoother and more accurate lateral control
|
||||
* Simplified neural network architecture in the model's last layers
|
||||
* Minor fixes to desire augmentation and weight decay
|
||||
* New driver monitoring model
|
||||
* Improved end-to-end bit for phone detection
|
||||
* Adjust driving personality with the follow distance button
|
||||
* Support for hybrid variants of supported Ford models
|
||||
* Fingerprinting without the OBD-II port on all cars
|
||||
* Improved fuzzy fingerprinting for Ford and Volkswagen
|
||||
|
||||
Version 0.9.6 (2024-02-27)
|
||||
========================
|
||||
@@ -11,6 +23,9 @@ Version 0.9.6 (2024-02-27)
|
||||
* Directly outputs curvature for lateral control
|
||||
* New driver monitoring model
|
||||
* Trained on larger dataset
|
||||
* Model path UI
|
||||
* Shows where driving model wants to be
|
||||
* Shows what model is seeing more clearly, but more jittery
|
||||
* AGNOS 9
|
||||
* comma body streaming and controls over WebRTC
|
||||
* Improved fuzzy fingerprinting for many makes and models
|
||||
@@ -628,7 +643,7 @@ Version 0.5.13 (2019-05-31)
|
||||
* Reduce CPU utilization by 20% and improve stability
|
||||
* Temporarily remove mapd functionalities to improve stability
|
||||
* Add openpilot record-only mode for unsupported cars
|
||||
* Synchronize controlsd to boardd to reduce latency
|
||||
* Synchronize controlsd to pandad to reduce latency
|
||||
* Remove panda support for Subaru giraffe
|
||||
|
||||
Version 0.5.12 (2019-05-16)
|
||||
@@ -964,7 +979,7 @@ Version 0.2.8 (2017-02-27)
|
||||
Version 0.2.7 (2017-02-08)
|
||||
===========================
|
||||
* Better performance and pictures at night
|
||||
* Fix ptr alignment issue in boardd
|
||||
* Fix ptr alignment issue in pandad
|
||||
* Fix brake error light, fix crash if too cold
|
||||
|
||||
Version 0.2.6 (2017-01-31)
|
||||
@@ -996,7 +1011,7 @@ Version 0.2.2 (2017-01-10)
|
||||
Version 0.2.1 (2016-12-14)
|
||||
===========================
|
||||
* Performance improvements, removal of more numpy
|
||||
* Fix boardd process priority
|
||||
* Fix pandad process priority
|
||||
* Make counter timer reset on use of steering wheel
|
||||
|
||||
Version 0.2 (2016-12-12)
|
||||
|
||||
40
SConstruct
40
SConstruct
@@ -67,7 +67,7 @@ AddOption('--pc-thneed',
|
||||
AddOption('--minimal',
|
||||
action='store_false',
|
||||
dest='extras',
|
||||
default=os.path.islink(Dir('#rednose/').abspath), # minimal by default on release branch (where rednose is not a link)
|
||||
default=os.path.exists(File('#.lfsconfig').abspath), # minimal by default on release branch (where there's no LFS)
|
||||
help='the minimum build to run openpilot. no tests, tools, etc.')
|
||||
|
||||
## Architecture name breakdown (arch)
|
||||
@@ -193,6 +193,7 @@ env = Environment(
|
||||
"-Wno-c99-designator",
|
||||
"-Wno-reorder-init-list",
|
||||
"-Wno-error=unused-but-set-variable",
|
||||
"-Wno-vla-cxx-extension",
|
||||
] + cflags + ccflags,
|
||||
|
||||
CPPPATH=cpppath + [
|
||||
@@ -208,9 +209,8 @@ env = Environment(
|
||||
"#third_party/qrcode",
|
||||
"#third_party",
|
||||
"#cereal",
|
||||
"#msgq",
|
||||
"#opendbc/can",
|
||||
"#third_party/maplibre-native-qt/include",
|
||||
f"#third_party/maplibre-native-qt/{arch}/include"
|
||||
],
|
||||
|
||||
CC='clang',
|
||||
@@ -222,10 +222,9 @@ env = Environment(
|
||||
CFLAGS=["-std=gnu11"] + cflags,
|
||||
CXXFLAGS=["-std=c++1z"] + cxxflags,
|
||||
LIBPATH=libpath + [
|
||||
"#cereal",
|
||||
"#msgq_repo",
|
||||
"#third_party",
|
||||
"#opendbc/can",
|
||||
"#selfdrive/boardd",
|
||||
"#selfdrive/pandad",
|
||||
"#common",
|
||||
"#rednose/helpers",
|
||||
],
|
||||
@@ -276,7 +275,7 @@ Export('envCython')
|
||||
|
||||
# Qt build environment
|
||||
qt_env = env.Clone()
|
||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "Location", "Positioning", "DBus", "Xml"]
|
||||
qt_modules = ["Widgets", "Gui", "Core", "Network", "Concurrent", "Multimedia", "Quick", "Qml", "QuickWidgets", "DBus", "Xml"]
|
||||
|
||||
qt_libs = []
|
||||
if arch == "Darwin":
|
||||
@@ -329,8 +328,7 @@ qt_flags = [
|
||||
"-DQT_MESSAGELOGCONTEXT",
|
||||
]
|
||||
qt_env['CXXFLAGS'] += qt_flags
|
||||
qt_env['LIBPATH'] += ['#selfdrive/ui', f"#third_party/maplibre-native-qt/{arch}/lib"]
|
||||
qt_env['RPATH'] += [Dir(f"#third_party/maplibre-native-qt/{arch}/lib").srcnode().abspath]
|
||||
qt_env['LIBPATH'] += ['#selfdrive/ui', ]
|
||||
qt_env['LIBS'] = qt_libs
|
||||
|
||||
if GetOption("clazy"):
|
||||
@@ -355,8 +353,13 @@ gpucommon = [_gpucommon]
|
||||
|
||||
Export('common', 'gpucommon')
|
||||
|
||||
# Build cereal and messaging
|
||||
# Build messaging (cereal + msgq + socketmaster + their dependencies)
|
||||
SConscript(['msgq_repo/SConscript'])
|
||||
SConscript(['cereal/SConscript'])
|
||||
Import('socketmaster', 'msgq')
|
||||
messaging = [socketmaster, msgq, 'zmq', 'capnp', 'kj',]
|
||||
Export('messaging')
|
||||
|
||||
|
||||
# Build other submodules
|
||||
SConscript([
|
||||
@@ -376,25 +379,22 @@ SConscript([
|
||||
])
|
||||
if arch != "Darwin":
|
||||
SConscript([
|
||||
'system/camerad/SConscript',
|
||||
'system/sensord/SConscript',
|
||||
'system/logcatd/SConscript',
|
||||
])
|
||||
|
||||
if arch == "larch64":
|
||||
SConscript(['system/camerad/SConscript'])
|
||||
|
||||
# Build openpilot
|
||||
SConscript(['third_party/SConscript'])
|
||||
|
||||
SConscript(['selfdrive/boardd/SConscript'])
|
||||
SConscript(['selfdrive/controls/lib/lateral_mpc_lib/SConscript'])
|
||||
SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript'])
|
||||
SConscript(['selfdrive/locationd/SConscript'])
|
||||
SConscript(['selfdrive/navd/SConscript'])
|
||||
SConscript(['selfdrive/modeld/SConscript'])
|
||||
SConscript(['selfdrive/ui/SConscript'])
|
||||
SConscript(['selfdrive/SConscript'])
|
||||
|
||||
if arch in ['x86_64', 'aarch64', 'Darwin'] and Dir('#tools/cabana/').exists() and GetOption('extras'):
|
||||
if Dir('#tools/cabana/').exists() and GetOption('extras'):
|
||||
SConscript(['tools/replay/SConscript'])
|
||||
SConscript(['tools/cabana/SConscript'])
|
||||
if arch != "larch64":
|
||||
SConscript(['tools/cabana/SConscript'])
|
||||
|
||||
external_sconscript = GetOption('external_sconscript')
|
||||
if external_sconscript:
|
||||
|
||||
2
body
2
body
Submodule body updated: 61ace31efa...0e74db67ae
1
cereal
1
cereal
Submodule cereal deleted from d4c43a0865
51
cereal/README.md
Normal file
51
cereal/README.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# What is cereal?
|
||||
|
||||
cereal is the messaging system for openpilot. It uses [msgq](https://github.com/commaai/msgq) as a pub/sub backend, and [Cap'n proto](https://capnproto.org/capnp-tool.html) for serialization of the structs.
|
||||
|
||||
|
||||
## Messaging Spec
|
||||
|
||||
You'll find the message types in [log.capnp](log.capnp). It uses [Cap'n proto](https://capnproto.org/capnp-tool.html) and defines one struct called `Event`.
|
||||
|
||||
All `Events` have a `logMonoTime` and a `valid`. Then a big union defines the packet type.
|
||||
|
||||
### Best Practices
|
||||
|
||||
- **All fields must describe quantities in SI units**, unless otherwise specified in the field name.
|
||||
- In the context of the message they are in, field names should be completely unambiguous.
|
||||
- All values should be easy to plot and be human-readable with minimal parsing.
|
||||
|
||||
### Maintaining backwards-compatibility
|
||||
|
||||
When making changes to the messaging spec you want to maintain backwards-compatibility, such that old logs can
|
||||
be parsed with a new version of cereal. Adding structs and adding members to structs is generally safe, most other
|
||||
things are not. Read more details [here](https://capnproto.org/language.html).
|
||||
|
||||
### Custom forks
|
||||
|
||||
Forks of [openpilot](https://github.com/commaai/openpilot) might want to add things to the messaging
|
||||
spec, however this could conflict with future changes made in mainline cereal/openpilot. Rebasing against mainline openpilot
|
||||
then means breaking backwards-compatibility with all old logs of your fork. So we added reserved events in
|
||||
[custom.capnp](custom.capnp) that we will leave empty in mainline cereal/openpilot. **If you only modify those, you can ensure your
|
||||
fork will remain backwards-compatible with all versions of mainline openpilot and your fork.**
|
||||
|
||||
Example
|
||||
---
|
||||
```python
|
||||
import cereal.messaging as messaging
|
||||
|
||||
# in subscriber
|
||||
sm = messaging.SubMaster(['sensorEvents'])
|
||||
while 1:
|
||||
sm.update()
|
||||
print(sm['sensorEvents'])
|
||||
|
||||
```
|
||||
|
||||
```python
|
||||
# in publisher
|
||||
pm = messaging.PubMaster(['sensorEvents'])
|
||||
dat = messaging.new_message('sensorEvents', size=1)
|
||||
dat.sensorEvents[0] = {"gyro": {"v": [0.1, -0.1, 0.1]}}
|
||||
pm.send('sensorEvents', dat)
|
||||
```
|
||||
31
cereal/SConscript
Normal file
31
cereal/SConscript
Normal file
@@ -0,0 +1,31 @@
|
||||
Import('env', 'envCython', 'arch', 'common', 'msgq')
|
||||
|
||||
import shutil
|
||||
|
||||
cereal_dir = Dir('.')
|
||||
gen_dir = Dir('gen')
|
||||
other_dir = Dir('#msgq')
|
||||
|
||||
# Build cereal
|
||||
schema_files = ['log.capnp', 'car.capnp', 'legacy.capnp', 'custom.capnp']
|
||||
env.Command(["gen/c/include/c++.capnp.h"], [], "mkdir -p " + gen_dir.path + "/c/include && touch $TARGETS")
|
||||
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
|
||||
schema_files,
|
||||
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
|
||||
|
||||
# TODO: remove non shared cereal and messaging
|
||||
cereal_objects = env.SharedObject([f'gen/cpp/{s}.c++' for s in schema_files])
|
||||
|
||||
cereal = env.Library('cereal', cereal_objects)
|
||||
env.SharedLibrary('cereal_shared', cereal_objects)
|
||||
|
||||
# Build messaging
|
||||
|
||||
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
|
||||
env.Program('messaging/bridge', ['messaging/bridge.cc'], LIBS=[msgq, 'zmq', common])
|
||||
|
||||
|
||||
socketmaster = env.SharedObject(['messaging/socketmaster.cc'])
|
||||
socketmaster = env.Library('socketmaster', socketmaster)
|
||||
|
||||
Export('cereal', 'socketmaster')
|
||||
9
cereal/__init__.py
Normal file
9
cereal/__init__.py
Normal file
@@ -0,0 +1,9 @@
|
||||
import os
|
||||
import capnp
|
||||
|
||||
CEREAL_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
capnp.remove_import_hook()
|
||||
|
||||
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
|
||||
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))
|
||||
custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp"))
|
||||
759
cereal/car.capnp
Normal file
759
cereal/car.capnp
Normal file
@@ -0,0 +1,759 @@
|
||||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0x8e2af1e708af8b8d;
|
||||
|
||||
# ******* events causing controls state machine transition *******
|
||||
|
||||
struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
name @0 :EventName;
|
||||
|
||||
# event types
|
||||
enable @1 :Bool;
|
||||
noEntry @2 :Bool;
|
||||
warning @3 :Bool; # alerts presented only when enabled or soft disabling
|
||||
userDisable @4 :Bool;
|
||||
softDisable @5 :Bool;
|
||||
immediateDisable @6 :Bool;
|
||||
preEnable @7 :Bool;
|
||||
permanent @8 :Bool; # alerts presented regardless of openpilot state
|
||||
overrideLateral @10 :Bool;
|
||||
overrideLongitudinal @9 :Bool;
|
||||
|
||||
enum EventName @0xbaa8c5d505f727de {
|
||||
canError @0;
|
||||
steerUnavailable @1;
|
||||
wrongGear @4;
|
||||
doorOpen @5;
|
||||
seatbeltNotLatched @6;
|
||||
espDisabled @7;
|
||||
wrongCarMode @8;
|
||||
steerTempUnavailable @9;
|
||||
reverseGear @10;
|
||||
buttonCancel @11;
|
||||
buttonEnable @12;
|
||||
pedalPressed @13; # exits active state
|
||||
preEnableStandstill @73; # added during pre-enable state with brake
|
||||
gasPressedOverride @108; # added when user is pressing gas with no disengage on gas
|
||||
steerOverride @114;
|
||||
cruiseDisabled @14;
|
||||
speedTooLow @17;
|
||||
outOfSpace @18;
|
||||
overheat @19;
|
||||
calibrationIncomplete @20;
|
||||
calibrationInvalid @21;
|
||||
calibrationRecalibrating @117;
|
||||
controlsMismatch @22;
|
||||
pcmEnable @23;
|
||||
pcmDisable @24;
|
||||
radarFault @26;
|
||||
brakeHold @28;
|
||||
parkBrake @29;
|
||||
manualRestart @30;
|
||||
lowSpeedLockout @31;
|
||||
joystickDebug @34;
|
||||
steerTempUnavailableSilent @35;
|
||||
resumeRequired @36;
|
||||
preDriverDistracted @37;
|
||||
promptDriverDistracted @38;
|
||||
driverDistracted @39;
|
||||
preDriverUnresponsive @43;
|
||||
promptDriverUnresponsive @44;
|
||||
driverUnresponsive @45;
|
||||
belowSteerSpeed @46;
|
||||
lowBattery @48;
|
||||
accFaulted @51;
|
||||
sensorDataInvalid @52;
|
||||
commIssue @53;
|
||||
commIssueAvgFreq @109;
|
||||
tooDistracted @54;
|
||||
posenetInvalid @55;
|
||||
soundsUnavailable @56;
|
||||
preLaneChangeLeft @57;
|
||||
preLaneChangeRight @58;
|
||||
laneChange @59;
|
||||
lowMemory @63;
|
||||
stockAeb @64;
|
||||
ldw @65;
|
||||
carUnrecognized @66;
|
||||
invalidLkasSetting @69;
|
||||
speedTooHigh @70;
|
||||
laneChangeBlocked @71;
|
||||
relayMalfunction @72;
|
||||
stockFcw @74;
|
||||
startup @75;
|
||||
startupNoCar @76;
|
||||
startupNoControl @77;
|
||||
startupMaster @78;
|
||||
startupNoFw @104;
|
||||
fcw @79;
|
||||
steerSaturated @80;
|
||||
belowEngageSpeed @84;
|
||||
noGps @85;
|
||||
wrongCruiseMode @87;
|
||||
modeldLagging @89;
|
||||
deviceFalling @90;
|
||||
fanMalfunction @91;
|
||||
cameraMalfunction @92;
|
||||
cameraFrameRate @110;
|
||||
processNotRunning @95;
|
||||
dashcamMode @96;
|
||||
controlsInitializing @98;
|
||||
usbError @99;
|
||||
roadCameraError @100;
|
||||
driverCameraError @101;
|
||||
wideRoadCameraError @102;
|
||||
highCpuUsage @105;
|
||||
cruiseMismatch @106;
|
||||
lkasDisabled @107;
|
||||
canBusMissing @111;
|
||||
controlsdLagging @112;
|
||||
resumeBlocked @113;
|
||||
steerTimeLimit @115;
|
||||
vehicleSensorsInvalid @116;
|
||||
locationdTemporaryError @103;
|
||||
locationdPermanentError @118;
|
||||
paramsdTemporaryError @50;
|
||||
paramsdPermanentError @119;
|
||||
actuatorsApiUnavailable @120;
|
||||
espActive @121;
|
||||
manualSteeringRequired @122;
|
||||
manualLongitudinalRequired @123;
|
||||
silentPedalPressed @124;
|
||||
silentButtonEnable @125;
|
||||
silentBrakeHold @126;
|
||||
silentWrongGear @127;
|
||||
spReverseGear @128;
|
||||
preKeepHandsOnWheel @129;
|
||||
promptKeepHandsOnWheel @130;
|
||||
keepHandsOnWheel @131;
|
||||
speedLimitActive @132;
|
||||
speedLimitValueChange @133;
|
||||
e2eLongStop @134;
|
||||
e2eLongStart @135;
|
||||
controlsMismatchLong @136;
|
||||
cruiseEngageBlocked @137;
|
||||
laneChangeRoadEdge @138;
|
||||
speedLimitPreActive @139;
|
||||
speedLimitConfirmed @140;
|
||||
torqueNNLoad @141;
|
||||
|
||||
radarCanErrorDEPRECATED @15;
|
||||
communityFeatureDisallowedDEPRECATED @62;
|
||||
radarCommIssueDEPRECATED @67;
|
||||
driverMonitorLowAccDEPRECATED @68;
|
||||
gasUnavailableDEPRECATED @3;
|
||||
dataNeededDEPRECATED @16;
|
||||
modelCommIssueDEPRECATED @27;
|
||||
ipasOverrideDEPRECATED @33;
|
||||
geofenceDEPRECATED @40;
|
||||
driverMonitorOnDEPRECATED @41;
|
||||
driverMonitorOffDEPRECATED @42;
|
||||
calibrationProgressDEPRECATED @47;
|
||||
invalidGiraffeHondaDEPRECATED @49;
|
||||
invalidGiraffeToyotaDEPRECATED @60;
|
||||
internetConnectivityNeededDEPRECATED @61;
|
||||
whitePandaUnsupportedDEPRECATED @81;
|
||||
commIssueWarningDEPRECATED @83;
|
||||
focusRecoverActiveDEPRECATED @86;
|
||||
neosUpdateRequiredDEPRECATED @88;
|
||||
modelLagWarningDEPRECATED @93;
|
||||
startupOneplusDEPRECATED @82;
|
||||
startupFuzzyFingerprintDEPRECATED @97;
|
||||
noTargetDEPRECATED @25;
|
||||
brakeUnavailableDEPRECATED @2;
|
||||
plannerErrorDEPRECATED @32;
|
||||
gpsMalfunctionDEPRECATED @94;
|
||||
}
|
||||
}
|
||||
|
||||
# ******* main car state @ 100hz *******
|
||||
# all speeds in m/s
|
||||
|
||||
struct CarState {
|
||||
events @13 :List(CarEvent);
|
||||
|
||||
# CAN health
|
||||
canValid @26 :Bool; # invalid counter/checksums
|
||||
canTimeout @40 :Bool; # CAN bus dropped out
|
||||
canErrorCounter @48 :UInt32;
|
||||
|
||||
# car speed
|
||||
vEgo @1 :Float32; # best estimate of speed
|
||||
aEgo @16 :Float32; # best estimate of acceleration
|
||||
vEgoRaw @17 :Float32; # unfiltered speed from CAN sensors
|
||||
vEgoCluster @44 :Float32; # best estimate of speed shown on car's instrument cluster, used for UI
|
||||
|
||||
yawRate @22 :Float32; # best estimate of yaw rate
|
||||
standstill @18 :Bool;
|
||||
wheelSpeeds @2 :WheelSpeeds;
|
||||
|
||||
# gas pedal, 0.0-1.0
|
||||
gas @3 :Float32; # this is user pedal only
|
||||
gasPressed @4 :Bool; # this is user pedal only
|
||||
|
||||
engineRpm @46 :Float32;
|
||||
|
||||
# brake pedal, 0.0-1.0
|
||||
brake @5 :Float32; # this is user pedal only
|
||||
brakePressed @6 :Bool; # this is user pedal only
|
||||
regenBraking @45 :Bool; # this is user pedal only
|
||||
parkingBrake @39 :Bool;
|
||||
brakeHoldActive @38 :Bool;
|
||||
|
||||
# steering wheel
|
||||
steeringAngleDeg @7 :Float32;
|
||||
steeringAngleOffsetDeg @37 :Float32; # Offset betweens sensors in case there multiple
|
||||
steeringRateDeg @15 :Float32;
|
||||
steeringTorque @8 :Float32; # TODO: standardize units
|
||||
steeringTorqueEps @27 :Float32; # TODO: standardize units
|
||||
steeringPressed @9 :Bool; # if the user is using the steering wheel
|
||||
steerFaultTemporary @35 :Bool; # temporary EPS fault
|
||||
steerFaultPermanent @36 :Bool; # permanent EPS fault
|
||||
stockAeb @30 :Bool;
|
||||
stockFcw @31 :Bool;
|
||||
espDisabled @32 :Bool;
|
||||
accFaulted @42 :Bool;
|
||||
carFaultedNonCritical @47 :Bool; # some ECU is faulted, but car remains controllable
|
||||
espActive @51 :Bool;
|
||||
|
||||
# cruise state
|
||||
cruiseState @10 :CruiseState;
|
||||
|
||||
# gear
|
||||
gearShifter @14 :GearShifter;
|
||||
|
||||
# button presses
|
||||
buttonEvents @11 :List(ButtonEvent);
|
||||
leftBlinker @20 :Bool;
|
||||
rightBlinker @21 :Bool;
|
||||
genericToggle @23 :Bool;
|
||||
|
||||
# lock info
|
||||
doorOpen @24 :Bool;
|
||||
seatbeltUnlatched @25 :Bool;
|
||||
|
||||
# clutch (manual transmission only)
|
||||
clutchPressed @28 :Bool;
|
||||
|
||||
madsEnabled @52 :Bool;
|
||||
leftBlinkerOn @53 :Bool;
|
||||
rightBlinkerOn @54 :Bool;
|
||||
disengageByBrake @55 :Bool;
|
||||
belowLaneChangeSpeed @56 :Bool;
|
||||
accEnabled @57 :Bool;
|
||||
latActive @58 :Bool;
|
||||
gapAdjustCruiseTr @59 :Int32;
|
||||
endToEndLong @60 :Bool;
|
||||
customStockLong @61 :CustomStockLong;
|
||||
|
||||
struct CustomStockLong {
|
||||
cruiseButton @0 :Int16;
|
||||
finalSpeedKph @1 :Float32;
|
||||
vCruiseKphPrev @2 :Float32;
|
||||
targetSpeed @3 :Float32;
|
||||
vSetDis @4 :Float32;
|
||||
speedDiff @5 :Float32;
|
||||
buttonType @6 :Int16;
|
||||
}
|
||||
|
||||
# blindspot sensors
|
||||
leftBlindspot @33 :Bool; # Is there something blocking the left lane change
|
||||
rightBlindspot @34 :Bool; # Is there something blocking the right lane change
|
||||
|
||||
fuelGauge @41 :Float32; # battery or fuel tank level from 0.0 to 1.0
|
||||
charging @43 :Bool;
|
||||
|
||||
# process meta
|
||||
cumLagMs @50 :Float32;
|
||||
|
||||
struct WheelSpeeds {
|
||||
# optional wheel speeds
|
||||
fl @0 :Float32;
|
||||
fr @1 :Float32;
|
||||
rl @2 :Float32;
|
||||
rr @3 :Float32;
|
||||
}
|
||||
|
||||
struct CruiseState {
|
||||
enabled @0 :Bool;
|
||||
speed @1 :Float32;
|
||||
speedCluster @6 :Float32; # Set speed as shown on instrument cluster
|
||||
available @2 :Bool;
|
||||
speedOffset @3 :Float32;
|
||||
standstill @4 :Bool;
|
||||
nonAdaptive @5 :Bool;
|
||||
speedLimit @7 :Float32;
|
||||
}
|
||||
|
||||
enum GearShifter {
|
||||
unknown @0;
|
||||
park @1;
|
||||
drive @2;
|
||||
neutral @3;
|
||||
reverse @4;
|
||||
sport @5;
|
||||
low @6;
|
||||
brake @7;
|
||||
eco @8;
|
||||
manumatic @9;
|
||||
}
|
||||
|
||||
# send on change
|
||||
struct ButtonEvent {
|
||||
pressed @0 :Bool;
|
||||
type @1 :Type;
|
||||
|
||||
enum Type {
|
||||
unknown @0;
|
||||
leftBlinker @1;
|
||||
rightBlinker @2;
|
||||
accelCruise @3;
|
||||
decelCruise @4;
|
||||
cancel @5;
|
||||
altButton1 @6;
|
||||
altButton2 @7;
|
||||
altButton3 @8;
|
||||
setCruise @9;
|
||||
resumeCruise @10;
|
||||
gapAdjustCruise @11;
|
||||
}
|
||||
}
|
||||
|
||||
# deprecated
|
||||
errorsDEPRECATED @0 :List(CarEvent.EventName);
|
||||
brakeLightsDEPRECATED @19 :Bool;
|
||||
steeringRateLimitedDEPRECATED @29 :Bool;
|
||||
canMonoTimesDEPRECATED @12: List(UInt64);
|
||||
canRcvTimeoutDEPRECATED @49 :Bool;
|
||||
}
|
||||
|
||||
# ******* radar state @ 20hz *******
|
||||
|
||||
struct RadarData @0x888ad6581cf0aacb {
|
||||
errors @0 :List(Error);
|
||||
points @1 :List(RadarPoint);
|
||||
|
||||
enum Error {
|
||||
canError @0;
|
||||
fault @1;
|
||||
wrongConfig @2;
|
||||
}
|
||||
|
||||
# similar to LiveTracks
|
||||
# is one timestamp valid for all? I think so
|
||||
struct RadarPoint {
|
||||
trackId @0 :UInt64; # no trackId reuse
|
||||
|
||||
# these 3 are the minimum required
|
||||
dRel @1 :Float32; # m from the front bumper of the car
|
||||
yRel @2 :Float32; # m
|
||||
vRel @3 :Float32; # m/s
|
||||
|
||||
# these are optional and valid if they are not NaN
|
||||
aRel @4 :Float32; # m/s^2
|
||||
yvRel @5 :Float32; # m/s
|
||||
|
||||
# some radars flag measurements VS estimates
|
||||
measured @6 :Bool;
|
||||
}
|
||||
|
||||
# deprecated
|
||||
canMonoTimesDEPRECATED @2 :List(UInt64);
|
||||
}
|
||||
|
||||
# ******* car controls @ 100hz *******
|
||||
|
||||
struct CarControl {
|
||||
# must be true for any actuator commands to work
|
||||
enabled @0 :Bool;
|
||||
latActive @11: Bool;
|
||||
longActive @12: Bool;
|
||||
vCruise @17 :Float32; # actual set speed
|
||||
|
||||
# Actuator commands as computed by controlsd
|
||||
actuators @6 :Actuators;
|
||||
|
||||
# moved to CarOutput
|
||||
actuatorsOutputDEPRECATED @10 :Actuators;
|
||||
|
||||
leftBlinker @15: Bool;
|
||||
rightBlinker @16: Bool;
|
||||
|
||||
orientationNED @13 :List(Float32);
|
||||
angularVelocity @14 :List(Float32);
|
||||
|
||||
cruiseControl @4 :CruiseControl;
|
||||
hudControl @5 :HUDControl;
|
||||
|
||||
struct Actuators {
|
||||
# range from 0.0 - 1.0
|
||||
gas @0: Float32;
|
||||
brake @1: Float32;
|
||||
# range from -1.0 - 1.0
|
||||
steer @2: Float32;
|
||||
# value sent over can to the car
|
||||
steerOutputCan @8: Float32;
|
||||
steeringAngleDeg @3: Float32;
|
||||
|
||||
curvature @7: Float32;
|
||||
|
||||
speed @6: Float32; # m/s
|
||||
accel @4: Float32; # m/s^2
|
||||
longControlState @5: LongControlState;
|
||||
|
||||
enum LongControlState @0xe40f3a917d908282{
|
||||
off @0;
|
||||
pid @1;
|
||||
stopping @2;
|
||||
starting @3;
|
||||
}
|
||||
}
|
||||
|
||||
struct CruiseControl {
|
||||
cancel @0: Bool;
|
||||
resume @1: Bool;
|
||||
override @4: Bool;
|
||||
speedOverrideDEPRECATED @2: Float32;
|
||||
accelOverrideDEPRECATED @3: Float32;
|
||||
}
|
||||
|
||||
struct HUDControl {
|
||||
speedVisible @0: Bool;
|
||||
setSpeed @1: Float32;
|
||||
lanesVisible @2: Bool;
|
||||
leadVisible @3: Bool;
|
||||
visualAlert @4: VisualAlert;
|
||||
audibleAlert @5: AudibleAlert;
|
||||
rightLaneVisible @6: Bool;
|
||||
leftLaneVisible @7: Bool;
|
||||
rightLaneDepart @8: Bool;
|
||||
leftLaneDepart @9: Bool;
|
||||
leadDistanceBars @10: Int8; # 1-3: 1 is closest, 3 is farthest. some ports may utilize 2-4 bars instead
|
||||
|
||||
enum VisualAlert {
|
||||
# these are the choices from the Honda
|
||||
# map as good as you can for your car
|
||||
none @0;
|
||||
fcw @1;
|
||||
steerRequired @2;
|
||||
brakePressed @3;
|
||||
wrongGear @4;
|
||||
seatbeltUnbuckled @5;
|
||||
speedTooHigh @6;
|
||||
ldw @7;
|
||||
}
|
||||
|
||||
enum AudibleAlert {
|
||||
none @0;
|
||||
|
||||
engage @1;
|
||||
disengage @2;
|
||||
refuse @3;
|
||||
|
||||
warningSoft @4;
|
||||
warningImmediate @5;
|
||||
|
||||
prompt @6;
|
||||
promptRepeat @7;
|
||||
promptDistracted @8;
|
||||
promptStarting @9;
|
||||
promptSingleLow @10;
|
||||
promptSingleHigh @11;
|
||||
}
|
||||
}
|
||||
|
||||
gasDEPRECATED @1 :Float32;
|
||||
brakeDEPRECATED @2 :Float32;
|
||||
steeringTorqueDEPRECATED @3 :Float32;
|
||||
activeDEPRECATED @7 :Bool;
|
||||
rollDEPRECATED @8 :Float32;
|
||||
pitchDEPRECATED @9 :Float32;
|
||||
}
|
||||
|
||||
struct CarOutput {
|
||||
# Any car specific rate limits or quirks applied by
|
||||
# the CarController are reflected in actuatorsOutput
|
||||
# and matches what is sent to the car
|
||||
actuatorsOutput @0 :CarControl.Actuators;
|
||||
}
|
||||
|
||||
# ****** car param ******
|
||||
|
||||
struct CarParams {
|
||||
carName @0 :Text;
|
||||
carFingerprint @1 :Text;
|
||||
fuzzyFingerprint @55 :Bool;
|
||||
|
||||
notCar @66 :Bool; # flag for non-car robotics platforms
|
||||
|
||||
pcmCruise @3 :Bool; # is openpilot's state tied to the PCM's cruise state?
|
||||
enableDsu @5 :Bool; # driving support unit
|
||||
enableBsm @56 :Bool; # blind spot monitoring
|
||||
flags @64 :UInt32; # flags for car specific quirks
|
||||
experimentalLongitudinalAvailable @71 :Bool;
|
||||
pcmCruiseSpeed @74 :Bool; # is openpilot's state tied to the PCM's cruise speed?
|
||||
customStockLongAvailable @75 :Bool;
|
||||
spFlags @76 :UInt32; # flags for car specific quirks in sunnypilot
|
||||
|
||||
minEnableSpeed @7 :Float32;
|
||||
minSteerSpeed @8 :Float32;
|
||||
safetyConfigs @62 :List(SafetyConfig);
|
||||
alternativeExperience @65 :Int16; # panda flag for features like no disengage on gas
|
||||
|
||||
# Car docs fields
|
||||
maxLateralAccel @68 :Float32;
|
||||
autoResumeSng @69 :Bool; # describes whether car can resume from a stop automatically
|
||||
|
||||
# things about the car in the manual
|
||||
mass @17 :Float32; # [kg] curb weight: all fluids no cargo
|
||||
wheelbase @18 :Float32; # [m] distance from rear axle to front axle
|
||||
centerToFront @19 :Float32; # [m] distance from center of mass to front axle
|
||||
steerRatio @20 :Float32; # [] ratio of steering wheel angle to front wheel angle
|
||||
steerRatioRear @21 :Float32; # [] ratio of steering wheel angle to rear wheel angle (usually 0)
|
||||
|
||||
# things we can derive
|
||||
rotationalInertia @22 :Float32; # [kg*m2] body rotational inertia
|
||||
tireStiffnessFactor @72 :Float32; # scaling factor used in calculating tireStiffness[Front,Rear]
|
||||
tireStiffnessFront @23 :Float32; # [N/rad] front tire coeff of stiff
|
||||
tireStiffnessRear @24 :Float32; # [N/rad] rear tire coeff of stiff
|
||||
|
||||
longitudinalTuning @25 :LongitudinalPIDTuning;
|
||||
lateralParams @48 :LateralParams;
|
||||
lateralTuning :union {
|
||||
pid @26 :LateralPIDTuning;
|
||||
indiDEPRECATED @27 :LateralINDITuning;
|
||||
lqrDEPRECATED @40 :LateralLQRTuning;
|
||||
torque @67 :LateralTorqueTuning;
|
||||
}
|
||||
|
||||
steerLimitAlert @28 :Bool;
|
||||
steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued
|
||||
|
||||
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
|
||||
vEgoStarting @59 :Float32; # Speed at which the car goes into starting state
|
||||
stoppingControl @31 :Bool; # Does the car allow full control even at lows speeds when stopping
|
||||
steerControlType @34 :SteerControlType;
|
||||
radarUnavailable @35 :Bool; # True when radar objects aren't visible on CAN or aren't parsed out
|
||||
stopAccel @60 :Float32; # Required acceleration to keep vehicle stationary
|
||||
stoppingDecelRate @52 :Float32; # m/s^2/s while trying to stop
|
||||
startAccel @32 :Float32; # Required acceleration to get car moving
|
||||
startingState @70 :Bool; # Does this car make use of special starting state
|
||||
|
||||
steerActuatorDelay @36 :Float32; # Steering wheel actuator delay in seconds
|
||||
longitudinalActuatorDelay @58 :Float32; # Gas/Brake actuator delay in seconds
|
||||
openpilotLongitudinalControl @37 :Bool; # is openpilot doing the longitudinal control?
|
||||
carVin @38 :Text; # VIN number queried during fingerprinting
|
||||
dashcamOnly @41: Bool;
|
||||
passive @73: Bool; # is openpilot in control?
|
||||
transmissionType @43 :TransmissionType;
|
||||
carFw @44 :List(CarFw);
|
||||
|
||||
radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
|
||||
fingerprintSource @49: FingerprintSource;
|
||||
networkLocation @50 :NetworkLocation; # Where Panda/C2 is integrated into the car's CAN network
|
||||
|
||||
wheelSpeedFactor @63 :Float32; # Multiplier on wheels speeds to computer actual speeds
|
||||
|
||||
struct SafetyConfig {
|
||||
safetyModel @0 :SafetyModel;
|
||||
safetyParam @3 :UInt16;
|
||||
safetyParamDEPRECATED @1 :Int16;
|
||||
safetyParam2DEPRECATED @2 :UInt32;
|
||||
}
|
||||
|
||||
struct LateralParams {
|
||||
torqueBP @0 :List(Int32);
|
||||
torqueV @1 :List(Int32);
|
||||
}
|
||||
|
||||
struct LateralPIDTuning {
|
||||
kpBP @0 :List(Float32);
|
||||
kpV @1 :List(Float32);
|
||||
kiBP @2 :List(Float32);
|
||||
kiV @3 :List(Float32);
|
||||
kf @4 :Float32;
|
||||
}
|
||||
|
||||
struct LateralTorqueTuning {
|
||||
useSteeringAngle @0 :Bool;
|
||||
kp @1 :Float32;
|
||||
ki @2 :Float32;
|
||||
friction @3 :Float32;
|
||||
kf @4 :Float32;
|
||||
steeringAngleDeadzoneDeg @5 :Float32;
|
||||
latAccelFactor @6 :Float32;
|
||||
latAccelOffset @7 :Float32;
|
||||
nnModelName @8 :Text;
|
||||
nnModelFuzzyMatch @9 :Bool;
|
||||
}
|
||||
|
||||
struct LongitudinalPIDTuning {
|
||||
kpBP @0 :List(Float32);
|
||||
kpV @1 :List(Float32);
|
||||
kiBP @2 :List(Float32);
|
||||
kiV @3 :List(Float32);
|
||||
kf @6 :Float32;
|
||||
deadzoneBPDEPRECATED @4 :List(Float32);
|
||||
deadzoneVDEPRECATED @5 :List(Float32);
|
||||
}
|
||||
|
||||
struct LateralINDITuning {
|
||||
outerLoopGainBP @4 :List(Float32);
|
||||
outerLoopGainV @5 :List(Float32);
|
||||
innerLoopGainBP @6 :List(Float32);
|
||||
innerLoopGainV @7 :List(Float32);
|
||||
timeConstantBP @8 :List(Float32);
|
||||
timeConstantV @9 :List(Float32);
|
||||
actuatorEffectivenessBP @10 :List(Float32);
|
||||
actuatorEffectivenessV @11 :List(Float32);
|
||||
|
||||
outerLoopGainDEPRECATED @0 :Float32;
|
||||
innerLoopGainDEPRECATED @1 :Float32;
|
||||
timeConstantDEPRECATED @2 :Float32;
|
||||
actuatorEffectivenessDEPRECATED @3 :Float32;
|
||||
}
|
||||
|
||||
struct LateralLQRTuning {
|
||||
scale @0 :Float32;
|
||||
ki @1 :Float32;
|
||||
dcGain @2 :Float32;
|
||||
|
||||
# State space system
|
||||
a @3 :List(Float32);
|
||||
b @4 :List(Float32);
|
||||
c @5 :List(Float32);
|
||||
|
||||
k @6 :List(Float32); # LQR gain
|
||||
l @7 :List(Float32); # Kalman gain
|
||||
}
|
||||
|
||||
enum SafetyModel {
|
||||
silent @0;
|
||||
hondaNidec @1;
|
||||
toyota @2;
|
||||
elm327 @3;
|
||||
gm @4;
|
||||
hondaBoschGiraffe @5;
|
||||
ford @6;
|
||||
cadillac @7;
|
||||
hyundai @8;
|
||||
chrysler @9;
|
||||
tesla @10;
|
||||
subaru @11;
|
||||
gmPassive @12;
|
||||
mazda @13;
|
||||
nissan @14;
|
||||
volkswagen @15;
|
||||
toyotaIpas @16;
|
||||
allOutput @17;
|
||||
gmAscm @18;
|
||||
noOutput @19; # like silent but without silent CAN TXs
|
||||
hondaBosch @20;
|
||||
volkswagenPq @21;
|
||||
subaruPreglobal @22; # pre-Global platform
|
||||
hyundaiLegacy @23;
|
||||
hyundaiCommunity @24;
|
||||
volkswagenMlb @25;
|
||||
hongqi @26;
|
||||
body @27;
|
||||
hyundaiCanfd @28;
|
||||
volkswagenMqbEvo @29;
|
||||
chryslerCusw @30;
|
||||
psa @31;
|
||||
}
|
||||
|
||||
enum SteerControlType {
|
||||
torque @0;
|
||||
angle @1;
|
||||
|
||||
curvatureDEPRECATED @2;
|
||||
}
|
||||
|
||||
enum TransmissionType {
|
||||
unknown @0;
|
||||
automatic @1; # Traditional auto, including DSG
|
||||
manual @2; # True "stick shift" only
|
||||
direct @3; # Electric vehicle or other direct drive
|
||||
cvt @4;
|
||||
}
|
||||
|
||||
struct CarFw {
|
||||
ecu @0 :Ecu;
|
||||
fwVersion @1 :Data;
|
||||
address @2 :UInt32;
|
||||
subAddress @3 :UInt8;
|
||||
responseAddress @4 :UInt32;
|
||||
request @5 :List(Data);
|
||||
brand @6 :Text;
|
||||
bus @7 :UInt8;
|
||||
logging @8 :Bool;
|
||||
obdMultiplexing @9 :Bool;
|
||||
}
|
||||
|
||||
enum Ecu {
|
||||
eps @0;
|
||||
abs @1;
|
||||
fwdRadar @2;
|
||||
fwdCamera @3;
|
||||
engine @4;
|
||||
unknown @5;
|
||||
transmission @8; # Transmission Control Module
|
||||
hybrid @18; # hybrid control unit, e.g. Chrysler's HCP, Honda's IMA Control Unit, Toyota's hybrid control computer
|
||||
srs @9; # airbag
|
||||
gateway @10; # can gateway
|
||||
hud @11; # heads up display
|
||||
combinationMeter @12; # instrument cluster
|
||||
electricBrakeBooster @15;
|
||||
shiftByWire @16;
|
||||
adas @19;
|
||||
cornerRadar @21;
|
||||
hvac @20;
|
||||
parkingAdas @7; # parking assist system ECU, e.g. Toyota's IPAS, Hyundai's RSPA, etc.
|
||||
epb @22; # electronic parking brake
|
||||
telematics @23;
|
||||
body @24; # body control module
|
||||
|
||||
# Toyota only
|
||||
dsu @6;
|
||||
|
||||
# Honda only
|
||||
vsa @13; # Vehicle Stability Assist
|
||||
programmedFuelInjection @14;
|
||||
|
||||
debug @17;
|
||||
}
|
||||
|
||||
enum FingerprintSource {
|
||||
can @0;
|
||||
fw @1;
|
||||
fixed @2;
|
||||
}
|
||||
|
||||
enum NetworkLocation {
|
||||
fwdCamera @0; # Standard/default integration at LKAS camera
|
||||
gateway @1; # Integration at vehicle's CAN gateway
|
||||
}
|
||||
|
||||
enableGasInterceptorDEPRECATED @2 :Bool;
|
||||
enableCameraDEPRECATED @4 :Bool;
|
||||
enableApgsDEPRECATED @6 :Bool;
|
||||
steerRateCostDEPRECATED @33 :Float32;
|
||||
isPandaBlackDEPRECATED @39 :Bool;
|
||||
hasStockCameraDEPRECATED @57 :Bool;
|
||||
safetyParamDEPRECATED @10 :Int16;
|
||||
safetyModelDEPRECATED @9 :SafetyModel;
|
||||
safetyModelPassiveDEPRECATED @42 :SafetyModel = silent;
|
||||
minSpeedCanDEPRECATED @51 :Float32;
|
||||
communityFeatureDEPRECATED @46: Bool;
|
||||
startingAccelRateDEPRECATED @53 :Float32;
|
||||
steerMaxBPDEPRECATED @11 :List(Float32);
|
||||
steerMaxVDEPRECATED @12 :List(Float32);
|
||||
gasMaxBPDEPRECATED @13 :List(Float32);
|
||||
gasMaxVDEPRECATED @14 :List(Float32);
|
||||
brakeMaxBPDEPRECATED @15 :List(Float32);
|
||||
brakeMaxVDEPRECATED @16 :List(Float32);
|
||||
directAccelControlDEPRECATED @30 :Bool;
|
||||
maxSteeringAngleDegDEPRECATED @54 :Float32;
|
||||
longitudinalActuatorDelayLowerBoundDEPRECATEDDEPRECATED @61 :Float32;
|
||||
}
|
||||
192
cereal/custom.capnp
Normal file
192
cereal/custom.capnp
Normal file
@@ -0,0 +1,192 @@
|
||||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
using Car = import "car.capnp";
|
||||
|
||||
@0xb526ba661d550a59;
|
||||
|
||||
# custom.capnp: a home for empty structs reserved for custom forks
|
||||
# These structs are guaranteed to remain reserved and empty in mainline
|
||||
# cereal, so use these if you want custom events in your fork.
|
||||
|
||||
# you can rename the struct, but don't change the identifier
|
||||
|
||||
enum LongitudinalPersonalitySP {
|
||||
aggressive @0;
|
||||
moderate @1;
|
||||
standard @2;
|
||||
relaxed @3;
|
||||
}
|
||||
|
||||
struct ControlsStateSP @0x81c2f05a394cf4af {
|
||||
lateralState @0 :Text;
|
||||
personality @8 :LongitudinalPersonalitySP;
|
||||
|
||||
lateralControlState :union {
|
||||
indiState @1 :LateralINDIState;
|
||||
pidState @2 :LateralPIDState;
|
||||
angleState @3 :LateralAngleState;
|
||||
debugState @4 :LateralDebugState;
|
||||
torqueState @5 :LateralTorqueState;
|
||||
curvatureState @6 :LateralCurvatureState;
|
||||
|
||||
lqrStateDEPRECATED @7 :LateralLQRState;
|
||||
}
|
||||
|
||||
struct LateralINDIState {
|
||||
}
|
||||
|
||||
struct LateralPIDState {
|
||||
}
|
||||
|
||||
struct LateralAngleState {
|
||||
}
|
||||
|
||||
struct LateralDebugState {
|
||||
}
|
||||
|
||||
struct LateralTorqueState {
|
||||
nnLog @0 :List(Float32);
|
||||
}
|
||||
|
||||
struct LateralCurvatureState {
|
||||
}
|
||||
|
||||
struct LateralLQRState {
|
||||
}
|
||||
}
|
||||
|
||||
struct LongitudinalPlanSP @0xaedffd8f31e7b55d {
|
||||
visionTurnControllerState @0 :VisionTurnControllerState;
|
||||
visionTurnSpeed @1 :Float32;
|
||||
visionCurrentLatAcc @16 :Float32;
|
||||
visionMaxPredLatAcc @17 :Float32;
|
||||
|
||||
speedLimitControlState @2 :SpeedLimitControlState;
|
||||
speedLimit @3 :Float32;
|
||||
speedLimitOffset @4 :Float32;
|
||||
distToSpeedLimit @5 :Float32;
|
||||
isMapSpeedLimit @6 :Bool;
|
||||
speedLimitPercOffset @11 :Bool;
|
||||
speedLimitValueOffset @12 :Float32;
|
||||
desiredTF @13 :Float32;
|
||||
notSpeedLimit @14 :Int16;
|
||||
e2eX @15 :List(Float32);
|
||||
e2eBlended @18 :Text;
|
||||
e2eStatus @22 :Bool;
|
||||
|
||||
distToTurn @7 :Float32;
|
||||
turnSpeed @8 :Float32;
|
||||
turnSpeedControlState @9 :SpeedLimitControlState;
|
||||
turnSign @10 :Int16;
|
||||
|
||||
events @19 :List(Car.CarEvent);
|
||||
longitudinalPlanSource @20 :LongitudinalPlanSource;
|
||||
|
||||
personalityDEPRECATED @21 :LongitudinalPersonalitySP;
|
||||
|
||||
enum SpeedLimitControlState {
|
||||
inactive @0; # No speed limit set or not enabled by parameter.
|
||||
tempInactive @1; # User wants to ignore speed limit until it changes.
|
||||
adapting @2; # Reducing speed to match new speed limit.
|
||||
active @3; # Cruising at speed limit.
|
||||
preActive @4;
|
||||
}
|
||||
|
||||
enum VisionTurnControllerState {
|
||||
disabled @0; # No predicted substantial turn on vision range or feature disabled.
|
||||
entering @1; # A substantial turn is predicted ahead, adapting speed to turn comfort levels.
|
||||
turning @2; # Actively turning. Managing acceleration to provide a roll on turn feeling.
|
||||
leaving @3; # Road ahead straightens. Start to allow positive acceleration.
|
||||
}
|
||||
|
||||
enum LongitudinalPlanSource {
|
||||
cruise @0;
|
||||
lead0 @1;
|
||||
lead1 @2;
|
||||
lead2 @3;
|
||||
e2e @4;
|
||||
turn @5;
|
||||
limit @6;
|
||||
turnlimit @7;
|
||||
}
|
||||
}
|
||||
|
||||
struct LateralPlanSP @0xf35cc4560bbf6ec2 {
|
||||
laneWidth @0 :Float32;
|
||||
lProb @1 :Float32;
|
||||
rProb @2 :Float32;
|
||||
|
||||
dProb @3 :Float32;
|
||||
|
||||
dynamicLaneProfile @4 :Int8;
|
||||
standstillElapsed @5 :Float32;
|
||||
dynamicLaneProfileStatus @9 :Bool;
|
||||
|
||||
dPathWLinesXDEPRECATED @6 :List(Float32);
|
||||
dPathWLinesYDEPRECATED @7 :List(Float32);
|
||||
laneChangePrevDEPRECATED @8 :Bool;
|
||||
laneChangeEdgeBlockDEPRECATED @10 :Bool;
|
||||
}
|
||||
|
||||
struct DriverMonitoringStateSP @0xda96579883444c35 {
|
||||
handsOnWheelState @0 :HandsOnWheelState;
|
||||
notModified @1 :Float32;
|
||||
|
||||
enum HandsOnWheelState {
|
||||
none @0; # hand on wheel monitoring inactive
|
||||
ok @1; # driver has hands on steering wheel
|
||||
minor @2; # hands off steering wheel for acceptable period
|
||||
warning @3; # hands off steering wheel for warning period
|
||||
critical @4; # # hands off steering wheel for critical period
|
||||
terminal @5; # # hands off steering wheel for terminal period
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveMapDataSP @0x80ae746ee2596b11 {
|
||||
speedLimitValid @0 :Bool;
|
||||
speedLimit @1 :Float32;
|
||||
speedLimitAheadValid @2 :Bool;
|
||||
speedLimitAhead @3 :Float32;
|
||||
speedLimitAheadDistance @4 :Float32;
|
||||
turnSpeedLimitValid @5 :Bool;
|
||||
turnSpeedLimit @6 :Float32;
|
||||
turnSpeedLimitEndDistance @7 :Float32;
|
||||
turnSpeedLimitSign @8 :Int16;
|
||||
turnSpeedLimitsAhead @9 :List(Float32);
|
||||
turnSpeedLimitsAheadDistances @10 :List(Float32);
|
||||
turnSpeedLimitsAheadSigns @11 :List(Int16);
|
||||
lastGpsTimestamp @12 :Int64; # Milliseconds since January 1, 1970.
|
||||
currentRoadName @13 :Text;
|
||||
lastGpsLatitude @14 :Float64;
|
||||
lastGpsLongitude @15 :Float64;
|
||||
lastGpsSpeed @16 :Float32;
|
||||
lastGpsBearingDeg @17 :Float32;
|
||||
lastGpsAccuracy @18 :Float32;
|
||||
lastGpsBearingAccuracyDeg @19 :Float32;
|
||||
dataType @20 :DataType;
|
||||
|
||||
enum DataType {
|
||||
default @0;
|
||||
offline @1;
|
||||
online @2;
|
||||
}
|
||||
}
|
||||
|
||||
struct E2eLongStateSP @0xa5cd762cd951a455 {
|
||||
status @0 :UInt16;
|
||||
}
|
||||
|
||||
struct ModelDataV2SP @0xf98d843bfd7004a3 {
|
||||
laneChangePrev @0 :Bool;
|
||||
laneChangeEdgeBlock @1 :Bool;
|
||||
}
|
||||
|
||||
struct CustomReserved7 @0xb86e6369214c01c8 {
|
||||
}
|
||||
|
||||
struct CustomReserved8 @0xf416ec09499d9d19 {
|
||||
}
|
||||
|
||||
struct CustomReserved9 @0xa1680744031fdb2d {
|
||||
}
|
||||
26
cereal/include/c++.capnp
Normal file
26
cereal/include/c++.capnp
Normal file
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2013-2014 Sandstorm Development Group, Inc. and contributors
|
||||
# Licensed under the MIT License:
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
|
||||
@0xbdf87d7bb8304e81;
|
||||
$namespace("capnp::annotations");
|
||||
|
||||
annotation namespace(file): Text;
|
||||
annotation name(field, enumerant, struct, enum, interface, method, param, group, union): Text;
|
||||
574
cereal/legacy.capnp
Normal file
574
cereal/legacy.capnp
Normal file
@@ -0,0 +1,574 @@
|
||||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0x80ef1ec4889c2a63;
|
||||
|
||||
# legacy.capnp: a home for deprecated structs
|
||||
|
||||
struct LogRotate @0x9811e1f38f62f2d1 {
|
||||
segmentNum @0 :Int32;
|
||||
path @1 :Text;
|
||||
}
|
||||
|
||||
struct LiveUI @0xc08240f996aefced {
|
||||
rearViewCam @0 :Bool;
|
||||
alertText1 @1 :Text;
|
||||
alertText2 @2 :Text;
|
||||
awarenessStatus @3 :Float32;
|
||||
}
|
||||
|
||||
struct UiLayoutState @0x88dcce08ad29dda0 {
|
||||
activeApp @0 :App;
|
||||
sidebarCollapsed @1 :Bool;
|
||||
mapEnabled @2 :Bool;
|
||||
mockEngaged @3 :Bool;
|
||||
|
||||
enum App @0x9917470acf94d285 {
|
||||
home @0;
|
||||
music @1;
|
||||
nav @2;
|
||||
settings @3;
|
||||
none @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct OrbslamCorrection @0x8afd33dc9b35e1aa {
|
||||
correctionMonoTime @0 :UInt64;
|
||||
prePositionECEF @1 :List(Float64);
|
||||
postPositionECEF @2 :List(Float64);
|
||||
prePoseQuatECEF @3 :List(Float32);
|
||||
postPoseQuatECEF @4 :List(Float32);
|
||||
numInliers @5 :UInt32;
|
||||
}
|
||||
|
||||
struct EthernetPacket @0xa99a9d5b33cf5859 {
|
||||
pkt @0 :Data;
|
||||
ts @1 :Float32;
|
||||
}
|
||||
|
||||
struct CellInfo @0xcff7566681c277ce {
|
||||
timestamp @0 :UInt64;
|
||||
repr @1 :Text; # android toString() for now
|
||||
}
|
||||
|
||||
struct WifiScan @0xd4df5a192382ba0b {
|
||||
bssid @0 :Text;
|
||||
ssid @1 :Text;
|
||||
capabilities @2 :Text;
|
||||
frequency @3 :Int32;
|
||||
level @4 :Int32;
|
||||
timestamp @5 :Int64;
|
||||
|
||||
centerFreq0 @6 :Int32;
|
||||
centerFreq1 @7 :Int32;
|
||||
channelWidth @8 :ChannelWidth;
|
||||
operatorFriendlyName @9 :Text;
|
||||
venueName @10 :Text;
|
||||
is80211mcResponder @11 :Bool;
|
||||
passpoint @12 :Bool;
|
||||
|
||||
distanceCm @13 :Int32;
|
||||
distanceSdCm @14 :Int32;
|
||||
|
||||
enum ChannelWidth @0xcb6a279f015f6b51 {
|
||||
w20Mhz @0;
|
||||
w40Mhz @1;
|
||||
w80Mhz @2;
|
||||
w160Mhz @3;
|
||||
w80Plus80Mhz @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveEventData @0x94b7baa90c5c321e {
|
||||
name @0 :Text;
|
||||
value @1 :Int32;
|
||||
}
|
||||
|
||||
struct ModelData @0xb8aad62cffef28a9 {
|
||||
frameId @0 :UInt32;
|
||||
frameAge @12 :UInt32;
|
||||
frameDropPerc @13 :Float32;
|
||||
timestampEof @9 :UInt64;
|
||||
modelExecutionTime @14 :Float32;
|
||||
gpuExecutionTime @16 :Float32;
|
||||
rawPred @15 :Data;
|
||||
|
||||
path @1 :PathData;
|
||||
leftLane @2 :PathData;
|
||||
rightLane @3 :PathData;
|
||||
lead @4 :LeadData;
|
||||
freePath @6 :List(Float32);
|
||||
|
||||
settings @5 :ModelSettings;
|
||||
leadFuture @7 :LeadData;
|
||||
speed @8 :List(Float32);
|
||||
meta @10 :MetaData;
|
||||
longitudinal @11 :LongitudinalData;
|
||||
|
||||
struct PathData @0x8817eeea389e9f08 {
|
||||
points @0 :List(Float32);
|
||||
prob @1 :Float32;
|
||||
std @2 :Float32;
|
||||
stds @3 :List(Float32);
|
||||
poly @4 :List(Float32);
|
||||
validLen @5 :Float32;
|
||||
}
|
||||
|
||||
struct LeadData @0xd1c9bef96d26fa91 {
|
||||
dist @0 :Float32;
|
||||
prob @1 :Float32;
|
||||
std @2 :Float32;
|
||||
relVel @3 :Float32;
|
||||
relVelStd @4 :Float32;
|
||||
relY @5 :Float32;
|
||||
relYStd @6 :Float32;
|
||||
relA @7 :Float32;
|
||||
relAStd @8 :Float32;
|
||||
}
|
||||
|
||||
struct ModelSettings @0xa26e3710efd3e914 {
|
||||
bigBoxX @0 :UInt16;
|
||||
bigBoxY @1 :UInt16;
|
||||
bigBoxWidth @2 :UInt16;
|
||||
bigBoxHeight @3 :UInt16;
|
||||
boxProjection @4 :List(Float32);
|
||||
yuvCorrection @5 :List(Float32);
|
||||
inputTransform @6 :List(Float32);
|
||||
}
|
||||
|
||||
struct MetaData @0x9744f25fb60f2bf8 {
|
||||
engagedProb @0 :Float32;
|
||||
desirePrediction @1 :List(Float32);
|
||||
brakeDisengageProb @2 :Float32;
|
||||
gasDisengageProb @3 :Float32;
|
||||
steerOverrideProb @4 :Float32;
|
||||
desireState @5 :List(Float32);
|
||||
}
|
||||
|
||||
struct LongitudinalData @0xf98f999c6a071122 {
|
||||
distances @2 :List(Float32);
|
||||
speeds @0 :List(Float32);
|
||||
accelerations @1 :List(Float32);
|
||||
}
|
||||
}
|
||||
|
||||
struct ECEFPoint @0xc25bbbd524983447 {
|
||||
x @0 :Float64;
|
||||
y @1 :Float64;
|
||||
z @2 :Float64;
|
||||
}
|
||||
|
||||
struct ECEFPointDEPRECATED @0xe10e21168db0c7f7 {
|
||||
x @0 :Float32;
|
||||
y @1 :Float32;
|
||||
z @2 :Float32;
|
||||
}
|
||||
|
||||
struct GPSPlannerPoints @0xab54c59699f8f9f3 {
|
||||
curPosDEPRECATED @0 :ECEFPointDEPRECATED;
|
||||
pointsDEPRECATED @1 :List(ECEFPointDEPRECATED);
|
||||
curPos @6 :ECEFPoint;
|
||||
points @7 :List(ECEFPoint);
|
||||
valid @2 :Bool;
|
||||
trackName @3 :Text;
|
||||
speedLimit @4 :Float32;
|
||||
accelTarget @5 :Float32;
|
||||
}
|
||||
|
||||
struct GPSPlannerPlan @0xf5ad1d90cdc1dd6b {
|
||||
valid @0 :Bool;
|
||||
poly @1 :List(Float32);
|
||||
trackName @2 :Text;
|
||||
speed @3 :Float32;
|
||||
acceleration @4 :Float32;
|
||||
pointsDEPRECATED @5 :List(ECEFPointDEPRECATED);
|
||||
points @6 :List(ECEFPoint);
|
||||
xLookahead @7 :Float32;
|
||||
}
|
||||
|
||||
struct UiNavigationEvent @0x90c8426c3eaddd3b {
|
||||
type @0: Type;
|
||||
status @1: Status;
|
||||
distanceTo @2: Float32;
|
||||
endRoadPointDEPRECATED @3: ECEFPointDEPRECATED;
|
||||
endRoadPoint @4: ECEFPoint;
|
||||
|
||||
enum Type @0xe8db07dcf8fcea05 {
|
||||
none @0;
|
||||
laneChangeLeft @1;
|
||||
laneChangeRight @2;
|
||||
mergeLeft @3;
|
||||
mergeRight @4;
|
||||
turnLeft @5;
|
||||
turnRight @6;
|
||||
}
|
||||
|
||||
enum Status @0xb9aa88c75ef99a1f {
|
||||
none @0;
|
||||
passive @1;
|
||||
approaching @2;
|
||||
active @3;
|
||||
}
|
||||
}
|
||||
|
||||
struct LiveLocationData @0xb99b2bc7a57e8128 {
|
||||
status @0 :UInt8;
|
||||
|
||||
# 3D fix
|
||||
lat @1 :Float64;
|
||||
lon @2 :Float64;
|
||||
alt @3 :Float32; # m
|
||||
|
||||
# speed
|
||||
speed @4 :Float32; # m/s
|
||||
|
||||
# NED velocity components
|
||||
vNED @5 :List(Float32);
|
||||
|
||||
# roll, pitch, heading (x,y,z)
|
||||
roll @6 :Float32; # WRT to center of earth?
|
||||
pitch @7 :Float32; # WRT to center of earth?
|
||||
heading @8 :Float32; # WRT to north?
|
||||
|
||||
# what are these?
|
||||
wanderAngle @9 :Float32;
|
||||
trackAngle @10 :Float32;
|
||||
|
||||
# car frame -- https://upload.wikimedia.org/wikipedia/commons/f/f5/RPY_angles_of_cars.png
|
||||
|
||||
# gyro, in car frame, deg/s
|
||||
gyro @11 :List(Float32);
|
||||
|
||||
# accel, in car frame, m/s^2
|
||||
accel @12 :List(Float32);
|
||||
|
||||
accuracy @13 :Accuracy;
|
||||
|
||||
source @14 :SensorSource;
|
||||
# if we are fixing a location in the past
|
||||
fixMonoTime @15 :UInt64;
|
||||
|
||||
gpsWeek @16 :Int32;
|
||||
timeOfWeek @17 :Float64;
|
||||
|
||||
positionECEF @18 :List(Float64);
|
||||
poseQuatECEF @19 :List(Float32);
|
||||
pitchCalibration @20 :Float32;
|
||||
yawCalibration @21 :Float32;
|
||||
imuFrame @22 :List(Float32);
|
||||
|
||||
struct Accuracy @0x943dc4625473b03f {
|
||||
pNEDError @0 :List(Float32);
|
||||
vNEDError @1 :List(Float32);
|
||||
rollError @2 :Float32;
|
||||
pitchError @3 :Float32;
|
||||
headingError @4 :Float32;
|
||||
ellipsoidSemiMajorError @5 :Float32;
|
||||
ellipsoidSemiMinorError @6 :Float32;
|
||||
ellipsoidOrientationError @7 :Float32;
|
||||
}
|
||||
|
||||
enum SensorSource @0xc871d3cc252af657 {
|
||||
applanix @0;
|
||||
kalman @1;
|
||||
orbslam @2;
|
||||
timing @3;
|
||||
dummy @4;
|
||||
}
|
||||
}
|
||||
|
||||
struct OrbOdometry @0xd7700859ed1f5b76 {
|
||||
# timing first
|
||||
startMonoTime @0 :UInt64;
|
||||
endMonoTime @1 :UInt64;
|
||||
|
||||
# fundamental matrix and error
|
||||
f @2: List(Float64);
|
||||
err @3: Float64;
|
||||
|
||||
# number of inlier points
|
||||
inliers @4: Int32;
|
||||
|
||||
# for debug only
|
||||
# indexed by endMonoTime features
|
||||
# value is startMonoTime feature match
|
||||
# -1 if no match
|
||||
matches @5: List(Int16);
|
||||
}
|
||||
|
||||
struct OrbFeatures @0xcd60164a8a0159ef {
|
||||
timestampEof @0 :UInt64;
|
||||
# transposed arrays of normalized image coordinates
|
||||
# len(xs) == len(ys) == len(descriptors) * 32
|
||||
xs @1 :List(Float32);
|
||||
ys @2 :List(Float32);
|
||||
descriptors @3 :Data;
|
||||
octaves @4 :List(Int8);
|
||||
|
||||
# match index to last OrbFeatures
|
||||
# -1 if no match
|
||||
timestampLastEof @5 :UInt64;
|
||||
matches @6: List(Int16);
|
||||
}
|
||||
|
||||
struct OrbFeaturesSummary @0xd500d30c5803fa4f {
|
||||
timestampEof @0 :UInt64;
|
||||
timestampLastEof @1 :UInt64;
|
||||
|
||||
featureCount @2 :UInt16;
|
||||
matchCount @3 :UInt16;
|
||||
computeNs @4 :UInt64;
|
||||
}
|
||||
|
||||
struct OrbKeyFrame @0xc8233c0345e27e24 {
|
||||
# this is a globally unique id for the KeyFrame
|
||||
id @0: UInt64;
|
||||
|
||||
# this is the location of the KeyFrame
|
||||
pos @1: ECEFPoint;
|
||||
|
||||
# these are the features in the world
|
||||
# len(dpos) == len(descriptors) * 32
|
||||
dpos @2 :List(ECEFPoint);
|
||||
descriptors @3 :Data;
|
||||
}
|
||||
|
||||
struct KalmanOdometry @0x92e21bb7ea38793a {
|
||||
trans @0 :List(Float32); # m/s in device frame
|
||||
rot @1 :List(Float32); # rad/s in device frame
|
||||
transStd @2 :List(Float32); # std m/s in device frame
|
||||
rotStd @3 :List(Float32); # std rad/s in device frame
|
||||
}
|
||||
|
||||
struct OrbObservation @0x9b326d4e436afec7 {
|
||||
observationMonoTime @0 :UInt64;
|
||||
normalizedCoordinates @1 :List(Float32);
|
||||
locationECEF @2 :List(Float64);
|
||||
matchDistance @3: UInt32;
|
||||
}
|
||||
|
||||
struct CalibrationFeatures @0x8fdfadb254ea867a {
|
||||
frameId @0 :UInt32;
|
||||
|
||||
p0 @1 :List(Float32);
|
||||
p1 @2 :List(Float32);
|
||||
status @3 :List(Int8);
|
||||
}
|
||||
|
||||
struct NavStatus @0xbd8822120928120c {
|
||||
isNavigating @0 :Bool;
|
||||
currentAddress @1 :Address;
|
||||
|
||||
struct Address @0xce7cd672cacc7814 {
|
||||
title @0 :Text;
|
||||
lat @1 :Float64;
|
||||
lng @2 :Float64;
|
||||
house @3 :Text;
|
||||
address @4 :Text;
|
||||
street @5 :Text;
|
||||
city @6 :Text;
|
||||
state @7 :Text;
|
||||
country @8 :Text;
|
||||
}
|
||||
}
|
||||
|
||||
struct NavUpdate @0xdb98be6565516acb {
|
||||
isNavigating @0 :Bool;
|
||||
curSegment @1 :Int32;
|
||||
segments @2 :List(Segment);
|
||||
|
||||
struct LatLng @0x9eaef9187cadbb9b {
|
||||
lat @0 :Float64;
|
||||
lng @1 :Float64;
|
||||
}
|
||||
|
||||
struct Segment @0xa5b39b4fc4d7da3f {
|
||||
from @0 :LatLng;
|
||||
to @1 :LatLng;
|
||||
updateTime @2 :Int32;
|
||||
distance @3 :Int32;
|
||||
crossTime @4 :Int32;
|
||||
exitNo @5 :Int32;
|
||||
instruction @6 :Instruction;
|
||||
|
||||
parts @7 :List(LatLng);
|
||||
|
||||
enum Instruction @0xc5417a637451246f {
|
||||
turnLeft @0;
|
||||
turnRight @1;
|
||||
keepLeft @2;
|
||||
keepRight @3;
|
||||
straight @4;
|
||||
roundaboutExitNumber @5;
|
||||
roundaboutExit @6;
|
||||
roundaboutTurnLeft @7;
|
||||
unkn8 @8;
|
||||
roundaboutStraight @9;
|
||||
unkn10 @10;
|
||||
roundaboutTurnRight @11;
|
||||
unkn12 @12;
|
||||
roundaboutUturn @13;
|
||||
unkn14 @14;
|
||||
arrive @15;
|
||||
exitLeft @16;
|
||||
exitRight @17;
|
||||
unkn18 @18;
|
||||
uturn @19;
|
||||
# ...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct TrafficEvent @0xacfa74a094e62626 {
|
||||
type @0 :Type;
|
||||
distance @1 :Float32;
|
||||
action @2 :Action;
|
||||
resuming @3 :Bool;
|
||||
|
||||
enum Type @0xd85d75253435bf4b {
|
||||
stopSign @0;
|
||||
lightRed @1;
|
||||
lightYellow @2;
|
||||
lightGreen @3;
|
||||
stopLight @4;
|
||||
}
|
||||
|
||||
enum Action @0xa6f6ce72165ccb49 {
|
||||
none @0;
|
||||
yield @1;
|
||||
stop @2;
|
||||
resumeReady @3;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
struct AndroidGnss @0xdfdf30d03fc485bd {
|
||||
union {
|
||||
measurements @0 :Measurements;
|
||||
navigationMessage @1 :NavigationMessage;
|
||||
}
|
||||
|
||||
struct Measurements @0xa20710d4f428d6cd {
|
||||
clock @0 :Clock;
|
||||
measurements @1 :List(Measurement);
|
||||
|
||||
struct Clock @0xa0e27b453a38f450 {
|
||||
timeNanos @0 :Int64;
|
||||
hardwareClockDiscontinuityCount @1 :Int32;
|
||||
|
||||
hasTimeUncertaintyNanos @2 :Bool;
|
||||
timeUncertaintyNanos @3 :Float64;
|
||||
|
||||
hasLeapSecond @4 :Bool;
|
||||
leapSecond @5 :Int32;
|
||||
|
||||
hasFullBiasNanos @6 :Bool;
|
||||
fullBiasNanos @7 :Int64;
|
||||
|
||||
hasBiasNanos @8 :Bool;
|
||||
biasNanos @9 :Float64;
|
||||
|
||||
hasBiasUncertaintyNanos @10 :Bool;
|
||||
biasUncertaintyNanos @11 :Float64;
|
||||
|
||||
hasDriftNanosPerSecond @12 :Bool;
|
||||
driftNanosPerSecond @13 :Float64;
|
||||
|
||||
hasDriftUncertaintyNanosPerSecond @14 :Bool;
|
||||
driftUncertaintyNanosPerSecond @15 :Float64;
|
||||
}
|
||||
|
||||
struct Measurement @0xd949bf717d77614d {
|
||||
svId @0 :Int32;
|
||||
constellation @1 :Constellation;
|
||||
|
||||
timeOffsetNanos @2 :Float64;
|
||||
state @3 :Int32;
|
||||
receivedSvTimeNanos @4 :Int64;
|
||||
receivedSvTimeUncertaintyNanos @5 :Int64;
|
||||
cn0DbHz @6 :Float64;
|
||||
pseudorangeRateMetersPerSecond @7 :Float64;
|
||||
pseudorangeRateUncertaintyMetersPerSecond @8 :Float64;
|
||||
accumulatedDeltaRangeState @9 :Int32;
|
||||
accumulatedDeltaRangeMeters @10 :Float64;
|
||||
accumulatedDeltaRangeUncertaintyMeters @11 :Float64;
|
||||
|
||||
hasCarrierFrequencyHz @12 :Bool;
|
||||
carrierFrequencyHz @13 :Float32;
|
||||
hasCarrierCycles @14 :Bool;
|
||||
carrierCycles @15 :Int64;
|
||||
hasCarrierPhase @16 :Bool;
|
||||
carrierPhase @17 :Float64;
|
||||
hasCarrierPhaseUncertainty @18 :Bool;
|
||||
carrierPhaseUncertainty @19 :Float64;
|
||||
hasSnrInDb @20 :Bool;
|
||||
snrInDb @21 :Float64;
|
||||
|
||||
multipathIndicator @22 :MultipathIndicator;
|
||||
|
||||
enum Constellation @0x9ef1f3ff0deb5ffb {
|
||||
unknown @0;
|
||||
gps @1;
|
||||
sbas @2;
|
||||
glonass @3;
|
||||
qzss @4;
|
||||
beidou @5;
|
||||
galileo @6;
|
||||
}
|
||||
|
||||
enum State @0xcbb9490adce12d72 {
|
||||
unknown @0;
|
||||
codeLock @1;
|
||||
bitSync @2;
|
||||
subframeSync @3;
|
||||
towDecoded @4;
|
||||
msecAmbiguous @5;
|
||||
symbolSync @6;
|
||||
gloStringSync @7;
|
||||
gloTodDecoded @8;
|
||||
bdsD2BitSync @9;
|
||||
bdsD2SubframeSync @10;
|
||||
galE1bcCodeLock @11;
|
||||
galE1c2ndCodeLock @12;
|
||||
galE1bPageSync @13;
|
||||
sbasSync @14;
|
||||
}
|
||||
|
||||
enum MultipathIndicator @0xc04e7b6231d4caa8 {
|
||||
unknown @0;
|
||||
detected @1;
|
||||
notDetected @2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NavigationMessage @0xe2517b083095fd4e {
|
||||
type @0 :Int32;
|
||||
svId @1 :Int32;
|
||||
messageId @2 :Int32;
|
||||
submessageId @3 :Int32;
|
||||
data @4 :Data;
|
||||
status @5 :Status;
|
||||
|
||||
enum Status @0xec1ff7996b35366f {
|
||||
unknown @0;
|
||||
parityPassed @1;
|
||||
parityRebuilt @2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct LidarPts @0xe3d6685d4e9d8f7a {
|
||||
r @0 :List(UInt16); # uint16 m*500.0
|
||||
theta @1 :List(UInt16); # uint16 deg*100.0
|
||||
reflect @2 :List(UInt8); # uint8 0-255
|
||||
|
||||
# For storing out of file.
|
||||
idx @3 :UInt64;
|
||||
|
||||
# For storing in file
|
||||
pkt @4 :Data;
|
||||
}
|
||||
|
||||
|
||||
2405
cereal/log.capnp
Normal file
2405
cereal/log.capnp
Normal file
File diff suppressed because it is too large
Load Diff
49
cereal/maptile.capnp
Normal file
49
cereal/maptile.capnp
Normal file
@@ -0,0 +1,49 @@
|
||||
using Cxx = import "./include/c++.capnp";
|
||||
$Cxx.namespace("cereal");
|
||||
|
||||
@0xa086df597ef5d7a0;
|
||||
|
||||
# Geometry
|
||||
struct Point {
|
||||
x @0: Float64;
|
||||
y @1: Float64;
|
||||
z @2: Float64;
|
||||
}
|
||||
|
||||
struct PolyLine {
|
||||
points @0: List(Point);
|
||||
}
|
||||
|
||||
# Map features
|
||||
struct Lane {
|
||||
id @0 :Text;
|
||||
|
||||
leftBoundary @1 :LaneBoundary;
|
||||
rightBoundary @2 :LaneBoundary;
|
||||
|
||||
leftAdjacentId @3 :Text;
|
||||
rightAdjacentId @4 :Text;
|
||||
|
||||
inboundIds @5 :List(Text);
|
||||
outboundIds @6 :List(Text);
|
||||
|
||||
struct LaneBoundary {
|
||||
polyLine @0 :PolyLine;
|
||||
startHeading @1 :Float32; # WRT north
|
||||
}
|
||||
}
|
||||
|
||||
# Map tiles
|
||||
struct TileSummary {
|
||||
version @0 :Text;
|
||||
updatedAt @1 :UInt64; # Millis since epoch
|
||||
|
||||
level @2 :UInt8;
|
||||
x @3 :UInt16;
|
||||
y @4 :UInt16;
|
||||
}
|
||||
|
||||
struct MapTile {
|
||||
summary @0 :TileSummary;
|
||||
lanes @1 :List(Lane);
|
||||
}
|
||||
252
cereal/messaging/__init__.py
Normal file
252
cereal/messaging/__init__.py
Normal file
@@ -0,0 +1,252 @@
|
||||
# must be built with scons
|
||||
from msgq.ipc_pyx import Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
|
||||
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
|
||||
from msgq.ipc_pyx import MultiplePublishersError, IpcError
|
||||
from msgq import fake_event_handle, pub_sock, sub_sock, drain_sock_raw, context
|
||||
|
||||
import os
|
||||
import capnp
|
||||
import time
|
||||
|
||||
from typing import Optional, List, Union, Dict, Deque
|
||||
from collections import deque
|
||||
|
||||
from cereal import log
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
NO_TRAVERSAL_LIMIT = 2**64-1
|
||||
|
||||
|
||||
def log_from_bytes(dat: bytes) -> capnp.lib.capnp._DynamicStructReader:
|
||||
with log.Event.from_bytes(dat, traversal_limit_in_words=NO_TRAVERSAL_LIMIT) as msg:
|
||||
return msg
|
||||
|
||||
|
||||
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
|
||||
args = {
|
||||
'valid': False,
|
||||
'logMonoTime': int(time.monotonic() * 1e9),
|
||||
**kwargs
|
||||
}
|
||||
dat = log.Event.new_message(**args)
|
||||
if service is not None:
|
||||
if size is None:
|
||||
dat.init(service)
|
||||
else:
|
||||
dat.init(service, size)
|
||||
return dat
|
||||
|
||||
|
||||
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]:
|
||||
"""Receive all message currently available on the queue"""
|
||||
msgs = drain_sock_raw(sock, wait_for_one=wait_for_one)
|
||||
return [log_from_bytes(m) for m in msgs]
|
||||
|
||||
|
||||
# TODO: print when we drop packets?
|
||||
def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
|
||||
dat = None
|
||||
|
||||
while 1:
|
||||
if wait and dat is None:
|
||||
recv = sock.receive()
|
||||
else:
|
||||
recv = sock.receive(non_blocking=True)
|
||||
|
||||
if recv is None: # Timeout hit
|
||||
break
|
||||
|
||||
dat = recv
|
||||
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
dat = sock.receive()
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]:
|
||||
dat = sock.receive(non_blocking=True)
|
||||
if dat is not None:
|
||||
dat = log_from_bytes(dat)
|
||||
return dat
|
||||
|
||||
|
||||
def recv_one_retry(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader:
|
||||
"""Keep receiving until we get a message"""
|
||||
while True:
|
||||
dat = sock.receive()
|
||||
if dat is not None:
|
||||
return log_from_bytes(dat)
|
||||
|
||||
|
||||
class SubMaster:
|
||||
def __init__(self, services: List[str], poll: Optional[str] = None,
|
||||
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None,
|
||||
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None):
|
||||
self.frame = -1
|
||||
self.seen = {s: False for s in services}
|
||||
self.updated = {s: False for s in services}
|
||||
self.recv_time = {s: 0. for s in services}
|
||||
self.recv_frame = {s: 0 for s in services}
|
||||
self.alive = {s: False for s in services}
|
||||
self.freq_ok = {s: False for s in services}
|
||||
self.recv_dts: Dict[str, Deque[float]] = {}
|
||||
self.sock = {}
|
||||
self.data = {}
|
||||
self.valid = {}
|
||||
self.logMonoTime = {}
|
||||
|
||||
self.max_freq = {}
|
||||
self.min_freq = {}
|
||||
|
||||
self.poller = Poller()
|
||||
polled_services = set([poll, ] if poll is not None else services)
|
||||
self.non_polled_services = set(services) - polled_services
|
||||
|
||||
self.ignore_average_freq = [] if ignore_avg_freq is None else ignore_avg_freq
|
||||
self.ignore_alive = [] if ignore_alive is None else ignore_alive
|
||||
self.ignore_valid = [] if ignore_valid is None else ignore_valid
|
||||
|
||||
self.simulation = bool(int(os.getenv("SIMULATION", "0")))
|
||||
|
||||
# if freq and poll aren't specified, assume the max to be conservative
|
||||
assert frequency is None or poll is None, "Do not specify 'frequency' - frequency of the polled service will be used."
|
||||
self.update_freq = frequency or max([SERVICE_LIST[s].frequency for s in polled_services])
|
||||
|
||||
for s in services:
|
||||
p = self.poller if s not in self.non_polled_services else None
|
||||
self.sock[s] = sub_sock(s, poller=p, addr=addr, conflate=True)
|
||||
|
||||
try:
|
||||
data = new_message(s)
|
||||
except capnp.lib.capnp.KjException:
|
||||
data = new_message(s, 0) # lists
|
||||
|
||||
self.data[s] = getattr(data.as_reader(), s)
|
||||
self.logMonoTime[s] = 0
|
||||
self.valid[s] = True # FIXME: this should default to False
|
||||
|
||||
freq = max(min([SERVICE_LIST[s].frequency, self.update_freq]), 1.)
|
||||
if s == poll:
|
||||
max_freq = freq
|
||||
min_freq = freq
|
||||
else:
|
||||
max_freq = min(freq, self.update_freq)
|
||||
if SERVICE_LIST[s].frequency >= 2*self.update_freq:
|
||||
min_freq = self.update_freq
|
||||
elif self.update_freq >= 2*SERVICE_LIST[s].frequency:
|
||||
min_freq = freq
|
||||
else:
|
||||
min_freq = min(freq, freq / 2.)
|
||||
self.max_freq[s] = max_freq*1.2
|
||||
self.min_freq[s] = min_freq*0.8
|
||||
self.recv_dts[s] = deque(maxlen=int(10*freq))
|
||||
|
||||
def __getitem__(self, s: str) -> capnp.lib.capnp._DynamicStructReader:
|
||||
return self.data[s]
|
||||
|
||||
def _check_avg_freq(self, s: str) -> bool:
|
||||
return SERVICE_LIST[s].frequency > 0.99 and (s not in self.ignore_average_freq) and (s not in self.ignore_alive)
|
||||
|
||||
def update(self, timeout: int = 100) -> None:
|
||||
msgs = []
|
||||
for sock in self.poller.poll(timeout):
|
||||
msgs.append(recv_one_or_none(sock))
|
||||
|
||||
# non-blocking receive for non-polled sockets
|
||||
for s in self.non_polled_services:
|
||||
msgs.append(recv_one_or_none(self.sock[s]))
|
||||
self.update_msgs(time.monotonic(), msgs)
|
||||
|
||||
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None:
|
||||
self.frame += 1
|
||||
self.updated = dict.fromkeys(self.updated, False)
|
||||
for msg in msgs:
|
||||
if msg is None:
|
||||
continue
|
||||
|
||||
s = msg.which()
|
||||
self.seen[s] = True
|
||||
self.updated[s] = True
|
||||
|
||||
if self.recv_time[s] > 1e-5:
|
||||
self.recv_dts[s].append(cur_time - self.recv_time[s])
|
||||
self.recv_time[s] = cur_time
|
||||
self.recv_frame[s] = self.frame
|
||||
self.data[s] = getattr(msg, s)
|
||||
self.logMonoTime[s] = msg.logMonoTime
|
||||
self.valid[s] = msg.valid
|
||||
|
||||
for s in self.data:
|
||||
if SERVICE_LIST[s].frequency > 1e-5 and not self.simulation:
|
||||
# alive if delay is within 10x the expected frequency
|
||||
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency)
|
||||
|
||||
# check average frequency; slow to fall, quick to recover
|
||||
dts = self.recv_dts[s]
|
||||
assert dts.maxlen is not None
|
||||
recent_dts = list(dts)[-int(dts.maxlen / 10):]
|
||||
try:
|
||||
avg_freq = 1 / (sum(dts) / len(dts))
|
||||
avg_freq_recent = 1 / (sum(recent_dts) / len(recent_dts))
|
||||
except ZeroDivisionError:
|
||||
avg_freq = 0
|
||||
avg_freq_recent = 0
|
||||
|
||||
avg_freq_ok = self.min_freq[s] <= avg_freq <= self.max_freq[s]
|
||||
recent_freq_ok = self.min_freq[s] <= avg_freq_recent <= self.max_freq[s]
|
||||
self.freq_ok[s] = avg_freq_ok or recent_freq_ok
|
||||
else:
|
||||
self.freq_ok[s] = True
|
||||
if self.simulation:
|
||||
self.alive[s] = self.seen[s] # alive is defined as seen when simulation flag set
|
||||
else:
|
||||
self.alive[s] = True
|
||||
|
||||
def all_alive(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.alive[s] for s in service_list if s not in self.ignore_alive)
|
||||
|
||||
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.freq_ok[s] for s in service_list if self._check_avg_freq(s))
|
||||
|
||||
def all_valid(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
if service_list is None:
|
||||
service_list = list(self.sock.keys())
|
||||
return all(self.valid[s] for s in service_list if s not in self.ignore_valid)
|
||||
|
||||
def all_checks(self, service_list: Optional[List[str]] = None) -> bool:
|
||||
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
|
||||
|
||||
|
||||
class PubMaster:
|
||||
def __init__(self, services: List[str]):
|
||||
self.sock = {}
|
||||
for s in services:
|
||||
self.sock[s] = pub_sock(s)
|
||||
|
||||
def send(self, s: str, dat: Union[bytes, capnp.lib.capnp._DynamicStructBuilder]) -> None:
|
||||
if not isinstance(dat, bytes):
|
||||
dat = dat.to_bytes()
|
||||
self.sock[s].send(dat)
|
||||
|
||||
def wait_for_readers_to_update(self, s: str, timeout: int, dt: float = 0.05) -> bool:
|
||||
for _ in range(int(timeout*(1./dt))):
|
||||
if self.sock[s].all_readers_updated():
|
||||
return True
|
||||
time.sleep(dt)
|
||||
return False
|
||||
|
||||
def all_readers_updated(self, s: str) -> bool:
|
||||
return self.sock[s].all_readers_updated() # type: ignore
|
||||
92
cereal/messaging/bridge.cc
Normal file
92
cereal/messaging/bridge.cc
Normal file
@@ -0,0 +1,92 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <csignal>
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
typedef void (*sighandler_t)(int sig);
|
||||
|
||||
#include "cereal/services.h"
|
||||
#include "msgq/impl_msgq.h"
|
||||
#include "msgq/impl_zmq.h"
|
||||
|
||||
std::atomic<bool> do_exit = false;
|
||||
static void set_do_exit(int sig) {
|
||||
do_exit = true;
|
||||
}
|
||||
|
||||
void sigpipe_handler(int sig) {
|
||||
assert(sig == SIGPIPE);
|
||||
std::cout << "SIGPIPE received" << std::endl;
|
||||
}
|
||||
|
||||
static std::vector<std::string> get_services(std::string whitelist_str, bool zmq_to_msgq) {
|
||||
std::vector<std::string> service_list;
|
||||
for (const auto& it : services) {
|
||||
std::string name = it.second.name;
|
||||
bool in_whitelist = whitelist_str.find(name) != std::string::npos;
|
||||
if (name == "plusFrame" || name == "uiLayoutState" || (zmq_to_msgq && !in_whitelist)) {
|
||||
continue;
|
||||
}
|
||||
service_list.push_back(name);
|
||||
}
|
||||
return service_list;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
signal(SIGPIPE, (sighandler_t)sigpipe_handler);
|
||||
signal(SIGINT, (sighandler_t)set_do_exit);
|
||||
signal(SIGTERM, (sighandler_t)set_do_exit);
|
||||
|
||||
bool zmq_to_msgq = argc > 2;
|
||||
std::string ip = zmq_to_msgq ? argv[1] : "127.0.0.1";
|
||||
std::string whitelist_str = zmq_to_msgq ? std::string(argv[2]) : "";
|
||||
|
||||
Poller *poller;
|
||||
Context *pub_context;
|
||||
Context *sub_context;
|
||||
if (zmq_to_msgq) { // republishes zmq debugging messages as msgq
|
||||
poller = new ZMQPoller();
|
||||
pub_context = new MSGQContext();
|
||||
sub_context = new ZMQContext();
|
||||
} else {
|
||||
poller = new MSGQPoller();
|
||||
pub_context = new ZMQContext();
|
||||
sub_context = new MSGQContext();
|
||||
}
|
||||
|
||||
std::map<SubSocket*, PubSocket*> sub2pub;
|
||||
for (auto endpoint : get_services(whitelist_str, zmq_to_msgq)) {
|
||||
PubSocket * pub_sock;
|
||||
SubSocket * sub_sock;
|
||||
if (zmq_to_msgq) {
|
||||
pub_sock = new MSGQPubSocket();
|
||||
sub_sock = new ZMQSubSocket();
|
||||
} else {
|
||||
pub_sock = new ZMQPubSocket();
|
||||
sub_sock = new MSGQSubSocket();
|
||||
}
|
||||
pub_sock->connect(pub_context, endpoint);
|
||||
sub_sock->connect(sub_context, endpoint, ip, false);
|
||||
|
||||
poller->registerSocket(sub_sock);
|
||||
sub2pub[sub_sock] = pub_sock;
|
||||
}
|
||||
|
||||
while (!do_exit) {
|
||||
for (auto sub_sock : poller->poll(100)) {
|
||||
Message * msg = sub_sock->receive();
|
||||
if (msg == NULL) continue;
|
||||
int ret;
|
||||
do {
|
||||
ret = sub2pub[sub_sock]->sendMessage(msg);
|
||||
} while (ret == -1 && errno == EINTR && !do_exit);
|
||||
assert(ret >= 0 || do_exit);
|
||||
delete msg;
|
||||
|
||||
if (do_exit) break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
102
cereal/messaging/messaging.h
Normal file
102
cereal/messaging/messaging.h
Normal file
@@ -0,0 +1,102 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include <capnp/serialize.h>
|
||||
|
||||
#include "cereal/gen/cpp/log.capnp.h"
|
||||
#include "common/timing.h"
|
||||
#include "msgq/ipc.h"
|
||||
|
||||
class SubMaster {
|
||||
public:
|
||||
SubMaster(const std::vector<const char *> &service_list, const std::vector<const char *> &poll = {},
|
||||
const char *address = nullptr, const std::vector<const char *> &ignore_alive = {});
|
||||
void update(int timeout = 1000);
|
||||
void update_msgs(uint64_t current_time, const std::vector<std::pair<std::string, cereal::Event::Reader>> &messages);
|
||||
inline bool allAlive(const std::vector<const char *> &service_list = {}) { return all_(service_list, false, true); }
|
||||
inline bool allValid(const std::vector<const char *> &service_list = {}) { return all_(service_list, true, false); }
|
||||
inline bool allAliveAndValid(const std::vector<const char *> &service_list = {}) { return all_(service_list, true, true); }
|
||||
void drain();
|
||||
~SubMaster();
|
||||
|
||||
uint64_t frame = 0;
|
||||
bool updated(const char *name) const;
|
||||
bool alive(const char *name) const;
|
||||
bool valid(const char *name) const;
|
||||
uint64_t rcv_frame(const char *name) const;
|
||||
uint64_t rcv_time(const char *name) const;
|
||||
cereal::Event::Reader &operator[](const char *name) const;
|
||||
|
||||
private:
|
||||
bool all_(const std::vector<const char *> &service_list, bool valid, bool alive);
|
||||
Poller *poller_ = nullptr;
|
||||
struct SubMessage;
|
||||
std::map<SubSocket *, SubMessage *> messages_;
|
||||
std::map<std::string, SubMessage *> services_;
|
||||
};
|
||||
|
||||
class MessageBuilder : public capnp::MallocMessageBuilder {
|
||||
public:
|
||||
MessageBuilder() = default;
|
||||
|
||||
cereal::Event::Builder initEvent(bool valid = true) {
|
||||
cereal::Event::Builder event = initRoot<cereal::Event>();
|
||||
event.setLogMonoTime(nanos_since_boot());
|
||||
event.setValid(valid);
|
||||
return event;
|
||||
}
|
||||
|
||||
kj::ArrayPtr<capnp::byte> toBytes() {
|
||||
heapArray_ = capnp::messageToFlatArray(*this);
|
||||
return heapArray_.asBytes();
|
||||
}
|
||||
|
||||
size_t getSerializedSize() {
|
||||
return capnp::computeSerializedSizeInWords(*this) * sizeof(capnp::word);
|
||||
}
|
||||
|
||||
int serializeToBuffer(unsigned char *buffer, size_t buffer_size) {
|
||||
size_t serialized_size = getSerializedSize();
|
||||
if (serialized_size > buffer_size) { return -1; }
|
||||
kj::ArrayOutputStream out(kj::ArrayPtr<capnp::byte>(buffer, buffer_size));
|
||||
capnp::writeMessage(out, *this);
|
||||
return serialized_size;
|
||||
}
|
||||
|
||||
private:
|
||||
kj::Array<capnp::word> heapArray_;
|
||||
};
|
||||
|
||||
class PubMaster {
|
||||
public:
|
||||
PubMaster(const std::vector<const char *> &service_list);
|
||||
inline int send(const char *name, capnp::byte *data, size_t size) { return sockets_.at(name)->send((char *)data, size); }
|
||||
int send(const char *name, MessageBuilder &msg);
|
||||
~PubMaster();
|
||||
|
||||
private:
|
||||
std::map<std::string, PubSocket *> sockets_;
|
||||
};
|
||||
|
||||
class AlignedBuffer {
|
||||
public:
|
||||
kj::ArrayPtr<const capnp::word> align(const char *data, const size_t size) {
|
||||
words_size = size / sizeof(capnp::word) + 1;
|
||||
if (aligned_buf.size() < words_size) {
|
||||
aligned_buf = kj::heapArray<capnp::word>(words_size < 512 ? 512 : words_size);
|
||||
}
|
||||
memcpy(aligned_buf.begin(), data, size);
|
||||
return aligned_buf.slice(0, words_size);
|
||||
}
|
||||
inline kj::ArrayPtr<const capnp::word> align(Message *m) {
|
||||
return align(m->getData(), m->getSize());
|
||||
}
|
||||
private:
|
||||
kj::Array<capnp::word> aligned_buf;
|
||||
size_t words_size;
|
||||
};
|
||||
203
cereal/messaging/socketmaster.cc
Normal file
203
cereal/messaging/socketmaster.cc
Normal file
@@ -0,0 +1,203 @@
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include <string>
|
||||
#include <mutex>
|
||||
|
||||
#include "cereal/services.h"
|
||||
#include "cereal/messaging/messaging.h"
|
||||
|
||||
const bool SIMULATION = (getenv("SIMULATION") != nullptr) && (std::string(getenv("SIMULATION")) == "1");
|
||||
|
||||
static inline bool inList(const std::vector<const char *> &list, const char *value) {
|
||||
for (auto &v : list) {
|
||||
if (strcmp(value, v) == 0) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class MessageContext {
|
||||
public:
|
||||
MessageContext() : ctx_(nullptr) {}
|
||||
~MessageContext() { delete ctx_; }
|
||||
inline Context *context() {
|
||||
std::call_once(init_flag, [=]() { ctx_ = Context::create(); });
|
||||
return ctx_;
|
||||
}
|
||||
private:
|
||||
Context *ctx_;
|
||||
std::once_flag init_flag;
|
||||
};
|
||||
|
||||
MessageContext message_context;
|
||||
|
||||
struct SubMaster::SubMessage {
|
||||
std::string name;
|
||||
SubSocket *socket = nullptr;
|
||||
int freq = 0;
|
||||
bool updated = false, alive = false, valid = true, ignore_alive;
|
||||
uint64_t rcv_time = 0, rcv_frame = 0;
|
||||
void *allocated_msg_reader = nullptr;
|
||||
bool is_polled = false;
|
||||
capnp::FlatArrayMessageReader *msg_reader = nullptr;
|
||||
AlignedBuffer aligned_buf;
|
||||
cereal::Event::Reader event;
|
||||
};
|
||||
|
||||
SubMaster::SubMaster(const std::vector<const char *> &service_list, const std::vector<const char *> &poll,
|
||||
const char *address, const std::vector<const char *> &ignore_alive) {
|
||||
poller_ = Poller::create();
|
||||
for (auto name : service_list) {
|
||||
assert(services.count(std::string(name)) > 0);
|
||||
|
||||
service serv = services.at(std::string(name));
|
||||
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true);
|
||||
assert(socket != 0);
|
||||
bool is_polled = inList(poll, name) || poll.empty();
|
||||
if (is_polled) poller_->registerSocket(socket);
|
||||
SubMessage *m = new SubMessage{
|
||||
.name = name,
|
||||
.socket = socket,
|
||||
.freq = serv.frequency,
|
||||
.ignore_alive = inList(ignore_alive, name),
|
||||
.allocated_msg_reader = malloc(sizeof(capnp::FlatArrayMessageReader)),
|
||||
.is_polled = is_polled};
|
||||
m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader({});
|
||||
messages_[socket] = m;
|
||||
services_[name] = m;
|
||||
}
|
||||
}
|
||||
|
||||
void SubMaster::update(int timeout) {
|
||||
for (auto &kv : messages_) kv.second->updated = false;
|
||||
|
||||
auto sockets = poller_->poll(timeout);
|
||||
|
||||
// add non-polled sockets for non-blocking receive
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
SubSocket *s = kv.first;
|
||||
if (!m->is_polled) sockets.push_back(s);
|
||||
}
|
||||
|
||||
uint64_t current_time = nanos_since_boot();
|
||||
|
||||
std::vector<std::pair<std::string, cereal::Event::Reader>> messages;
|
||||
|
||||
for (auto s : sockets) {
|
||||
Message *msg = s->receive(true);
|
||||
if (msg == nullptr) continue;
|
||||
|
||||
SubMessage *m = messages_.at(s);
|
||||
|
||||
m->msg_reader->~FlatArrayMessageReader();
|
||||
capnp::ReaderOptions options;
|
||||
options.traversalLimitInWords = kj::maxValue; // Don't limit
|
||||
m->msg_reader = new (m->allocated_msg_reader) capnp::FlatArrayMessageReader(m->aligned_buf.align(msg), options);
|
||||
delete msg;
|
||||
messages.push_back({m->name, m->msg_reader->getRoot<cereal::Event>()});
|
||||
}
|
||||
|
||||
update_msgs(current_time, messages);
|
||||
}
|
||||
|
||||
void SubMaster::update_msgs(uint64_t current_time, const std::vector<std::pair<std::string, cereal::Event::Reader>> &messages){
|
||||
if (++frame == UINT64_MAX) frame = 1;
|
||||
|
||||
for (auto &kv : messages) {
|
||||
auto m_find = services_.find(kv.first);
|
||||
if (m_find == services_.end()){
|
||||
continue;
|
||||
}
|
||||
SubMessage *m = m_find->second;
|
||||
m->event = kv.second;
|
||||
m->updated = true;
|
||||
m->rcv_time = current_time;
|
||||
m->rcv_frame = frame;
|
||||
m->valid = m->event.getValid();
|
||||
if (SIMULATION) m->alive = true;
|
||||
}
|
||||
|
||||
if (!SIMULATION) {
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
m->alive = (m->freq <= (1e-5) || ((current_time - m->rcv_time) * (1e-9)) < (10.0 / m->freq));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SubMaster::all_(const std::vector<const char *> &service_list, bool valid, bool alive) {
|
||||
int found = 0;
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
if (service_list.size() == 0 || inList(service_list, m->name.c_str())) {
|
||||
found += (!valid || m->valid) && (!alive || (m->alive || m->ignore_alive));
|
||||
}
|
||||
}
|
||||
return service_list.size() == 0 ? found == messages_.size() : found == service_list.size();
|
||||
}
|
||||
|
||||
void SubMaster::drain() {
|
||||
while (true) {
|
||||
auto polls = poller_->poll(0);
|
||||
if (polls.size() == 0)
|
||||
break;
|
||||
|
||||
for (auto sock : polls) {
|
||||
Message *msg = sock->receive(true);
|
||||
delete msg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SubMaster::updated(const char *name) const {
|
||||
return services_.at(name)->updated;
|
||||
}
|
||||
|
||||
bool SubMaster::alive(const char *name) const {
|
||||
return services_.at(name)->alive;
|
||||
}
|
||||
|
||||
bool SubMaster::valid(const char *name) const {
|
||||
return services_.at(name)->valid;
|
||||
}
|
||||
|
||||
uint64_t SubMaster::rcv_frame(const char *name) const {
|
||||
return services_.at(name)->rcv_frame;
|
||||
}
|
||||
|
||||
uint64_t SubMaster::rcv_time(const char *name) const {
|
||||
return services_.at(name)->rcv_time;
|
||||
}
|
||||
|
||||
cereal::Event::Reader &SubMaster::operator[](const char *name) const {
|
||||
return services_.at(name)->event;
|
||||
}
|
||||
|
||||
SubMaster::~SubMaster() {
|
||||
delete poller_;
|
||||
for (auto &kv : messages_) {
|
||||
SubMessage *m = kv.second;
|
||||
m->msg_reader->~FlatArrayMessageReader();
|
||||
free(m->allocated_msg_reader);
|
||||
delete m->socket;
|
||||
delete m;
|
||||
}
|
||||
}
|
||||
|
||||
PubMaster::PubMaster(const std::vector<const char *> &service_list) {
|
||||
for (auto name : service_list) {
|
||||
assert(services.count(name) > 0);
|
||||
PubSocket *socket = PubSocket::create(message_context.context(), name);
|
||||
assert(socket);
|
||||
sockets_[name] = socket;
|
||||
}
|
||||
}
|
||||
|
||||
int PubMaster::send(const char *name, MessageBuilder &msg) {
|
||||
auto bytes = msg.toBytes();
|
||||
return send(name, bytes.begin(), bytes.size());
|
||||
}
|
||||
|
||||
PubMaster::~PubMaster() {
|
||||
for (auto s : sockets_) delete s.second;
|
||||
}
|
||||
195
cereal/messaging/tests/test_messaging.py
Executable file
195
cereal/messaging/tests/test_messaging.py
Executable file
@@ -0,0 +1,195 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import capnp
|
||||
import multiprocessing
|
||||
import numbers
|
||||
import random
|
||||
import threading
|
||||
import time
|
||||
import unittest
|
||||
from parameterized import parameterized
|
||||
|
||||
from cereal import log, car
|
||||
import cereal.messaging as messaging
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
events = [evt for evt in log.Event.schema.union_fields if evt in SERVICE_LIST.keys()]
|
||||
|
||||
def random_sock():
|
||||
return random.choice(events)
|
||||
|
||||
def random_socks(num_socks=10):
|
||||
return list({random_sock() for _ in range(num_socks)})
|
||||
|
||||
def random_bytes(length=1000):
|
||||
return bytes([random.randrange(0xFF) for _ in range(length)])
|
||||
|
||||
def zmq_sleep(t=1):
|
||||
if "ZMQ" in os.environ:
|
||||
time.sleep(t)
|
||||
|
||||
def zmq_expected_failure(func):
|
||||
if "ZMQ" in os.environ:
|
||||
return unittest.expectedFailure(func)
|
||||
else:
|
||||
return func
|
||||
|
||||
|
||||
# TODO: this should take any capnp struct and returrn a msg with random populated data
|
||||
def random_carstate():
|
||||
fields = ["vEgo", "aEgo", "gas", "steeringAngleDeg"]
|
||||
msg = messaging.new_message("carState")
|
||||
cs = msg.carState
|
||||
for f in fields:
|
||||
setattr(cs, f, random.random() * 10)
|
||||
return msg
|
||||
|
||||
# TODO: this should compare any capnp structs
|
||||
def assert_carstate(cs1, cs2):
|
||||
for f in car.CarState.schema.non_union_fields:
|
||||
# TODO: check all types
|
||||
val1, val2 = getattr(cs1, f), getattr(cs2, f)
|
||||
if isinstance(val1, numbers.Number):
|
||||
assert val1 == val2, f"{f}: sent '{val1}' vs recvd '{val2}'"
|
||||
|
||||
def delayed_send(delay, sock, dat):
|
||||
def send_func():
|
||||
sock.send(dat)
|
||||
threading.Timer(delay, send_func).start()
|
||||
|
||||
|
||||
class TestMessaging(unittest.TestCase):
|
||||
def setUp(self):
|
||||
# TODO: ZMQ tests are too slow; all sleeps will need to be
|
||||
# replaced with logic to block on the necessary condition
|
||||
if "ZMQ" in os.environ:
|
||||
raise unittest.SkipTest
|
||||
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep()
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_new_message(self, evt):
|
||||
try:
|
||||
msg = messaging.new_message(evt)
|
||||
except capnp.lib.capnp.KjException:
|
||||
msg = messaging.new_message(evt, random.randrange(200))
|
||||
self.assertLess(time.monotonic() - msg.logMonoTime, 0.1)
|
||||
self.assertFalse(msg.valid)
|
||||
self.assertEqual(evt, msg.which())
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_pub_sock(self, evt):
|
||||
messaging.pub_sock(evt)
|
||||
|
||||
@parameterized.expand(events)
|
||||
def test_sub_sock(self, evt):
|
||||
messaging.sub_sock(evt)
|
||||
|
||||
@parameterized.expand([
|
||||
(messaging.drain_sock, capnp._DynamicStructReader),
|
||||
(messaging.drain_sock_raw, bytes),
|
||||
])
|
||||
def test_drain_sock(self, func, expected_type):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=1000)
|
||||
zmq_sleep()
|
||||
|
||||
# no wait and no msgs in queue
|
||||
msgs = func(sub_sock)
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertEqual(len(msgs), 0)
|
||||
|
||||
# no wait but msgs are queued up
|
||||
num_msgs = random.randrange(3, 10)
|
||||
for _ in range(num_msgs):
|
||||
pub_sock.send(messaging.new_message(sock).to_bytes())
|
||||
time.sleep(0.1)
|
||||
msgs = func(sub_sock)
|
||||
self.assertIsInstance(msgs, list)
|
||||
self.assertTrue(all(isinstance(msg, expected_type) for msg in msgs))
|
||||
self.assertEqual(len(msgs), num_msgs)
|
||||
|
||||
def test_recv_sock(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=100)
|
||||
zmq_sleep()
|
||||
|
||||
# no wait and no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# no wait and one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
recvd = messaging.recv_sock(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
# https://github.com/python/mypy/issues/13038
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
def test_recv_one(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=1000)
|
||||
zmq_sleep()
|
||||
|
||||
# no msg in queue, socket should timeout
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
@zmq_expected_failure
|
||||
def test_recv_one_or_none(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock)
|
||||
zmq_sleep()
|
||||
|
||||
# no msg in queue, socket shouldn't block
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
self.assertTrue(recvd is None)
|
||||
|
||||
# one msg in queue
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
recvd = messaging.recv_one_or_none(sub_sock)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
def test_recv_one_retry(self):
|
||||
sock = "carState"
|
||||
sock_timeout = 0.1
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000))
|
||||
zmq_sleep()
|
||||
|
||||
# this test doesn't work with ZMQ since multiprocessing interrupts it
|
||||
if "ZMQ" not in os.environ:
|
||||
# wait 15 socket timeouts and make sure it's still retrying
|
||||
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
|
||||
p.start()
|
||||
time.sleep(sock_timeout*15)
|
||||
self.assertTrue(p.is_alive())
|
||||
p.terminate()
|
||||
|
||||
# wait 15 socket timeouts before sending
|
||||
msg = random_carstate()
|
||||
delayed_send(sock_timeout*15, pub_sock, msg.to_bytes())
|
||||
start_time = time.monotonic()
|
||||
recvd = messaging.recv_one_retry(sub_sock)
|
||||
self.assertGreaterEqual(time.monotonic() - start_time, sock_timeout*15)
|
||||
self.assertIsInstance(recvd, capnp._DynamicStructReader)
|
||||
assert_carstate(msg.carState, recvd.carState)
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
163
cereal/messaging/tests/test_pub_sub_master.py
Executable file
163
cereal/messaging/tests/test_pub_sub_master.py
Executable file
@@ -0,0 +1,163 @@
|
||||
#!/usr/bin/env python3
|
||||
import random
|
||||
import time
|
||||
from typing import Sized, cast
|
||||
import unittest
|
||||
|
||||
import cereal.messaging as messaging
|
||||
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
|
||||
random_bytes, random_carstate, assert_carstate, \
|
||||
zmq_sleep
|
||||
|
||||
|
||||
class TestSubMaster(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
|
||||
def test_init(self):
|
||||
sm = messaging.SubMaster(events)
|
||||
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
|
||||
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
|
||||
self.assertEqual(len(cast(Sized, p)), len(events))
|
||||
|
||||
def test_init_state(self):
|
||||
socks = random_socks()
|
||||
sm = messaging.SubMaster(socks)
|
||||
self.assertEqual(sm.frame, -1)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
self.assertFalse(any(sm.alive.values()))
|
||||
self.assertTrue(all(t == 0. for t in sm.recv_time.values()))
|
||||
self.assertTrue(all(f == 0 for f in sm.recv_frame.values()))
|
||||
self.assertTrue(all(t == 0 for t in sm.logMonoTime.values()))
|
||||
|
||||
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
|
||||
sm.sock, sm.data, sm.logMonoTime, sm.valid]:
|
||||
self.assertEqual(len(cast(Sized, p)), len(socks))
|
||||
|
||||
def test_getitem(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
zmq_sleep()
|
||||
|
||||
msg = random_carstate()
|
||||
pub_sock.send(msg.to_bytes())
|
||||
sm.update(1000)
|
||||
assert_carstate(msg.carState, sm[sock])
|
||||
|
||||
# TODO: break this test up to individually test SubMaster.update and SubMaster.update_msgs
|
||||
def test_update(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
zmq_sleep()
|
||||
|
||||
for i in range(10):
|
||||
msg = messaging.new_message(sock)
|
||||
pub_sock.send(msg.to_bytes())
|
||||
sm.update(1000)
|
||||
self.assertEqual(sm.frame, i)
|
||||
self.assertTrue(all(sm.updated.values()))
|
||||
|
||||
def test_update_timeout(self):
|
||||
sock = random_sock()
|
||||
sm = messaging.SubMaster([sock,])
|
||||
for _ in range(5):
|
||||
timeout = random.randrange(1000, 5000)
|
||||
start_time = time.monotonic()
|
||||
sm.update(timeout)
|
||||
t = time.monotonic() - start_time
|
||||
self.assertGreaterEqual(t, timeout/1000.)
|
||||
self.assertLess(t, 5)
|
||||
self.assertFalse(any(sm.updated.values()))
|
||||
|
||||
def test_avg_frequency_checks(self):
|
||||
for poll in (True, False):
|
||||
sm = messaging.SubMaster(["modelV2", "carParams", "carState", "cameraOdometry", "liveCalibration"],
|
||||
poll=("modelV2" if poll else None),
|
||||
frequency=(20. if not poll else None))
|
||||
|
||||
checks = {
|
||||
"carState": (20, 20),
|
||||
"modelV2": (20, 20 if poll else 10),
|
||||
"cameraOdometry": (20, 10),
|
||||
"liveCalibration": (4, 4),
|
||||
"carParams": (None, None),
|
||||
}
|
||||
|
||||
for service, (max_freq, min_freq) in checks.items():
|
||||
if max_freq is not None:
|
||||
assert sm._check_avg_freq(service)
|
||||
assert sm.max_freq[service] == max_freq*1.2
|
||||
assert sm.min_freq[service] == min_freq*0.8
|
||||
else:
|
||||
assert not sm._check_avg_freq(service)
|
||||
|
||||
def test_alive(self):
|
||||
pass
|
||||
|
||||
def test_ignore_alive(self):
|
||||
pass
|
||||
|
||||
def test_valid(self):
|
||||
pass
|
||||
|
||||
# SubMaster should always conflate
|
||||
def test_conflate(self):
|
||||
sock = "carState"
|
||||
pub_sock = messaging.pub_sock(sock)
|
||||
sm = messaging.SubMaster([sock,])
|
||||
|
||||
n = 10
|
||||
for i in range(n+1):
|
||||
msg = messaging.new_message(sock)
|
||||
msg.carState.vEgo = i
|
||||
pub_sock.send(msg.to_bytes())
|
||||
time.sleep(0.01)
|
||||
sm.update(1000)
|
||||
self.assertEqual(sm[sock].vEgo, n)
|
||||
|
||||
|
||||
class TestPubMaster(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
# ZMQ pub socket takes too long to die
|
||||
# sleep to prevent multiple publishers error between tests
|
||||
zmq_sleep(3)
|
||||
|
||||
def test_init(self):
|
||||
messaging.PubMaster(events)
|
||||
|
||||
def test_send(self):
|
||||
socks = random_socks()
|
||||
pm = messaging.PubMaster(socks)
|
||||
sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks}
|
||||
zmq_sleep()
|
||||
|
||||
# PubMaster accepts either a capnp msg builder or bytes
|
||||
for capnp in [True, False]:
|
||||
for i in range(100):
|
||||
sock = socks[i % len(socks)]
|
||||
|
||||
if capnp:
|
||||
try:
|
||||
msg = messaging.new_message(sock)
|
||||
except Exception:
|
||||
msg = messaging.new_message(sock, random.randrange(50))
|
||||
else:
|
||||
msg = random_bytes()
|
||||
|
||||
pm.send(sock, msg)
|
||||
recvd = sub_socks[sock].receive()
|
||||
|
||||
if capnp:
|
||||
msg.clear_write_flag()
|
||||
msg = msg.to_bytes()
|
||||
self.assertEqual(msg, recvd, i)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
26
cereal/messaging/tests/test_services.py
Executable file
26
cereal/messaging/tests/test_services.py
Executable file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import tempfile
|
||||
from typing import Dict
|
||||
import unittest
|
||||
from parameterized import parameterized
|
||||
|
||||
import cereal.services as services
|
||||
from cereal.services import SERVICE_LIST
|
||||
|
||||
|
||||
class TestServices(unittest.TestCase):
|
||||
|
||||
@parameterized.expand(SERVICE_LIST.keys())
|
||||
def test_services(self, s):
|
||||
service = SERVICE_LIST[s]
|
||||
self.assertTrue(service.frequency <= 104)
|
||||
self.assertTrue(service.decimation != 0)
|
||||
|
||||
def test_generated_header(self):
|
||||
with tempfile.NamedTemporaryFile(suffix=".h") as f:
|
||||
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name}")
|
||||
self.assertEqual(ret, 0, "generated services header is not valid C")
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
130
cereal/services.py
Executable file
130
cereal/services.py
Executable file
@@ -0,0 +1,130 @@
|
||||
#!/usr/bin/env python3
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class Service:
|
||||
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None):
|
||||
self.should_log = should_log
|
||||
self.frequency = frequency
|
||||
self.decimation = decimation
|
||||
|
||||
|
||||
_services: dict[str, tuple] = {
|
||||
# service: (should_log, frequency, qlog decimation (optional))
|
||||
# note: the "EncodeIdx" packets will still be in the log
|
||||
"gyroscope": (True, 104., 104),
|
||||
"gyroscope2": (True, 100., 100),
|
||||
"accelerometer": (True, 104., 104),
|
||||
"accelerometer2": (True, 100., 100),
|
||||
"magnetometer": (True, 25., 25),
|
||||
"lightSensor": (True, 100., 100),
|
||||
"temperatureSensor": (True, 2., 200),
|
||||
"temperatureSensor2": (True, 2., 200),
|
||||
"gpsNMEA": (True, 9.),
|
||||
"deviceState": (True, 2., 1),
|
||||
"can": (True, 100., 1223), # decimation gives ~5 msgs in a full segment
|
||||
"controlsState": (True, 100., 10),
|
||||
"pandaStates": (True, 10., 1),
|
||||
"peripheralState": (True, 2., 1),
|
||||
"radarState": (True, 20., 5),
|
||||
"roadEncodeIdx": (False, 20., 1),
|
||||
"liveTracks": (True, 20.),
|
||||
"sendcan": (True, 100., 139),
|
||||
"logMessage": (True, 0.),
|
||||
"errorLogMessage": (True, 0., 1),
|
||||
"liveCalibration": (True, 4., 4),
|
||||
"liveTorqueParameters": (True, 4., 1),
|
||||
"androidLog": (True, 0.),
|
||||
"carState": (True, 100., 10),
|
||||
"carControl": (True, 100., 10),
|
||||
"carOutput": (True, 100., 10),
|
||||
"longitudinalPlan": (True, 20., 5),
|
||||
"procLog": (True, 0.5, 15),
|
||||
"gpsLocationExternal": (True, 10., 10),
|
||||
"gpsLocation": (True, 1., 1),
|
||||
"ubloxGnss": (True, 10.),
|
||||
"qcomGnss": (True, 2.),
|
||||
"gnssMeasurements": (True, 10., 10),
|
||||
"clocks": (True, 0.1, 1),
|
||||
"ubloxRaw": (True, 20.),
|
||||
"liveLocationKalman": (True, 20., 5),
|
||||
"liveParameters": (True, 20., 5),
|
||||
"cameraOdometry": (True, 20., 5),
|
||||
"lateralPlanDEPRECATED": (True, 20., 5),
|
||||
"thumbnail": (True, 0.2, 1),
|
||||
"onroadEvents": (True, 1., 1),
|
||||
"carParams": (True, 0.02, 1),
|
||||
"roadCameraState": (True, 20., 20),
|
||||
"driverCameraState": (True, 20., 20),
|
||||
"driverEncodeIdx": (False, 20., 1),
|
||||
"driverStateV2": (True, 20., 10),
|
||||
"driverMonitoringState": (True, 20., 10),
|
||||
"wideRoadEncodeIdx": (False, 20., 1),
|
||||
"wideRoadCameraState": (True, 20., 20),
|
||||
"drivingModelData": (True, 20., 10),
|
||||
"modelV2": (True, 20.),
|
||||
"managerState": (True, 2., 1),
|
||||
"uploaderState": (True, 0., 1),
|
||||
"navInstruction": (True, 1., 10),
|
||||
"navRoute": (True, 0.),
|
||||
"navThumbnail": (True, 0.),
|
||||
"navModelDEPRECATED": (True, 2., 4.),
|
||||
"mapRenderState": (True, 2., 1.),
|
||||
"uiPlanDEPRECATED": (True, 20., 40.),
|
||||
"qRoadEncodeIdx": (False, 20.),
|
||||
"userFlag": (True, 0., 1),
|
||||
"microphone": (True, 10., 10),
|
||||
|
||||
"controlsStateSP": (True, 100., 10),
|
||||
"longitudinalPlanSP": (True, 20., 5),
|
||||
"lateralPlanSPDEPRECATED": (True, 20., 5),
|
||||
"driverMonitoringStateSP": (True, 20., 10),
|
||||
"liveMapDataSP": (True, 0.),
|
||||
"e2eLongStateSP": (True, 0.),
|
||||
"modelV2SP": (True, 20., 40),
|
||||
|
||||
# debug
|
||||
"uiDebug": (True, 0., 1),
|
||||
"testJoystick": (True, 0.),
|
||||
"roadEncodeData": (False, 20.),
|
||||
"driverEncodeData": (False, 20.),
|
||||
"wideRoadEncodeData": (False, 20.),
|
||||
"qRoadEncodeData": (False, 20.),
|
||||
"livestreamWideRoadEncodeIdx": (False, 20.),
|
||||
"livestreamRoadEncodeIdx": (False, 20.),
|
||||
"livestreamDriverEncodeIdx": (False, 20.),
|
||||
"livestreamWideRoadEncodeData": (False, 20.),
|
||||
"livestreamRoadEncodeData": (False, 20.),
|
||||
"livestreamDriverEncodeData": (False, 20.),
|
||||
"customReservedRawData0": (True, 0.),
|
||||
"customReservedRawData1": (True, 0.),
|
||||
"customReservedRawData2": (True, 0.),
|
||||
}
|
||||
SERVICE_LIST = {name: Service(*vals) for
|
||||
idx, (name, vals) in enumerate(_services.items())}
|
||||
|
||||
|
||||
def build_header():
|
||||
h = ""
|
||||
h += "/* THIS IS AN AUTOGENERATED FILE, PLEASE EDIT services.py */\n"
|
||||
h += "#ifndef __SERVICES_H\n"
|
||||
h += "#define __SERVICES_H\n"
|
||||
|
||||
h += "#include <map>\n"
|
||||
h += "#include <string>\n"
|
||||
|
||||
h += "struct service { std::string name; bool should_log; int frequency; int decimation; };\n"
|
||||
h += "static std::map<std::string, service> services = {\n"
|
||||
for k, v in SERVICE_LIST.items():
|
||||
should_log = "true" if v.should_log else "false"
|
||||
decimation = -1 if v.decimation is None else v.decimation
|
||||
h += ' { "%s", {"%s", %s, %d, %d}},\n' % \
|
||||
(k, k, should_log, v.frequency, decimation)
|
||||
h += "};\n"
|
||||
|
||||
h += "#endif\n"
|
||||
return h
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
print(build_header())
|
||||
@@ -1,13 +1,13 @@
|
||||
import jwt
|
||||
import os
|
||||
import requests
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timedelta, UTC
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.version import get_version
|
||||
|
||||
API_HOST = os.getenv('API_HOST', 'https://api.commadotai.com')
|
||||
|
||||
class Api():
|
||||
class Api:
|
||||
def __init__(self, dongle_id):
|
||||
self.dongle_id = dongle_id
|
||||
with open(Paths.persist_root()+'/comma/id_rsa') as f:
|
||||
@@ -23,7 +23,7 @@ class Api():
|
||||
return api_get(endpoint, method=method, timeout=timeout, access_token=access_token, **params)
|
||||
|
||||
def get_token(self, expiry_hours=1):
|
||||
now = datetime.utcnow()
|
||||
now = datetime.now(UTC).replace(tzinfo=None)
|
||||
payload = {
|
||||
'identity': self.dongle_id,
|
||||
'nbf': now,
|
||||
|
||||
42
common/git.py
Normal file
42
common/git.py
Normal file
@@ -0,0 +1,42 @@
|
||||
from functools import cache
|
||||
import subprocess
|
||||
from openpilot.common.run import run_cmd, run_cmd_default
|
||||
|
||||
|
||||
@cache
|
||||
def get_commit(cwd: str = None, branch: str = "HEAD") -> str:
|
||||
return run_cmd_default(["git", "rev-parse", branch], cwd=cwd)
|
||||
|
||||
|
||||
@cache
|
||||
def get_commit_date(cwd: str = None, commit: str = "HEAD") -> str:
|
||||
return run_cmd_default(["git", "show", "--no-patch", "--format='%ct %ci'", commit], cwd=cwd)
|
||||
|
||||
|
||||
@cache
|
||||
def get_short_branch(cwd: str = None) -> str:
|
||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
|
||||
|
||||
|
||||
@cache
|
||||
def get_branch(cwd: str = None) -> str:
|
||||
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "--symbolic-full-name", "@{u}"], cwd=cwd)
|
||||
|
||||
|
||||
@cache
|
||||
def get_origin(cwd: str = None) -> str:
|
||||
try:
|
||||
local_branch = run_cmd(["git", "name-rev", "--name-only", "HEAD"], cwd=cwd)
|
||||
tracking_remote = run_cmd(["git", "config", "branch." + local_branch + ".remote"], cwd=cwd)
|
||||
return run_cmd(["git", "config", "remote." + tracking_remote + ".url"], cwd=cwd)
|
||||
except subprocess.CalledProcessError: # Not on a branch, fallback
|
||||
return run_cmd_default(["git", "config", "--get", "remote.origin.url"], cwd=cwd)
|
||||
|
||||
|
||||
@cache
|
||||
def get_normalized_origin(cwd: str = None) -> str:
|
||||
return get_origin(cwd) \
|
||||
.replace("git@", "", 1) \
|
||||
.replace(".git", "", 1) \
|
||||
.replace("https://", "", 1) \
|
||||
.replace(":", "/", 1)
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from functools import lru_cache
|
||||
from functools import cache
|
||||
|
||||
def gpio_init(pin: int, output: bool) -> None:
|
||||
try:
|
||||
@@ -35,7 +35,7 @@ def gpio_export(pin: int) -> None:
|
||||
except Exception:
|
||||
print(f"Failed to export gpio {pin}")
|
||||
|
||||
@lru_cache(maxsize=None)
|
||||
@cache
|
||||
def get_irq_action(irq: int) -> list[str]:
|
||||
try:
|
||||
with open(f"/sys/kernel/irq/{irq}/actions") as f:
|
||||
|
||||
45
common/markdown.py
Normal file
45
common/markdown.py
Normal file
@@ -0,0 +1,45 @@
|
||||
HTML_REPLACEMENTS = [
|
||||
(r'&', r'&'),
|
||||
(r'"', r'"'),
|
||||
]
|
||||
|
||||
def parse_markdown(text: str, tab_length: int = 2) -> str:
|
||||
lines = text.split("\n")
|
||||
output: list[str] = []
|
||||
list_level = 0
|
||||
|
||||
def end_outstanding_lists(level: int, end_level: int) -> int:
|
||||
while level > end_level:
|
||||
level -= 1
|
||||
output.append("</ul>")
|
||||
if level > 0:
|
||||
output.append("</li>")
|
||||
return end_level
|
||||
|
||||
for i, line in enumerate(lines):
|
||||
if i + 1 < len(lines) and lines[i + 1].startswith("==="): # heading
|
||||
output.append(f"<h1>{line}</h1>")
|
||||
elif line.startswith("==="):
|
||||
pass
|
||||
elif line.lstrip().startswith("* "): # list
|
||||
line_level = 1 + line.count(" " * tab_length, 0, line.index("*"))
|
||||
if list_level >= line_level:
|
||||
list_level = end_outstanding_lists(list_level, line_level)
|
||||
else:
|
||||
list_level += 1
|
||||
if list_level > 1:
|
||||
output[-1] = output[-1].replace("</li>", "")
|
||||
output.append("<ul>")
|
||||
output.append(f"<li>{line.replace('*', '', 1).lstrip()}</li>")
|
||||
else:
|
||||
list_level = end_outstanding_lists(list_level, 0)
|
||||
if len(line) > 0:
|
||||
output.append(line)
|
||||
|
||||
end_outstanding_lists(list_level, 0)
|
||||
output_str = "\n".join(output) + "\n"
|
||||
|
||||
for (fr, to) in HTML_REPLACEMENTS:
|
||||
output_str = output_str.replace(fr, to)
|
||||
|
||||
return output_str
|
||||
@@ -89,8 +89,8 @@ private:
|
||||
|
||||
std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"AccessToken", CLEAR_ON_MANAGER_START | DONT_LOG},
|
||||
{"AlwaysOnDM", PERSISTENT},
|
||||
{"ApiCache_Device", PERSISTENT},
|
||||
{"ApiCache_NavDestinations", PERSISTENT},
|
||||
{"AssistNowToken", PERSISTENT},
|
||||
{"AthenadPid", PERSISTENT},
|
||||
{"AthenadUploadQueue", PERSISTENT},
|
||||
@@ -159,11 +159,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"LiveParameters", PERSISTENT},
|
||||
{"LiveTorqueParameters", PERSISTENT | DONT_LOG},
|
||||
{"LongitudinalPersonality", PERSISTENT},
|
||||
{"NavDestination", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
||||
{"NavDestinationWaypoints", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
||||
{"NavPastDestinations", PERSISTENT},
|
||||
{"NavSettingLeftSide", PERSISTENT},
|
||||
{"NavSettingTime24h", PERSISTENT},
|
||||
{"NetworkMetered", PERSISTENT},
|
||||
{"ObdMultiplexingChanged", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
{"ObdMultiplexingEnabled", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
@@ -171,7 +166,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"Offroad_CarUnrecognized", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
{"Offroad_ConnectivityNeeded", CLEAR_ON_MANAGER_START},
|
||||
{"Offroad_ConnectivityNeededPrompt", CLEAR_ON_MANAGER_START},
|
||||
{"Offroad_InvalidTime", CLEAR_ON_MANAGER_START},
|
||||
{"Offroad_IsTakingSnapshot", CLEAR_ON_MANAGER_START},
|
||||
{"Offroad_NeosUpdate", CLEAR_ON_MANAGER_START},
|
||||
{"Offroad_NoFirmware", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
@@ -188,10 +182,10 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"RecordFront", PERSISTENT},
|
||||
{"RecordFrontLock", PERSISTENT}, // for the internal fleet
|
||||
{"ReplayControlsState", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
{"RouteCount", PERSISTENT},
|
||||
{"SnoozeUpdate", CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION},
|
||||
{"SshEnabled", PERSISTENT},
|
||||
{"TermsVersion", PERSISTENT},
|
||||
{"Timezone", PERSISTENT},
|
||||
{"TrainingVersion", PERSISTENT},
|
||||
{"UbloxAvailable", PERSISTENT},
|
||||
{"UpdateAvailable", CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION},
|
||||
@@ -206,7 +200,6 @@ std::unordered_map<std::string, uint32_t> keys = {
|
||||
{"UpdaterTargetBranch", CLEAR_ON_MANAGER_START},
|
||||
{"UpdaterLastFetchTime", PERSISTENT},
|
||||
{"Version", PERSISTENT},
|
||||
{"VisionRadarToggle", PERSISTENT},
|
||||
|
||||
{"AccMadsCombo", PERSISTENT},
|
||||
{"AmapKey1", PERSISTENT},
|
||||
@@ -367,7 +360,9 @@ int Params::put(const char* key, const char* value, size_t value_size) {
|
||||
} while (false);
|
||||
|
||||
close(tmp_fd);
|
||||
::unlink(tmp_path.c_str());
|
||||
if (result != 0) {
|
||||
::unlink(tmp_path.c_str());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
|
||||
#include "common/params.h"
|
||||
#include "common/util.h"
|
||||
#include "system/hardware/hw.h"
|
||||
|
||||
class OpenpilotPrefix {
|
||||
public:
|
||||
@@ -25,6 +26,10 @@ public:
|
||||
system(util::string_format("rm %s -rf", real_path.c_str()).c_str());
|
||||
unlink(param_path.c_str());
|
||||
}
|
||||
if (getenv("COMMA_CACHE") == nullptr) {
|
||||
system(util::string_format("rm %s -rf", Path::download_cache_root().c_str()).c_str());
|
||||
}
|
||||
system(util::string_format("rm %s -rf", Path::comma_home().c_str()).c_str());
|
||||
system(util::string_format("rm %s -rf", msgq_path.c_str()).c_str());
|
||||
unsetenv("OPENPILOT_PREFIX");
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ import uuid
|
||||
|
||||
|
||||
from openpilot.common.params import Params
|
||||
from openpilot.system.hardware import PC
|
||||
from openpilot.system.hardware.hw import Paths
|
||||
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
|
||||
|
||||
@@ -45,7 +46,8 @@ class OpenpilotPrefix:
|
||||
shutil.rmtree(os.path.realpath(symlink_path), ignore_errors=True)
|
||||
os.remove(symlink_path)
|
||||
shutil.rmtree(self.msgq_path, ignore_errors=True)
|
||||
shutil.rmtree(Paths.log_root(), ignore_errors=True)
|
||||
if PC:
|
||||
shutil.rmtree(Paths.log_root(), ignore_errors=True)
|
||||
if not os.environ.get("COMMA_CACHE", False):
|
||||
shutil.rmtree(Paths.download_cache_root(), ignore_errors=True)
|
||||
shutil.rmtree(Paths.comma_home(), ignore_errors=True)
|
||||
|
||||
@@ -9,7 +9,7 @@ public:
|
||||
~RateKeeper() {}
|
||||
bool keepTime();
|
||||
bool monitorTime();
|
||||
inline double frame() const { return frame_; }
|
||||
inline uint64_t frame() const { return frame_; }
|
||||
inline double remaining() const { return remaining_; }
|
||||
|
||||
private:
|
||||
|
||||
@@ -4,7 +4,7 @@ import os
|
||||
import time
|
||||
from collections import deque
|
||||
|
||||
from setproctitle import getproctitle
|
||||
from openpilot.common.threadname import getthreadname
|
||||
|
||||
from openpilot.system.hardware import PC
|
||||
|
||||
@@ -12,7 +12,7 @@ from openpilot.system.hardware import PC
|
||||
# time step for each process
|
||||
DT_CTRL = 0.01 # controlsd
|
||||
DT_MDL = 0.05 # model
|
||||
DT_TRML = 0.5 # thermald and manager
|
||||
DT_HW = 0.5 # hardwared and manager
|
||||
DT_DMON = 0.05 # driver monitoring
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ class Priority:
|
||||
CTRL_LOW = 51 # plannerd & radard
|
||||
|
||||
# CORE 3
|
||||
# - boardd = 55
|
||||
# - pandad = 55
|
||||
CTRL_HIGH = 53
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ class Ratekeeper:
|
||||
self._print_delay_threshold = print_delay_threshold
|
||||
self._frame = 0
|
||||
self._remaining = 0.0
|
||||
self._process_name = getproctitle()
|
||||
self._thread_name = getthreadname()
|
||||
self._dts = deque([self._interval], maxlen=100)
|
||||
self._last_monitor_time = time.monotonic()
|
||||
|
||||
@@ -87,7 +87,7 @@ class Ratekeeper:
|
||||
remaining = self._next_frame_time - time.monotonic()
|
||||
self._next_frame_time += self._interval
|
||||
if self._print_delay_threshold is not None and remaining < -self._print_delay_threshold:
|
||||
print(f"{self._process_name} lagging by {-remaining * 1000:.2f} ms")
|
||||
print(f"{self._thread_name} lagging by {-remaining * 1000:.2f} ms")
|
||||
lagged = True
|
||||
self._frame += 1
|
||||
self._remaining = remaining
|
||||
|
||||
13
common/run.py
Normal file
13
common/run.py
Normal file
@@ -0,0 +1,13 @@
|
||||
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,7 +3,7 @@ import subprocess
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
|
||||
|
||||
class Spinner():
|
||||
class Spinner:
|
||||
def __init__(self):
|
||||
try:
|
||||
self.spinner_proc = subprocess.Popen(["./spinner"],
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import numpy as np
|
||||
|
||||
class RunningStat():
|
||||
class RunningStat:
|
||||
# tracks realtime mean and standard deviation without storing any data
|
||||
def __init__(self, priors=None, max_trackable=-1):
|
||||
self.max_trackable = max_trackable
|
||||
@@ -51,7 +51,7 @@ class RunningStat():
|
||||
def params_to_save(self):
|
||||
return [self.M, self.S, self.n]
|
||||
|
||||
class RunningStatFilter():
|
||||
class RunningStatFilter:
|
||||
def __init__(self, raw_priors=None, filtered_priors=None, max_trackable=-1):
|
||||
self.raw_stat = RunningStat(raw_priors, -1)
|
||||
self.filtered_stat = RunningStat(filtered_priors, max_trackable)
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import os
|
||||
import unittest
|
||||
from uuid import uuid4
|
||||
|
||||
from openpilot.common.file_helpers import atomic_write_in_dir
|
||||
|
||||
|
||||
class TestFileHelpers(unittest.TestCase):
|
||||
class TestFileHelpers:
|
||||
def run_atomic_write_func(self, atomic_write_func):
|
||||
path = f"/tmp/tmp{uuid4()}"
|
||||
with atomic_write_func(path) as f:
|
||||
@@ -13,12 +12,8 @@ class TestFileHelpers(unittest.TestCase):
|
||||
assert not os.path.exists(path)
|
||||
|
||||
with open(path) as f:
|
||||
self.assertEqual(f.read(), "test")
|
||||
assert f.read() == "test"
|
||||
os.remove(path)
|
||||
|
||||
def test_atomic_write_in_dir(self):
|
||||
self.run_atomic_write_func(atomic_write_in_dir)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
15
common/tests/test_markdown.py
Normal file
15
common/tests/test_markdown.py
Normal file
@@ -0,0 +1,15 @@
|
||||
import os
|
||||
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.common.markdown import parse_markdown
|
||||
|
||||
|
||||
class TestMarkdown:
|
||||
def test_all_release_notes(self):
|
||||
with open(os.path.join(BASEDIR, "RELEASES.md")) as f:
|
||||
release_notes = f.read().split("\n\n")
|
||||
assert len(release_notes) > 10
|
||||
|
||||
for rn in release_notes:
|
||||
md = parse_markdown(rn)
|
||||
assert len(md) > 0
|
||||
@@ -1,10 +1,9 @@
|
||||
import numpy as np
|
||||
import unittest
|
||||
|
||||
from openpilot.common.numpy_fast import interp
|
||||
|
||||
|
||||
class InterpTest(unittest.TestCase):
|
||||
class TestInterp:
|
||||
def test_correctness_controls(self):
|
||||
_A_CRUISE_MIN_BP = np.asarray([0., 5., 10., 20., 40.])
|
||||
_A_CRUISE_MIN_V = np.asarray([-1.0, -.8, -.67, -.5, -.30])
|
||||
@@ -20,7 +19,3 @@ class InterpTest(unittest.TestCase):
|
||||
expected = np.interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
||||
actual = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
||||
np.testing.assert_equal(actual, expected)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import pytest
|
||||
import os
|
||||
import threading
|
||||
import time
|
||||
import uuid
|
||||
import unittest
|
||||
|
||||
from openpilot.common.params import Params, ParamKeyType, UnknownKeyName
|
||||
|
||||
class TestParams(unittest.TestCase):
|
||||
def setUp(self):
|
||||
class TestParams:
|
||||
def setup_method(self):
|
||||
self.params = Params()
|
||||
|
||||
def test_params_put_and_get(self):
|
||||
@@ -49,16 +49,16 @@ class TestParams(unittest.TestCase):
|
||||
assert self.params.get("CarParams", True) == b"test"
|
||||
|
||||
def test_params_unknown_key_fails(self):
|
||||
with self.assertRaises(UnknownKeyName):
|
||||
with pytest.raises(UnknownKeyName):
|
||||
self.params.get("swag")
|
||||
|
||||
with self.assertRaises(UnknownKeyName):
|
||||
with pytest.raises(UnknownKeyName):
|
||||
self.params.get_bool("swag")
|
||||
|
||||
with self.assertRaises(UnknownKeyName):
|
||||
with pytest.raises(UnknownKeyName):
|
||||
self.params.put("swag", "abc")
|
||||
|
||||
with self.assertRaises(UnknownKeyName):
|
||||
with pytest.raises(UnknownKeyName):
|
||||
self.params.put_bool("swag", True)
|
||||
|
||||
def test_remove_not_there(self):
|
||||
@@ -68,19 +68,19 @@ class TestParams(unittest.TestCase):
|
||||
|
||||
def test_get_bool(self):
|
||||
self.params.remove("IsMetric")
|
||||
self.assertFalse(self.params.get_bool("IsMetric"))
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
self.params.put_bool("IsMetric", True)
|
||||
self.assertTrue(self.params.get_bool("IsMetric"))
|
||||
assert self.params.get_bool("IsMetric")
|
||||
|
||||
self.params.put_bool("IsMetric", False)
|
||||
self.assertFalse(self.params.get_bool("IsMetric"))
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
self.params.put("IsMetric", "1")
|
||||
self.assertTrue(self.params.get_bool("IsMetric"))
|
||||
assert self.params.get_bool("IsMetric")
|
||||
|
||||
self.params.put("IsMetric", "0")
|
||||
self.assertFalse(self.params.get_bool("IsMetric"))
|
||||
assert not self.params.get_bool("IsMetric")
|
||||
|
||||
def test_put_non_blocking_with_get_block(self):
|
||||
q = Params()
|
||||
@@ -107,7 +107,3 @@ class TestParams(unittest.TestCase):
|
||||
assert len(keys) > 20
|
||||
assert len(keys) == len(set(keys))
|
||||
assert b"CarParams" in keys
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
import unittest
|
||||
|
||||
from openpilot.common.simple_kalman import KF1D
|
||||
|
||||
|
||||
class TestSimpleKalman(unittest.TestCase):
|
||||
def setUp(self):
|
||||
class TestSimpleKalman:
|
||||
def setup_method(self):
|
||||
dt = 0.01
|
||||
x0_0 = 0.0
|
||||
x1_0 = 0.0
|
||||
@@ -24,12 +22,8 @@ class TestSimpleKalman(unittest.TestCase):
|
||||
|
||||
def test_getter_setter(self):
|
||||
self.kf.set_x([[1.0], [1.0]])
|
||||
self.assertEqual(self.kf.x, [[1.0], [1.0]])
|
||||
assert self.kf.x == [[1.0], [1.0]]
|
||||
|
||||
def update_returns_state(self):
|
||||
x = self.kf.update(100)
|
||||
self.assertEqual(x, self.kf.x)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
assert x == self.kf.x
|
||||
|
||||
8
common/tests/test_threadname.py
Normal file
8
common/tests/test_threadname.py
Normal file
@@ -0,0 +1,8 @@
|
||||
from openpilot.common.threadname import setthreadname, getthreadname, LINUX
|
||||
|
||||
class TestThreadName:
|
||||
def test_set_get_threadname(self):
|
||||
if LINUX:
|
||||
name = 'TESTING'
|
||||
setthreadname(name)
|
||||
assert name == getthreadname()
|
||||
19
common/threadname.py
Normal file
19
common/threadname.py
Normal file
@@ -0,0 +1,19 @@
|
||||
import ctypes
|
||||
import os
|
||||
|
||||
LINUX = os.name == 'posix' and os.uname().sysname == 'Linux'
|
||||
|
||||
if LINUX:
|
||||
libc = ctypes.CDLL('libc.so.6')
|
||||
|
||||
def setthreadname(name: str) -> None:
|
||||
if LINUX:
|
||||
name = name[-15:] + '\0'
|
||||
libc.prctl(15, str.encode(name), 0, 0, 0)
|
||||
|
||||
def getthreadname() -> str:
|
||||
if LINUX:
|
||||
name = ctypes.create_string_buffer(16)
|
||||
libc.prctl(16, name)
|
||||
return name.value.decode('utf-8')
|
||||
return ""
|
||||
@@ -1,6 +1,15 @@
|
||||
import datetime
|
||||
from pathlib import Path
|
||||
|
||||
MIN_DATE = datetime.datetime(year=2024, month=1, day=28)
|
||||
_MIN_DATE = datetime.datetime(year=2024, month=3, day=30)
|
||||
|
||||
def min_date():
|
||||
# on systemd systems, the default time is the systemd build time
|
||||
systemd_path = Path("/lib/systemd/systemd")
|
||||
if systemd_path.exists():
|
||||
d = datetime.datetime.fromtimestamp(systemd_path.stat().st_mtime)
|
||||
return d + datetime.timedelta(days=1)
|
||||
return _MIN_DATE
|
||||
|
||||
def system_time_valid():
|
||||
return datetime.datetime.now() > MIN_DATE
|
||||
return datetime.datetime.now() > min_date()
|
||||
|
||||
@@ -1,55 +1,74 @@
|
||||
import itertools
|
||||
import numpy as np
|
||||
from dataclasses import dataclass
|
||||
|
||||
import openpilot.common.transformations.orientation as orient
|
||||
|
||||
## -- hardcoded hardware params --
|
||||
eon_f_focal_length = 910.0
|
||||
eon_d_focal_length = 650.0
|
||||
tici_f_focal_length = 2648.0
|
||||
tici_e_focal_length = tici_d_focal_length = 567.0 # probably wrong? magnification is not consistent across frame
|
||||
@dataclass(frozen=True)
|
||||
class CameraConfig:
|
||||
width: int
|
||||
height: int
|
||||
focal_length: float
|
||||
|
||||
eon_f_frame_size = (1164, 874)
|
||||
eon_d_frame_size = (816, 612)
|
||||
tici_f_frame_size = tici_e_frame_size = tici_d_frame_size = (1928, 1208)
|
||||
@property
|
||||
def size(self):
|
||||
return (self.width, self.height)
|
||||
|
||||
# aka 'K' aka camera_frame_from_view_frame
|
||||
eon_fcam_intrinsics = np.array([
|
||||
[eon_f_focal_length, 0.0, float(eon_f_frame_size[0])/2],
|
||||
[0.0, eon_f_focal_length, float(eon_f_frame_size[1])/2],
|
||||
[0.0, 0.0, 1.0]])
|
||||
eon_intrinsics = eon_fcam_intrinsics # xx
|
||||
@property
|
||||
def intrinsics(self):
|
||||
# aka 'K' aka camera_frame_from_view_frame
|
||||
return np.array([
|
||||
[self.focal_length, 0.0, float(self.width)/2],
|
||||
[0.0, self.focal_length, float(self.height)/2],
|
||||
[0.0, 0.0, 1.0]
|
||||
])
|
||||
|
||||
eon_dcam_intrinsics = np.array([
|
||||
[eon_d_focal_length, 0.0, float(eon_d_frame_size[0])/2],
|
||||
[0.0, eon_d_focal_length, float(eon_d_frame_size[1])/2],
|
||||
[0.0, 0.0, 1.0]])
|
||||
@property
|
||||
def intrinsics_inv(self):
|
||||
# aka 'K_inv' aka view_frame_from_camera_frame
|
||||
return np.linalg.inv(self.intrinsics)
|
||||
|
||||
tici_fcam_intrinsics = np.array([
|
||||
[tici_f_focal_length, 0.0, float(tici_f_frame_size[0])/2],
|
||||
[0.0, tici_f_focal_length, float(tici_f_frame_size[1])/2],
|
||||
[0.0, 0.0, 1.0]])
|
||||
@dataclass(frozen=True)
|
||||
class _NoneCameraConfig(CameraConfig):
|
||||
width: int = 0
|
||||
height: int = 0
|
||||
focal_length: float = 0
|
||||
|
||||
tici_dcam_intrinsics = np.array([
|
||||
[tici_d_focal_length, 0.0, float(tici_d_frame_size[0])/2],
|
||||
[0.0, tici_d_focal_length, float(tici_d_frame_size[1])/2],
|
||||
[0.0, 0.0, 1.0]])
|
||||
@dataclass(frozen=True)
|
||||
class DeviceCameraConfig:
|
||||
fcam: CameraConfig
|
||||
dcam: CameraConfig
|
||||
ecam: CameraConfig
|
||||
|
||||
tici_ecam_intrinsics = tici_dcam_intrinsics
|
||||
def all_cams(self):
|
||||
for cam in ['fcam', 'dcam', 'ecam']:
|
||||
if not isinstance(getattr(self, cam), _NoneCameraConfig):
|
||||
yield cam, getattr(self, cam)
|
||||
|
||||
# aka 'K_inv' aka view_frame_from_camera_frame
|
||||
eon_fcam_intrinsics_inv = np.linalg.inv(eon_fcam_intrinsics)
|
||||
eon_intrinsics_inv = eon_fcam_intrinsics_inv # xx
|
||||
_ar_ox_fisheye = CameraConfig(1928, 1208, 567.0) # focal length probably wrong? magnification is not consistent across frame
|
||||
_os_fisheye = CameraConfig(2688, 1520, 567.0 / 2 * 3)
|
||||
_ar_ox_config = DeviceCameraConfig(CameraConfig(1928, 1208, 2648.0), _ar_ox_fisheye, _ar_ox_fisheye)
|
||||
_os_config = DeviceCameraConfig(CameraConfig(2688, 1520, 2648.0 * 2 / 3), _os_fisheye, _os_fisheye)
|
||||
_neo_config = DeviceCameraConfig(CameraConfig(1164, 874, 910.0), CameraConfig(816, 612, 650.0), _NoneCameraConfig())
|
||||
|
||||
tici_fcam_intrinsics_inv = np.linalg.inv(tici_fcam_intrinsics)
|
||||
tici_ecam_intrinsics_inv = np.linalg.inv(tici_ecam_intrinsics)
|
||||
DEVICE_CAMERAS = {
|
||||
# A "device camera" is defined by a device type and sensor
|
||||
|
||||
# sensor type was never set on eon/neo/two
|
||||
("neo", "unknown"): _neo_config,
|
||||
# unknown here is AR0231, field was added with OX03C10 support
|
||||
("tici", "unknown"): _ar_ox_config,
|
||||
|
||||
FULL_FRAME_SIZE = tici_f_frame_size
|
||||
FOCAL = tici_f_focal_length
|
||||
fcam_intrinsics = tici_fcam_intrinsics
|
||||
|
||||
W, H = FULL_FRAME_SIZE[0], FULL_FRAME_SIZE[1]
|
||||
# before deviceState.deviceType was set, assume tici AR config
|
||||
("unknown", "ar0231"): _ar_ox_config,
|
||||
("unknown", "ox03c10"): _ar_ox_config,
|
||||
|
||||
# simulator (emulates a tici)
|
||||
("pc", "unknown"): _ar_ox_config,
|
||||
}
|
||||
prods = itertools.product(('tici', 'tizi', 'mici'), (('ar0231', _ar_ox_config), ('ox03c10', _ar_ox_config), ('os04c10', _os_config)))
|
||||
DEVICE_CAMERAS.update({(d, c[0]): c[1] for d, c in prods})
|
||||
|
||||
# device/mesh : x->forward, y-> right, z->down
|
||||
# view : x->right, y->down, z->forward
|
||||
@@ -93,7 +112,7 @@ def roll_from_ke(m):
|
||||
-(m[0, 0] - m[0, 1] * m[2, 0] / m[2, 1]))
|
||||
|
||||
|
||||
def normalize(img_pts, intrinsics=fcam_intrinsics):
|
||||
def normalize(img_pts, intrinsics):
|
||||
# normalizes image coordinates
|
||||
# accepts single pt or array of pts
|
||||
intrinsics_inv = np.linalg.inv(intrinsics)
|
||||
@@ -106,7 +125,7 @@ def normalize(img_pts, intrinsics=fcam_intrinsics):
|
||||
return img_pts_normalized[:, :2].reshape(input_shape)
|
||||
|
||||
|
||||
def denormalize(img_pts, intrinsics=fcam_intrinsics, width=np.inf, height=np.inf):
|
||||
def denormalize(img_pts, intrinsics, width=np.inf, height=np.inf):
|
||||
# denormalizes image coordinates
|
||||
# accepts single pt or array of pts
|
||||
img_pts = np.array(img_pts)
|
||||
@@ -123,7 +142,7 @@ def denormalize(img_pts, intrinsics=fcam_intrinsics, width=np.inf, height=np.inf
|
||||
return img_pts_denormalized[:, :2].reshape(input_shape)
|
||||
|
||||
|
||||
def get_calib_from_vp(vp, intrinsics=fcam_intrinsics):
|
||||
def get_calib_from_vp(vp, intrinsics):
|
||||
vp_norm = normalize(vp, intrinsics)
|
||||
yaw_calib = np.arctan(vp_norm[0])
|
||||
pitch_calib = -np.arctan(vp_norm[1]*np.cos(yaw_calib))
|
||||
|
||||
@@ -1,19 +1,11 @@
|
||||
import numpy as np
|
||||
|
||||
from openpilot.common.transformations.orientation import rot_from_euler
|
||||
from openpilot.common.transformations.camera import (
|
||||
FULL_FRAME_SIZE, get_view_frame_from_calib_frame, view_frame_from_device_frame,
|
||||
eon_fcam_intrinsics, tici_ecam_intrinsics, tici_fcam_intrinsics)
|
||||
from openpilot.common.transformations.camera import get_view_frame_from_calib_frame, view_frame_from_device_frame
|
||||
|
||||
# segnet
|
||||
SEGNET_SIZE = (512, 384)
|
||||
|
||||
def get_segnet_frame_from_camera_frame(segnet_size=SEGNET_SIZE, full_frame_size=FULL_FRAME_SIZE):
|
||||
return np.array([[float(segnet_size[0]) / full_frame_size[0], 0.0],
|
||||
[0.0, float(segnet_size[1]) / full_frame_size[1]]])
|
||||
segnet_frame_from_camera_frame = get_segnet_frame_from_camera_frame() # xx
|
||||
|
||||
|
||||
# MED model
|
||||
MEDMODEL_INPUT_SIZE = (512, 256)
|
||||
MEDMODEL_YUV_SIZE = (MEDMODEL_INPUT_SIZE[0], MEDMODEL_INPUT_SIZE[1] * 3 // 2)
|
||||
@@ -63,16 +55,9 @@ calib_from_medmodel = np.linalg.inv(medmodel_frame_from_calib_frame[:, :3])
|
||||
calib_from_sbigmodel = np.linalg.inv(sbigmodel_frame_from_calib_frame[:, :3])
|
||||
|
||||
# This function is verified to give similar results to xx.uncommon.utils.transform_img
|
||||
def get_warp_matrix(device_from_calib_euler: np.ndarray, wide_camera: bool = False, bigmodel_frame: bool = False, tici: bool = True) -> np.ndarray:
|
||||
if tici and wide_camera:
|
||||
cam_intrinsics = tici_ecam_intrinsics
|
||||
elif tici:
|
||||
cam_intrinsics = tici_fcam_intrinsics
|
||||
else:
|
||||
cam_intrinsics = eon_fcam_intrinsics
|
||||
|
||||
def get_warp_matrix(device_from_calib_euler: np.ndarray, intrinsics: np.ndarray, bigmodel_frame: bool = False) -> np.ndarray:
|
||||
calib_from_model = calib_from_sbigmodel if bigmodel_frame else calib_from_medmodel
|
||||
device_from_calib = rot_from_euler(device_from_calib_euler)
|
||||
camera_from_calib = cam_intrinsics @ view_frame_from_device_frame @ device_from_calib
|
||||
camera_from_calib = intrinsics @ view_frame_from_device_frame @ device_from_calib
|
||||
warp_matrix: np.ndarray = camera_from_calib @ calib_from_model
|
||||
return warp_matrix
|
||||
|
||||
15
common/transformations/tests/test_coordinates.py
Executable file → Normal file
15
common/transformations/tests/test_coordinates.py
Executable file → Normal file
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
import unittest
|
||||
|
||||
import openpilot.common.transformations.coordinates as coord
|
||||
|
||||
@@ -44,7 +41,7 @@ ned_offsets_batch = np.array([[ 53.88103168, 43.83445935, -46.27488057],
|
||||
[ 78.56272609, 18.53100158, -43.25290759]])
|
||||
|
||||
|
||||
class TestNED(unittest.TestCase):
|
||||
class TestNED:
|
||||
def test_small_distances(self):
|
||||
start_geodetic = np.array([33.8042184, -117.888593, 0.0])
|
||||
local_coord = coord.LocalCoord.from_geodetic(start_geodetic)
|
||||
@@ -54,13 +51,13 @@ class TestNED(unittest.TestCase):
|
||||
|
||||
west_geodetic = start_geodetic + [0, -0.0005, 0]
|
||||
west_ned = local_coord.geodetic2ned(west_geodetic)
|
||||
self.assertLess(np.abs(west_ned[0]), 1e-3)
|
||||
self.assertLess(west_ned[1], 0)
|
||||
assert np.abs(west_ned[0]) < 1e-3
|
||||
assert west_ned[1] < 0
|
||||
|
||||
southwest_geodetic = start_geodetic + [-0.0005, -0.002, 0]
|
||||
southwest_ned = local_coord.geodetic2ned(southwest_geodetic)
|
||||
self.assertLess(southwest_ned[0], 0)
|
||||
self.assertLess(southwest_ned[1], 0)
|
||||
assert southwest_ned[0] < 0
|
||||
assert southwest_ned[1] < 0
|
||||
|
||||
def test_ecef_geodetic(self):
|
||||
# testing single
|
||||
@@ -105,5 +102,3 @@ class TestNED(unittest.TestCase):
|
||||
np.testing.assert_allclose(converter.ned2ecef(ned_offsets_batch),
|
||||
ecef_positions_offset_batch,
|
||||
rtol=1e-9, atol=1e-7)
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
9
common/transformations/tests/test_orientation.py
Executable file → Normal file
9
common/transformations/tests/test_orientation.py
Executable file → Normal file
@@ -1,7 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import numpy as np
|
||||
import unittest
|
||||
|
||||
from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \
|
||||
rot2quat, quat2rot, \
|
||||
@@ -32,7 +29,7 @@ ned_eulers = np.array([[ 0.46806039, -0.4881889 , 1.65697808],
|
||||
[ 2.50450101, 0.36304151, 0.33136365]])
|
||||
|
||||
|
||||
class TestOrientation(unittest.TestCase):
|
||||
class TestOrientation:
|
||||
def test_quat_euler(self):
|
||||
for i, eul in enumerate(eulers):
|
||||
np.testing.assert_allclose(quats[i], euler2quat(eul), rtol=1e-7)
|
||||
@@ -62,7 +59,3 @@ class TestOrientation(unittest.TestCase):
|
||||
np.testing.assert_allclose(ned_eulers[i], ned_euler_from_ecef(ecef_positions[i], eulers[i]), rtol=1e-7)
|
||||
#np.testing.assert_allclose(eulers[i], ecef_euler_from_ned(ecef_positions[i], ned_eulers[i]), rtol=1e-7)
|
||||
# np.testing.assert_allclose(ned_eulers, ned_euler_from_ecef(ecef_positions, eulers), rtol=1e-7)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
||||
@@ -246,18 +246,13 @@ std::string random_string(std::string::size_type length) {
|
||||
return s;
|
||||
}
|
||||
|
||||
std::string dir_name(std::string const &path) {
|
||||
size_t pos = path.find_last_of("/");
|
||||
if (pos == std::string::npos) return "";
|
||||
return path.substr(0, pos);
|
||||
}
|
||||
|
||||
bool starts_with(const std::string &s1, const std::string &s2) {
|
||||
return strncmp(s1.c_str(), s2.c_str(), s2.size()) == 0;
|
||||
}
|
||||
|
||||
bool ends_with(const std::string &s1, const std::string &s2) {
|
||||
return strcmp(s1.c_str() + (s1.size() - s2.size()), s2.c_str()) == 0;
|
||||
bool ends_with(const std::string& s, const std::string& suffix) {
|
||||
return s.size() >= suffix.size() &&
|
||||
strcmp(s.c_str() + (s.size() - suffix.size()), suffix.c_str()) == 0;
|
||||
}
|
||||
|
||||
std::string check_output(const std::string& command) {
|
||||
@@ -276,20 +271,4 @@ std::string check_output(const std::string& command) {
|
||||
return result;
|
||||
}
|
||||
|
||||
struct tm get_time() {
|
||||
time_t rawtime;
|
||||
time(&rawtime);
|
||||
|
||||
struct tm sys_time;
|
||||
gmtime_r(&rawtime, &sys_time);
|
||||
|
||||
return sys_time;
|
||||
}
|
||||
|
||||
bool time_valid(struct tm sys_time) {
|
||||
int year = 1900 + sys_time.tm_year;
|
||||
int month = 1 + sys_time.tm_mon;
|
||||
return (year > 2023) || (year == 2023 && month >= 6);
|
||||
}
|
||||
|
||||
} // namespace util
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
#include <atomic>
|
||||
#include <chrono>
|
||||
#include <csignal>
|
||||
#include <ctime>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
@@ -45,10 +44,6 @@ int set_realtime_priority(int level);
|
||||
int set_core_affinity(std::vector<int> cores);
|
||||
int set_file_descriptor_limit(uint64_t limit);
|
||||
|
||||
// ***** Time helpers *****
|
||||
struct tm get_time();
|
||||
bool time_valid(struct tm sys_time);
|
||||
|
||||
// ***** math helpers *****
|
||||
|
||||
// map x from [a1, a2] to [b1, b2]
|
||||
@@ -75,9 +70,8 @@ int getenv(const char* key, int default_val);
|
||||
float getenv(const char* key, float default_val);
|
||||
|
||||
std::string hexdump(const uint8_t* in, const size_t size);
|
||||
std::string dir_name(std::string const& path);
|
||||
bool starts_with(const std::string &s1, const std::string &s2);
|
||||
bool ends_with(const std::string &s1, const std::string &s2);
|
||||
bool ends_with(const std::string &s, const std::string &suffix);
|
||||
|
||||
// ***** random helpers *****
|
||||
int random_int(int min, int max);
|
||||
@@ -179,3 +173,10 @@ void update_max_atomic(std::atomic<T>& max, T const& value) {
|
||||
T prev = max;
|
||||
while (prev < value && !max.compare_exchange_weak(prev, value)) {}
|
||||
}
|
||||
|
||||
typedef struct Rect {
|
||||
int x;
|
||||
int y;
|
||||
int w;
|
||||
int h;
|
||||
} Rect;
|
||||
|
||||
11
common/utils.py
Normal file
11
common/utils.py
Normal file
@@ -0,0 +1,11 @@
|
||||
class Freezable:
|
||||
_frozen: bool = False
|
||||
|
||||
def freeze(self):
|
||||
if not self._frozen:
|
||||
self._frozen = True
|
||||
|
||||
def __setattr__(self, *args, **kwargs):
|
||||
if self._frozen:
|
||||
raise Exception("cannot modify frozen object")
|
||||
super().__setattr__(*args, **kwargs)
|
||||
@@ -1 +1 @@
|
||||
#define COMMA_VERSION "0.9.7.0"
|
||||
#define COMMA_VERSION "0.9.8.0"
|
||||
|
||||
@@ -5,7 +5,7 @@ import pytest
|
||||
import random
|
||||
|
||||
from openpilot.common.prefix import OpenpilotPrefix
|
||||
from openpilot.selfdrive.manager import manager
|
||||
from openpilot.system.manager import manager
|
||||
from openpilot.system.hardware import TICI, HARDWARE
|
||||
|
||||
|
||||
|
||||
@@ -9,8 +9,10 @@ Get paid to improve openpilot!
|
||||
* once you open a PR, the bounty is locked to you until you stop working on it
|
||||
* open a ticket at [comma.ai/support](https://comma.ai/support/shop-order) with links to your PRs to claim
|
||||
* get an extra 20% if you redeem your bounty in [comma shop](https://comma.ai/shop) credit (including refunds on previous orders)
|
||||
* for bounties >$100, the first PR gets a lock, which times out after a week of no progress
|
||||
|
||||
New bounties can be proposed in the [**#contributing**](https://discord.com/channels/469524606043160576/1183173332531687454) channel in Discord.
|
||||
We put up each bounty with the intention that it'll get merged, but occasionally the right resolution is to close the bounty, which only becomes clear once some effort is put in.
|
||||
This is still valuable work, so we'll pay out $100 for getting any bounty closed with a good explanation.
|
||||
|
||||
## Issue bounties
|
||||
|
||||
@@ -20,6 +22,8 @@ We've tagged bounty-eligible issues across openpilot and the rest of our repos;
|
||||
* **$500** - a few days of work for an experienced openpilot developer
|
||||
* **$1k+** - a week or two of work (could be less for the right person)
|
||||
|
||||
New bounties can be proposed in the [**#contributing**](https://discord.com/channels/469524606043160576/1183173332531687454) channel in Discord.
|
||||
|
||||
## Car bounties
|
||||
|
||||
The car bounties only apply to cars that have a path to ship in openpilot release, which excludes unsupportable cars (e.g. Fords with a steering lockout) or cars that require extra hardware (Honda Accord with serial steering).
|
||||
@@ -53,10 +57,6 @@ The control doesn't have to be perfect, but it should generally do what it's sup
|
||||
Get a Rivian driving with openpilot.
|
||||
Requires a merged port with lateral control and at least a POC of longitudinal control.
|
||||
|
||||
#### Toyota SecOc - $5000
|
||||
|
||||
We're contributing $5k to the [community-organized bounty](https://github.com/commaai/openpilot/discussions/19932).
|
||||
|
||||
#### Chevy Bolt with SuperCruise - $2500
|
||||
|
||||
The Bolt is already supported on the trim with standard ACC. Get openpilot working on the trim with SuperCruise. It must be a normal install: no extra pandas or other hardware, no ECU reflashes, etc. The full bounty is for a port with lateral and longitudinal control. $1500 of the bounty can be claimed with a lateral-only port.
|
||||
|
||||
287
docs/CARS.md
287
docs/CARS.md
@@ -11,31 +11,27 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Acura|ILX 2016-19|AcuraWatch Plus|openpilot|25 mph|25 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-19">Buy Here</a></sub></details>||
|
||||
|Acura|RDX 2016-18|AcuraWatch Plus|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|RDX 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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-22">Buy Here</a></sub></details>||
|
||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Q3 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">Buy Here</a></sub></details>||
|
||||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Buick|LaCrosse 2017-19[<sup>4</sup>](#footnotes)|Driver Confidence Package 2|openpilot|18 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Buick&model=LaCrosse 2017-19">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade 2017[<sup>4</sup>](#footnotes)|Driver Assist Package|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade 2017">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade ESV 2016[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade ESV 2016">Buy Here</a></sub></details>||
|
||||
|Cadillac|Escalade ESV 2019[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<br>- 1 mount<br>- 1 right angle OBD-C cable (1.5 ft)<br><a href="https://comma.ai/shop/comma-3x.html?make=Cadillac&model=Escalade ESV 2019">Buy Here</a></sub></details>||
|
||||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Q3 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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-23">Buy Here</a></sub></details>||
|
||||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|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>|
|
||||
|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>||
|
||||
|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|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|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|Volt 2017-18[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<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=Volt 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/QeMCN_4TFfQ" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Chrysler|Pacifica Hybrid 2017|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2018|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 2018">Buy Here</a></sub></details>||
|
||||
|Chrysler|Pacifica Hybrid 2019-23|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|comma|body|All|openpilot|0 mph|0 mph|[](##)|[](##)|None||
|
||||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Ford|Bronco Sport 2021-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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-22">Buy Here</a></sub></details>||
|
||||
|Ford|Bronco Sport 2021-23|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
@@ -47,31 +43,31 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Ford|Kuga Hybrid 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-22">Buy Here</a></sub></details>||
|
||||
|Ford|Kuga Plug-in Hybrid 2020-22|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-22">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick 2022|LARIAT Luxury|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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|Maverick 2023|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Ford|Maverick 2023-24|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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|Maverick Hybrid 2022|LARIAT Luxury|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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|Maverick Hybrid 2023|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Genesis|G70 2018-19|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-19">Buy Here</a></sub></details>||
|
||||
|Genesis|G70 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 2020">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Genesis|G70 2018|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Genesis|G80 2017|All|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Genesis|G80 2018-19|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Genesis|G90 2017-18|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-18">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|GV60 (Performance Trim) 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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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) 2023">Buy Here</a></sub></details>||
|
||||
|Genesis|GV70 (2.5T Trim) 2022-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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) 2022-23">Buy Here</a></sub></details>||
|
||||
|Genesis|GV70 (3.5T Trim) 2022-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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) 2022-23">Buy Here</a></sub></details>||
|
||||
|Genesis|GV80 2023[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|GMC|Acadia 2018[<sup>4</sup>](#footnotes)|Adaptive Cruise Control (ACC)|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 comma 3X<br>- 2 long OBD-C cable<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=Acadia 2018">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0ZN6DdsBUZo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|GV60 (Advanced Trim) 2023[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|GV60 (Performance Trim) 2023[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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) 2023">Buy Here</a></sub></details>||
|
||||
|Genesis|GV70 (2.5T Trim, without HDA II) 2022-23[<sup>5</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Genesis|GV70 (3.5T Trim, without HDA II) 2022-23[<sup>5</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|GV80 2023[<sup>5</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai M connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Honda|Civic 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>4</sup>](#footnotes)|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Civic Hatchback 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|Honda|Civic Hatchback 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|CR-V 2015-16|Touring Trim|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|CR-V Hybrid 2017-20|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-20">Buy Here</a></sub></details>||
|
||||
|Honda|CR-V Hybrid 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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-21">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Fit 2018-20|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Freed 2020|Honda Sensing|openpilot|25 mph|12 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
@@ -87,30 +83,30 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Elantra 2017-18|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Elantra 2019|Smart Cruise Control (SCC)|Stock|19 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Hyundai|Elantra GT 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-19">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Ioniq 5 (Southeast Asia only) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 only) 2022-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Ioniq 5 (with HDA II) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Ioniq 5 (without HDA II) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Ioniq 6 (with HDA II) 2023[<sup>6</sup>](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Hyundai|Ioniq 5 (Non-US only) 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 (Non-US only) 2022-24">Buy Here</a></sub></details>||
|
||||
|Hyundai|Ioniq 5 (with HDA II) 2022-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Ioniq 5 (without HDA II) 2022-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Ioniq 6 (with HDA II) 2023-24[<sup>5</sup>](#footnotes)|Highway Driving Assist II|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Hyundai|Ioniq Electric 2019|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Ioniq Hybrid 2020-22|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Kona 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Kona Electric 2022-23|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Kona Electric (with HDA II, Korea only) 2023[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Santa Cruz 2022-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 N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Hyundai|Santa Cruz 2022-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
@@ -118,49 +114,51 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Hyundai|Sonata 2018-19|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Tucson 2023[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Hyundai|Staria 2023[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Tucson 2022[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Tucson 2023-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Tucson Hybrid 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Tucson Plug-in Hybrid 2024[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Veloster 2019-20|Smart Cruise Control (SCC)|Stock|5 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Jeep|Grand Cherokee 2016-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Jeep|Grand Cherokee 2019-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Kia|Carnival 2022-24[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Carnival (China only) 2023[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Carnival 2022-24[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Carnival (China only) 2023[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Ceed 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (Southeast Asia only) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (with HDA II) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (without HDA II) 2022-23[<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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Kia|Forte 2019-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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Forte 2023|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 2023">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (Non-US only) 2022-24[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 (Non-US only) 2022-24">Buy Here</a></sub></details>||
|
||||
|Kia|EV6 (with HDA II) 2022-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|EV6 (without HDA II) 2022-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|K8 Hybrid (with HDA II) 2023[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Kia|Niro EV 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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 2023">Buy Here</a></sub></details>||
|
||||
|Kia|Niro EV 2023[<sup>5</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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 2023">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Niro Plug-in Hybrid 2020|All|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Niro Plug-in Hybrid 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai D connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Niro Plug-in Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Niro Hybrid 2023[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Kia|Niro Plug-in Hybrid 2018-19|All|Stock|10 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Optima 2017|Advanced Smart Cruise Control|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Optima 2019-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Optima Hybrid 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento 2018|Advanced Smart Cruise Control & LKAS|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento 2019|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento 2021-23[<sup>6</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento Hybrid 2021-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento Plug-in Hybrid 2022-23[<sup>6</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sportage 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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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">Buy Here</a></sub></details>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento 2021-23[<sup>5</sup>](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento Hybrid 2021-23[<sup>5</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sorento Plug-in Hybrid 2022-23[<sup>5</sup>](#footnotes)|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sportage 2023-24[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|Sportage Hybrid 2023[<sup>5</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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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|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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
@@ -187,8 +185,8 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Lexus|UX Hybrid 2019-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator 2020-23|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|Lincoln|Aviator Plug-in Hybrid 2020-23|Co-Pilot360 Plus|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-23">Buy Here</a></sub></details>||
|
||||
|MAN|eTGE 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|TGE 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|
||||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Mazda|CX-5 2022-24|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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-24">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 RJ45 cable (7 ft)<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Nissan|Altima 2019-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
@@ -196,26 +194,27 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Nissan|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Nissan|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 RJ45 cable (7 ft)<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|0 mph|32 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Ram connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|SEAT|Ateca 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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 2018">Buy Here</a></sub></details>||
|
||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Legacy 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Outback 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|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 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Škoda|Fabia 2022-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Škoda|Kamiq 2021-23[<sup>10,12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Škoda|Karoq 2019-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Škoda|Kodiaq 2017-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Škoda|Octavia 2015-19[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Škoda|Octavia RS 2016[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Škoda|Scala 2020-23[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Škoda|Superb 2015-22[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Subaru|Ascent 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Forester 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Legacy 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|Outback 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru B connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Subaru A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Škoda|Fabia 2022-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Škoda|Kamiq 2021-23[<sup>9,11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Škoda|Karoq 2019-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Škoda|Kodiaq 2017-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Škoda|Octavia 2015-19[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Škoda|Octavia RS 2016[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Škoda|Octavia Scout 2017-19[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Škoda|Scala 2020-23[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Škoda|Superb 2015-22[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
@@ -228,20 +227,20 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>9</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>9</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>8</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>8</sup>](#footnotes)|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Corolla Hybrid (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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 (Non-US only) 2020-23">Buy Here</a></sub></details>||
|
||||
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>||
|
||||
|Toyota|Prius 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
@@ -249,69 +248,69 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|Prius Prime 2017-20|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|Prius v 2017|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|Prius v 2017|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 2023-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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-24">Buy Here</a></sub></details>||
|
||||
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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|RAV4 Hybrid 2023-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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-24">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 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>|
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>|
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>|
|
||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>|
|
||||
|Volkswagen|Crafter 2017-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">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-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">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,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Grand California 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|31 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 angled mount (8 degrees)<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">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-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Jetta GLI 2021-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat 2015-22[<sup>11</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>14</sup>](#footnotes)||
|
||||
|Volkswagen|T-Roc 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-22">Buy Here</a></sub></details>[<sup>14</sup>](#footnotes)||
|
||||
|Volkswagen|Taos 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,13</sup>](#footnotes)|0 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 J533 connector<br>- 1 USB-C coupler<br>- 1 comma 3X<br>- 1 harness box<br>- 1 long OBD-C cable<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>||
|
||||
|Toyota|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 RJ45 cable (7 ft)<br>- 1 Toyota A connector<br>- 1 comma 3X<br>- 1 comma power v2<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>|
|
||||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>|
|
||||
|Volkswagen|Jetta 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Jetta GLI 2021-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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-24">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Passat 2015-22[<sup>10</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>13</sup>](#footnotes)||
|
||||
|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|Volkswagen|Taos 2022-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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-23">Buy Here</a></sub></details>||
|
||||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,12</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<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>||
|
||||
|
||||
### 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 `master-ci`. <br />
|
||||
<sup>2</sup>By default, this car will use the stock Adaptive Cruise Control (ACC) for longitudinal control. If the Driver Support Unit (DSU) is disconnected, openpilot ACC will replace stock ACC. <b><i>NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).</i></b> <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>Requires a <a href="https://github.com/commaai/openpilot/wiki/GM#hardware" target="_blank">community built ASCM harness</a>. <b><i>NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).</i></b> <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>7</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>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
|
||||
<sup>10</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>11</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
||||
<sup>12</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality. <br />
|
||||
<sup>13</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
|
||||
<sup>14</sup>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>4</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
|
||||
<sup>5</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>In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance. <br />
|
||||
<sup>7</sup>Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB. <br />
|
||||
<sup>8</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>9</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
|
||||
<sup>10</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
|
||||
<sup>11</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma 3X functionality. <br />
|
||||
<sup>12</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>13</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
|
||||
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/).
|
||||
@@ -352,7 +351,9 @@ openpilot does not yet support these Toyota models due to a new message authenti
|
||||
* Toyota Venza 2021+
|
||||
* Toyota Sequoia 2023+
|
||||
* Toyota Tundra 2022+
|
||||
* Toyota Highlander 2024+
|
||||
* Toyota Corolla Cross 2022+ (only US model)
|
||||
* Toyota Camry 2025+
|
||||
* Lexus NX 2022+
|
||||
* Toyota bZ4x 2023+
|
||||
* Subaru Solterra 2023+
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# Minimal makefile for Sphinx documentation
|
||||
#
|
||||
|
||||
OPENPILOT_ROOT = `git rev-parse --show-toplevel`
|
||||
|
||||
# You can set these variables from the command line, and also
|
||||
# from the environment for the first two.
|
||||
SPHINXOPTS ?=
|
||||
SPHINXBUILD ?= sphinx-build
|
||||
DOCSDIR = "$(OPENPILOT_ROOT)/docs"
|
||||
SOURCEDIR = "$(OPENPILOT_ROOT)/build/docs"
|
||||
DOCSBUILDDIR = "$(OPENPILOT_ROOT)/build/docs"
|
||||
BUILDDIR = "$(OPENPILOT_ROOT)/build"
|
||||
|
||||
# Put it first so that "make" without argument is like "make help".
|
||||
help:
|
||||
@$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(DOCSBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
|
||||
clean:
|
||||
@echo "Cleaning build folder..."
|
||||
rm -rf "$(BUILDDIR)"
|
||||
|
||||
.PHONY: help Makefile
|
||||
|
||||
# Catch-all target: route all unknown targets to Sphinx using the new
|
||||
# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
|
||||
%: Makefile
|
||||
@echo "Cleaning build folder..."
|
||||
rm -rf "$(BUILDDIR)"
|
||||
mkdir -p "$(DOCSBUILDDIR)"
|
||||
|
||||
@echo "Copying docs & config to build folder..."
|
||||
cp -a "$(DOCSDIR)" "$(BUILDDIR)"
|
||||
cd "$(OPENPILOT_ROOT)" && \
|
||||
find . -type f \( -name "*.md" -o -name "*.rst" -o -name "*.png" -o -name "*.jpg" -o -name "*.svg" \) \
|
||||
-not -path "*/.*" \
|
||||
-not -path "./build/*" \
|
||||
-not -path "./docs/*" \
|
||||
-not -path "./xx/*" \
|
||||
-exec cp --parents "{}" ./build/docs/ \;
|
||||
|
||||
@echo "Building rst files..."
|
||||
sphinx-apidoc -o "$(DOCSBUILDDIR)" ../ \
|
||||
../xx ../rednose_repo ../notebooks ../panda_jungle \
|
||||
../third_party \
|
||||
../panda/examples \
|
||||
../scripts \
|
||||
../selfdrive/modeld \
|
||||
../selfdrive/debug \
|
||||
$(shell find .. -type d -name "*test* -not -path "**.venv**" \")
|
||||
|
||||
@echo "Building html files..."
|
||||
@$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(DOCSBUILDDIR)" $(SPHINXOPTS) $(O)
|
||||
@@ -9,6 +9,7 @@ Most development happens on normal Ubuntu workstations, and not in cars or direc
|
||||
```bash
|
||||
# get the latest stuff
|
||||
git pull
|
||||
git lfs pull
|
||||
git submodule update --init --recursive
|
||||
|
||||
# update dependencies
|
||||
@@ -22,7 +23,7 @@ scons -j8 selfdrive/ui/
|
||||
cd selfdrive/ui/ && scons -u -j8
|
||||
|
||||
# test everything
|
||||
pytest .
|
||||
pytest
|
||||
|
||||
# test just logging services
|
||||
cd system/loggerd && pytest .
|
||||
|
||||
BIN
docs/_static/favicon.ico
vendored
BIN
docs/_static/favicon.ico
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB |
BIN
docs/_static/logo.png
LFS
vendored
BIN
docs/_static/logo.png
LFS
vendored
Binary file not shown.
2
docs/_static/robots.txt
vendored
2
docs/_static/robots.txt
vendored
@@ -1,2 +0,0 @@
|
||||
User-agent: *
|
||||
Sitemap: https://docs.comma.ai/sitemap.xml
|
||||
@@ -1,89 +0,0 @@
|
||||
openpilot
|
||||
==========
|
||||
|
||||
|
||||
opendbc
|
||||
------
|
||||
.. autodoxygenindex::
|
||||
:project: opendbc_can
|
||||
|
||||
|
||||
cereal
|
||||
------
|
||||
|
||||
messaging
|
||||
^^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: cereal_messaging
|
||||
|
||||
visionipc
|
||||
^^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: cereal_visionipc
|
||||
|
||||
|
||||
selfdrive
|
||||
---------
|
||||
|
||||
camerad
|
||||
^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: system_camerad_cameras
|
||||
|
||||
locationd
|
||||
^^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_locationd
|
||||
|
||||
ui
|
||||
^^
|
||||
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_ui
|
||||
|
||||
replay
|
||||
""""""
|
||||
.. autodoxygenindex::
|
||||
:project: tools_replay
|
||||
|
||||
qt
|
||||
""
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_ui_qt_offroad
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_ui_qt_maps
|
||||
|
||||
proclogd
|
||||
^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: system_proclogd
|
||||
|
||||
modeld
|
||||
^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_modeld_transforms
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_modeld_models
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_modeld_runners
|
||||
|
||||
common
|
||||
^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: common
|
||||
|
||||
sensorsd
|
||||
^^^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: system_sensord_sensors
|
||||
|
||||
boardd
|
||||
^^^^^^
|
||||
.. autodoxygenindex::
|
||||
:project: selfdrive_boardd
|
||||
|
||||
|
||||
rednose
|
||||
-------
|
||||
.. autodoxygenindex::
|
||||
:project: rednose_repo_rednose_helpers
|
||||
147
docs/conf.py
147
docs/conf.py
@@ -1,147 +0,0 @@
|
||||
# type: ignore
|
||||
|
||||
# Configuration file for the Sphinx documentation builder.
|
||||
#
|
||||
# This file only contains a selection of the most common options. For a full
|
||||
# list see the documentation:
|
||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html
|
||||
|
||||
# -- Path setup --------------------------------------------------------------
|
||||
|
||||
# If extensions (or modules to document with autodoc) are in another directory,
|
||||
# add these directories to sys.path here. If the directory is relative to the
|
||||
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||
#
|
||||
import os
|
||||
import sys
|
||||
from os.path import exists
|
||||
|
||||
from openpilot.common.basedir import BASEDIR
|
||||
from openpilot.system.version import get_version
|
||||
|
||||
sys.path.insert(0, os.path.abspath('.'))
|
||||
sys.path.insert(0, os.path.abspath('..'))
|
||||
|
||||
VERSION = get_version()
|
||||
|
||||
|
||||
# -- Project information -----------------------------------------------------
|
||||
|
||||
project = 'openpilot docs'
|
||||
copyright = '2021, comma.ai' # noqa: A001
|
||||
author = 'comma.ai'
|
||||
version = VERSION
|
||||
release = VERSION
|
||||
language = 'en'
|
||||
|
||||
|
||||
# -- General configuration ---------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||
# ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc', # Auto-generate docs
|
||||
'sphinx.ext.viewcode', # Add view code link to modules
|
||||
'sphinx_rtd_theme', # Read The Docs theme
|
||||
'myst_parser', # Markdown parsing
|
||||
'breathe', # Doxygen C/C++ integration
|
||||
'sphinx_sitemap', # sitemap generation for SEO
|
||||
]
|
||||
|
||||
myst_html_meta = {
|
||||
"description": "openpilot docs",
|
||||
"keywords": "op, openpilot, docs, documentation",
|
||||
"robots": "all,follow",
|
||||
"googlebot": "index,follow,snippet,archive",
|
||||
"property=og:locale": "en_US",
|
||||
"property=og:site_name": "docs.comma.ai",
|
||||
"property=og:url": "https://docs.comma.ai",
|
||||
"property=og:title": "openpilot Documentation",
|
||||
"property=og:type": "website",
|
||||
"property=og:image:type": "image/jpeg",
|
||||
"property=og:image:width": "400",
|
||||
"property=og:image": "https://docs.comma.ai/_static/logo.png",
|
||||
"property=og:image:url": "https://docs.comma.ai/_static/logo.png",
|
||||
"property=og:image:secure_url": "https://docs.comma.ai/_static/logo.png",
|
||||
"property=og:description": "openpilot Documentation",
|
||||
"property=twitter:card": "summary_large_image",
|
||||
"property=twitter:logo": "https://docs.comma.ai/_static/logo.png",
|
||||
"property=twitter:title": "openpilot Documentation",
|
||||
"property=twitter:description": "openpilot Documentation"
|
||||
}
|
||||
|
||||
html_baseurl = 'https://docs.comma.ai/'
|
||||
sitemap_filename = "sitemap.xml"
|
||||
|
||||
# Add any paths that contain templates here, relative to this directory.
|
||||
templates_path = ['_templates']
|
||||
|
||||
# List of patterns, relative to source directory, that match files and
|
||||
# directories to ignore when looking for source files.
|
||||
# This pattern also affects html_static_path and html_extra_path.
|
||||
exclude_patterns = []
|
||||
|
||||
|
||||
# -- c docs configuration ---------------------------------------------------
|
||||
|
||||
# Breathe Configuration
|
||||
# breathe_default_project = "c_docs"
|
||||
breathe_build_directory = f"{BASEDIR}/build/docs/html/xml"
|
||||
breathe_separate_member_pages = True
|
||||
breathe_default_members = ('members', 'private-members', 'undoc-members')
|
||||
breathe_domain_by_extension = {
|
||||
"h": "cc",
|
||||
}
|
||||
breathe_implementation_filename_extensions = ['.c', '.cc']
|
||||
breathe_doxygen_config_options = {}
|
||||
breathe_projects_source = {}
|
||||
|
||||
# only document files that have accompanying .cc files next to them
|
||||
print("searching for c_docs...")
|
||||
for root, _, files in os.walk(BASEDIR):
|
||||
found = False
|
||||
breath_src = {}
|
||||
breathe_srcs_list = []
|
||||
|
||||
for file in files:
|
||||
ccFile = os.path.join(root, file)[:-2] + ".cc"
|
||||
|
||||
if file.endswith(".h") and exists(ccFile):
|
||||
f = os.path.join(root, file)
|
||||
|
||||
parent_dir_abs = os.path.dirname(f)
|
||||
parent_dir = parent_dir_abs[len(BASEDIR) + 1:]
|
||||
parent_project = parent_dir.replace('/', '_')
|
||||
print(f"\tFOUND: {f} in {parent_project}")
|
||||
|
||||
breathe_srcs_list.append(file)
|
||||
found = True
|
||||
|
||||
if found:
|
||||
breath_src[parent_project] = (parent_dir_abs, breathe_srcs_list)
|
||||
breathe_projects_source.update(breath_src)
|
||||
|
||||
print(f"breathe_projects_source: {breathe_projects_source.keys()}")
|
||||
|
||||
# -- Options for HTML output -------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||
# a list of builtin themes.
|
||||
#
|
||||
html_theme = 'sphinx_rtd_theme'
|
||||
html_show_copyright = True
|
||||
|
||||
# Add any paths that contain custom static files (such as style sheets) here,
|
||||
# relative to this directory. They are copied after the builtin static files,
|
||||
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||
html_static_path = ['_static']
|
||||
html_logo = '_static/logo.png'
|
||||
html_favicon = '_static/favicon.ico'
|
||||
html_theme_options = {
|
||||
'logo_only': False,
|
||||
'display_version': True,
|
||||
'vcs_pageview_mode': 'blob',
|
||||
'style_nav_header_background': '#000000',
|
||||
}
|
||||
html_extra_path = ['_static']
|
||||
@@ -1,42 +0,0 @@
|
||||
# openpilot Documentation
|
||||
|
||||
```{include} README.md
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
:caption: 'General'
|
||||
:maxdepth: 4
|
||||
|
||||
CARS.md
|
||||
CONTRIBUTING.md
|
||||
INTEGRATION.md
|
||||
LIMITATIONS.md
|
||||
SAFETY.md
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
:caption: 'Overview'
|
||||
:maxdepth: 2
|
||||
|
||||
overview.rst
|
||||
```
|
||||
|
||||
## API Documentation
|
||||
|
||||
- {ref}`genindex`
|
||||
- {ref}`modindex`
|
||||
- {ref}`search`
|
||||
|
||||
```{toctree}
|
||||
:caption: 'Python API'
|
||||
:maxdepth: 2
|
||||
|
||||
modules.rst
|
||||
```
|
||||
|
||||
```{toctree}
|
||||
:caption: 'C/C++ API'
|
||||
:maxdepth: 4
|
||||
|
||||
c_docs.rst
|
||||
```
|
||||
12
docs/new/README.md
Normal file
12
docs/new/README.md
Normal file
@@ -0,0 +1,12 @@
|
||||
This is the source for a new https://docs.comma.ai. It's not hosted anywhere yet, but it's easy to run locally.
|
||||
|
||||
https://www.mkdocs.org/getting-started/
|
||||
|
||||
```
|
||||
pip install mkdocs mkdocs-terminal
|
||||
mkdocs serve
|
||||
```
|
||||
|
||||
inspiration:
|
||||
* https://rerun.io/docs/
|
||||
* https://docs.expo.dev/
|
||||
5
docs/new/docs/car-porting/brand-port.md
Normal file
5
docs/new/docs/car-porting/brand-port.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Developing a car brand port
|
||||
|
||||
A brand port is a port of openpilot to a substantially new car brand or platform within a brand.
|
||||
|
||||
Here's an example of one: https://github.com/commaai/openpilot/pull/23331.
|
||||
5
docs/new/docs/car-porting/model-port.md
Normal file
5
docs/new/docs/car-porting/model-port.md
Normal file
@@ -0,0 +1,5 @@
|
||||
# Developing a car model port
|
||||
|
||||
A model port is a port of openpilot to a new car model within an already supported brand. Model ports are easier than brand ports because the car's existing APIs are already known.
|
||||
|
||||
Here's an example of one: https://github.com/commaai/openpilot/pull/30672/.
|
||||
9
docs/new/docs/car-porting/what-is-a-car-port.md
Normal file
9
docs/new/docs/car-porting/what-is-a-car-port.md
Normal file
@@ -0,0 +1,9 @@
|
||||
# What is a car port?
|
||||
|
||||
All car ports live in `openpilot/selfdrive/car/`.
|
||||
|
||||
* interface.py: Interface for the car, defines the CarInterface class
|
||||
* carstate.py: Reads CAN from car and builds openpilot CarState message
|
||||
* carcontroller.py: Builds CAN messages to send to car
|
||||
* values.py: Limits for actuation, general constants for cars, and supported car documentation
|
||||
* radar_interface.py: Interface for parsing radar points from the car
|
||||
12
docs/new/docs/getting-started/what-is-openpilot.md
Normal file
12
docs/new/docs/getting-started/what-is-openpilot.md
Normal file
@@ -0,0 +1,12 @@
|
||||
# What is openpilot?
|
||||
|
||||
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW), and Lane Departure Warning (LDW) for a growing variety of [supported car makes, models, and model years](docs/CARS.md). In addition, while openpilot is engaged, a camera-based Driver Monitoring (DM) feature alerts distracted and asleep drivers. See more about [the vehicle integration](docs/INTEGRATION.md) and [limitations](docs/LIMITATIONS.md).
|
||||
|
||||
|
||||
## How do I use it?
|
||||
|
||||
openpilot is designed to be used on the comma 3X.
|
||||
|
||||
## How does it work?
|
||||
|
||||
In short, openpilot uses the car's existing APIs for the built-in [ADAS](https://en.wikipedia.org/wiki/Advanced_driver-assistance_system) system and simply provides better acceleration, braking, and steering inputs than the stock system.
|
||||
4
docs/new/docs/how-to/turning-the-speed-blue.md
Normal file
4
docs/new/docs/how-to/turning-the-speed-blue.md
Normal file
@@ -0,0 +1,4 @@
|
||||
This section is for how-to's on common workflows.
|
||||
|
||||
They'll be like this blog post we wrote:
|
||||
https://blog.comma.ai/turning-the-speed-blue/
|
||||
18
docs/new/mkdocs.yml
Normal file
18
docs/new/mkdocs.yml
Normal file
@@ -0,0 +1,18 @@
|
||||
site_name: openpilot docs
|
||||
docs_dir: docs
|
||||
repo_url: https://github.com/commaai/openpilot/
|
||||
|
||||
theme:
|
||||
name: terminal
|
||||
features:
|
||||
- navigation.side.toc.hide
|
||||
|
||||
nav:
|
||||
- Getting Started:
|
||||
- What is openpilot?: getting-started/what-is-openpilot.md
|
||||
- How-to:
|
||||
- Turn the speed blue: how-to/turning-the-speed-blue.md
|
||||
- Car Porting:
|
||||
- What is a car port?: car-porting/what-is-a-car-port.md
|
||||
- Porting a car brand: car-porting/brand-port.md
|
||||
- Porting a car model: car-porting/model-port.md
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user