Compare commits

...

433 Commits

Author SHA1 Message Date
discountchubbs 319069378e merge 2026-02-18 14:10:16 -08:00
discountchubbs cedb501376 better attribution to plan 2026-02-18 14:09:21 -08:00
discountchubbs fd1ec26e9a 20hz 2026-02-17 17:53:03 -08:00
discountchubbs 2b01fc4c9c Hyundai Longitudinal: deprecate ramp update for dynamic tune 2026-02-16 18:27:18 -08:00
github-actions[bot] f81e7245fe [bot] Update Python packages (#1702)
Update Python packages

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-16 04:18:44 -05:00
Jason Wen 0cb6b7b807 ci: exclude non-sunnypilot maintained submodules from repo maintenance (#1703)
* ci: exclude non-sunnypilot maintained submodules from repo maintenance

* match names
2026-02-16 04:16:49 -05:00
Jason Wen 4a869778a9 Revert "ci: skip uv lock upgrade on forks" (#1701)
Revert "ci: skip uv lock upgrade on forks (#1213)"

This reverts commit 220cfff04d.
2026-02-16 04:07:07 -05:00
Jason Wen a120053d12 docker: Dockerfile.sunnypilot uv run scons (#1700)
* docker: Dockerfile.sunnypilot uv run scons

* docker: Dockerfile.sunnypilot: don't set UV_PROJECT_ENVIRONMENT
2026-02-16 03:32:08 -05:00
James Vecellio-Grant a48988ccb3 chore: sync tinygrad (#1680)
* chore: sync tinygrad

Runs great in sim. now we need to rebuild some models

* oops forgot to unblock this after testing

* helpers

* oh yeah

* latest tg

* this wont do anything empriically

* reduce complexity

* okay lint

* Update tinygrad_runner.py

* Update modeld.py

* Update build-all-tinygrad-models.yaml

* tinygrad bump

* Update modeld.py

* Update tinygrad_runner.py

* bump

* Update SConscript

* Update SConscript

* com

* Update fetcher.py

* Update helpers.py

* Update model_runner.py

* Update model_runner.py

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-16 03:01:59 -05:00
Jason Wen 0650964559 [TIZI/TICI] ui: only fetch roles and users when the sunnylink panel is opened (#1697)
* sunnylink: only roles and users when the sunnylink panel is opened

* shadow

* thread-safe
2026-02-13 23:39:55 -05:00
Yasuhiro Ohno b62014eb12 SCC-V: Use p97 for predicted lateral accel (#1635)
* SCC-V: Use p97 for predicted lateral accel

* SCC-V: add param tests for p97 max_pred_lat_acc

* fix

* typo

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-13 17:03:03 -05:00
Jason Wen 037e8c18f8 sunnylink: update subscribed services states while running (#1694) 2026-02-13 16:22:51 -05:00
royjr 4bd60cd3cd [MICI] ui: rainbow path (#1630)
* allow rainbow road on mici

* initialization

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-13 11:41:30 -05:00
Jason Wen 3fe33cbe97 [TIZI/TICI] ui: fix toggle states and simplify blindspots/turn signals updates (#1692)
* [TIZI/TICI] ui: fix toggle states and simplify blindspots/turn signals updates

* more
2026-02-13 11:33:52 -05:00
Christopher Haucke b3878fb211 Pause Lateral Control with Blinker: Post-Blinker Delay (#1567)
* Delay lateral reengagement

* UI elements

* Add tests

* Update title and description

* Update params_metadata

* Didn't mean to pass this to int()

* Keep sentry happy

* Title and description update

* always 100 hz

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-12 23:33:38 -05:00
Nayan 33a26ba373 ui: better wake mode support (#1578)
* wake mode support

* use ui_state.params

* better

* cleanup

* fix

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-12 23:09:24 -05:00
Jason Wen 58af294ffd [TIZI/TICI] ui: Cruise panel (#1691)
* init cruise panel

* init descriptions

* damn descriptions

* init SLA sub layout

* reorder

* icbm it

* callback for `Custom ACC Speed Increments` toggle to update dependent UI elements dynamically.

* works

* more init

* more

* [TIZI/TICI] ui: individual button states support for MultipleButtonActionSP

* less

* convert

* init properly

---------

Co-authored-by: nayan <nayan8teen@gmail.com>
2026-02-12 22:56:18 -05:00
Jason Wen bafbfe19b4 [TIZI/TICI] ui: individual button states support for MultipleButtonActionSP (#1690)
* [TIZI/TICI] ui: individual button states support for MultipleButtonActionSP

* no magic nums
2026-02-12 22:32:15 -05:00
Jason Wen dae95af1df [TIZI/TICI] ui: override set_parent_rect to dynamically update item height (#1689)
[TIZI/TICI] ui: override `set_parent_rect` method to update item height dynamically
2026-02-12 22:07:05 -05:00
Jason Wen 86d52ab969 Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1687)
* clips: allow mici UI (now default) (#37070)

fix: make big false by default and remove assertion

* comma four: new keyboard enter button (#37072)

* works

* enter dis

* clean up

* clean up

* no debug

* useless

* poadding

* tools: fix Python version comparison using normalized semantic version format (#37075)

* Back to tethering BigButton (#37082)

Back to tethering big button

* Stock LKAS: remove permanent alert (#37083)

rm perm

* BigButton: remove unused scrolling (#37085)

* BigButton: remove unused scrolling

* clean up

* BigButton: use UnifiedLabel (#37086)

* BigButton: remove unused scrolling

* start

* debug

* stash

* actually removing the hardcoded size for multioption fixes it

* back

* cursor does sub label

* clean  up

* more

* more

* try this for now

* nick suggest

* clean up

* more

* more

* Network menu improvements (#37077)

* try this

* that's handy

* todo, not sure what happens here

* set_text

* normalize

* scroll wifi

* clean up

* more

* better check

* UI: only show `onroad_fade.png` when engaged (#37051)

* only show when engaged

* retrigger CI

* fade animation 0.1

* nl

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>

* NavBar: fix no show animation (#37090)

* 1.5 not enough time on small screen

* ohhhh

* clean up

* translations: remove arabic (#37087)

* remove arabic

* more

* bump opendbc (#37091)

* long_mpc: use log.capnp source enum instead of list (#37093)

* Revert "long_mpc: use log.capnp source enum instead of list" (#37095)

Revert "long_mpc: use log.capnp source enum instead of list (#37093)"

This reverts commit 7e959c5a3e.

* mici setup: remove unused functions

* fix mici setup int enum

* clips: improve overlays for mici (#37088)

* adjust overlay sizes and wrap metadata text for mici

* comment

* adjust overlay rendering to dynamically calculate line height for wrapped metadata text

* render time first so we can use width in margin calculation

* update comment (to retry failed CI actually)

* increase metadata size on mici

* longitudinal mpc tuning: behind if main (#37099)

* longitudinal mpc tuning report: add sinusoidal oscillation scenario (#37100)

* long_mpc: use log.capnp source enum (#37096)

* Calibrate in tg (#36621)

* squash

* bump tg

* fix linmt

* Ready to merge

* cleaner

* match modeld

* more dead stuff

* long mpc: state name before subscript (#37101)

* clip: clean up imports (#37104)

* wtf is this

* don't break import timing

* they are the same

* clean up

* good catch

* rm common/mat.h

* Remove all the OpenCL (#37105)

* Remove all the OpenCL

* lil more

* bump msgq

* clip: use wrap_text helper (#37102)

* they are same

* no duplication!

* rm rstrip

* bump opendbc (#37108)

bump

* Delete less dialogs (#37111)

* try

* revert

* this is fine

* revert tg calib and opencl cleanup (#37113)

* Revert "Remove all the OpenCL (#37105)"

This reverts commit d5cbb89d84.

* Revert "rm common/mat.h"

This reverts commit 4ce701150a.

* Revert "Calibrate in tg (#36621)"

This reverts commit 593c3a0c8e.

* fix: route fetch metadata when first log isnt uploaded (#37114)

* fix: route fetch metadata when first log isnt uploaded

* default

* simple

---------

Co-authored-by: Trey Moen <treymoen@amazon.com>

* gitignore .context/

* ui diff replay: remove unused frame_data list for individual frame display (#37117)

Remove unused base64 encoding and simplify frame data handling in diff video report

* bridge: move ZMQ handling over (#37118)

* replace tabulate with simple helper (#37122)

* Better memory usage debugging (#37120)

* Revert "revert tg calib and opencl cleanup (#37113)" (#37115)

* Revert "revert tg calib and opencl cleanup (#37113)"

This reverts commit 51312afd3d.

* power draw is a lil higher

* just don't miss a cycle

* fix warp targets

* fix tinygrad dep

* CI: garbage collect tmp jenkins branches (#37125)

* Build vendored artifacts in CI (#37127)

* Build vendored artifacts in CI

* parallel

* deterministic

* fix up

* fix gitignores

* lil more

* lil more consistency

* remove get_mcu_type from pandad.py (#37132)

* Chunk big model files (#37134)

* file chunking

* try this

* more cleanup

* cleaner

* ui: delay nav bar animation (#37137)

* from da bounce

* try this

* you can get it to clean up wow

* modeld: simplify model run processing (#37138)

Hi! The point of this pr is to make the model run easier to read. On the latest tinygrad numpy().flatten() empirically does the same thing as the internal contiguous().realize().uop.base.buffer.numpy(). numpy() is also documented (docstrings), which can assist new contributors in learning what each potential execution does. Torq_boi or yassine, I know you want proof in the code base, so here it is. As of tinygrad commit 2f55005:

 in tinygrad_repo/tinygrad/tensor.py
Lines 316-318 (def _buffer): ensure the tenso is contiguous() and realized() before accessing the raw buffer.
Line 378 (def numpy): Wraps the buffer access and adds a reshape to match the tensor shape.
self._buffer() is what executes contiguous().realize() and returns the buffer object.
Calling numpy() on that buffer object returns a 1D array (defined in tinygrad/device.py:193 via np.frombuffer).
The reshape(self.shape) at the end of Tensor.numpy() then adds dimensions to that 1D array. The added .flatten() removes those dimensions, flattening it back to a 1D array. Effectively the same as what is currently done, but less complex.

* Revert "Chunk big model files (#37134)" (#37139)

This reverts commit a941e8f78f.

* Process replay: move refs to ci-artifacts (#37049)

* rm upload

* use ci-artifacts

* sanitize

* rm ref_commit

* add ci

* handle exept

* bootstrap

* always

* fix

* replay

* keep ref_commit fork compatibility

* remove upload-only

* apply comments

* safe diffs in master

* Revert "safe diffs in master"

This reverts commit 369fccac786a67799193e9152488813c6df20414.

* continue on master diff

* Update .github/workflows/tests.yaml

Co-authored-by: Shane Smiskol <shane@smiskol.com>

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>

* fix first-interaction action inputs for v3 (#37144)

v3 renamed inputs from kebab-case to snake_case (repo-token -> repo_token,
pr-message -> pr_message). The old names were silently ignored, causing
"Input required and not supplied: issue_message" errors.

* bump create-pull-request action to v8.1.0 (#37143)

The pinned SHA was v6.0.4, which is incompatible with actions/checkout@v6
and causes a "Duplicate header: Authorization" 400 error during git
remote operations. See peter-evans/create-pull-request#4272.

* bump numpy to 2.4.2 (#37145)

* show dependency tree in weekly uv lock job (#37146)

* Revert "DM: Ford GT model" (#37148)

Revert "DM: Ford GT model (#37013)"

This reverts commit 1459d3519d.

* remove dead multilang for mici (#37150)

* ui: remove dead side button (#37151)

* rm side button

* fix

* fix

* BigButton: fix alignment and style (#37153)

* correct from bottom alignment

* temp

* fix scale animation w/ btn_y

* home settings are always 64

* cleanup

* some clean up

* make 23 const

* rev

* more

* remove azure deps (#37084)

* remove azure deps

* fix lint

* restore scripts

* [bot] Update Python packages (#37147)

* Update Python packages

* fix

* bump panda

* revert tinygrad

---------

Co-authored-by: Vehicle Researcher <user@comma.ai>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>

* remove pytest-repeat (#37156)

* BigButton: push up all content when pressed (#37157)

clean implementation

* ui.py: fix stride (#37159)

fix uii.py

* BigButton: don't round drawn content (#37158)

* unround icons

* unround rest

* Revert tgwarp again (#37161)

* Reapply "revert tg calib and opencl cleanup (#37113)" (#37115)

This reverts commit 667f3bb32f.

* revert msgq too

* msgq on master

* newline in updater error

* Remove vertical scroll bar

* Simple scroll indicator (#37162)

* scroll indicator

* 65%

* calibrate

* margin

* cleaner?

* manual clean up

* clean up

* full scroll bar

* look

* looks

* unlook

* no fade, looks good but "too much"

* clean up

* cmt

* Scroll panel: adapt to content size shrinking (#37163)

fix

* WifiManager: sort by known networks (#37164)

sort by known

* mpc tuning report: minor improvements (#37167)

---------

Co-authored-by: David <49467229+TheSecurityDev@users.noreply.github.com>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
Co-authored-by: ugtthis <142481257+ugtthis@users.noreply.github.com>
Co-authored-by: royjr <royjr96@gmail.com>
Co-authored-by: Jason Young <46612682+jyoung8607@users.noreply.github.com>
Co-authored-by: felsager <76905857+felsager@users.noreply.github.com>
Co-authored-by: Harald Schäfer <harald.the.engineer@gmail.com>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: Trey Moen <50057480+greatgitsby@users.noreply.github.com>
Co-authored-by: Trey Moen <treymoen@amazon.com>
Co-authored-by: Andi Radulescu <andi.radulescu@gmail.com>
Co-authored-by: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Co-authored-by: Daniel Koepping <elkoled@gmail.com>
Co-authored-by: ZwX1616 <zwx1616@gmail.com>
Co-authored-by: commaci-public <60409688+commaci-public@users.noreply.github.com>
Co-authored-by: Vehicle Researcher <user@comma.ai>
2026-02-11 20:35:55 -05:00
Jason Wen 52fb0b8171 Merge branch 'upstream/openpilot/master' into sync-20260211
# Conflicts:
#	.github/workflows/auto_pr_review.yaml
#	.github/workflows/tests.yaml
#	opendbc_repo
#	panda
#	selfdrive/pandad/pandad.py
#	selfdrive/test/process_replay/test_processes.py
2026-02-11 20:16:02 -05:00
felsager 5b98ea04ad mpc tuning report: minor improvements (#37167) 2026-02-11 10:21:12 -08:00
Shane Smiskol b9344af9bb WifiManager: sort by known networks (#37164)
sort by known
2026-02-11 01:23:14 -08:00
Shane Smiskol 1e0f1a8abc Scroll panel: adapt to content size shrinking (#37163)
fix
2026-02-11 01:23:00 -08:00
Shane Smiskol 8ba36b76a0 Simple scroll indicator (#37162)
* scroll indicator

* 65%

* calibrate

* margin

* cleaner?

* manual clean up

* clean up

* full scroll bar

* look

* looks

* unlook

* no fade, looks good but "too much"

* clean up

* cmt
2026-02-11 01:15:02 -08:00
Shane Smiskol 3f382d6e69 Remove vertical scroll bar 2026-02-11 00:18:02 -08:00
Shane Smiskol 10edb90ac6 newline in updater error 2026-02-10 23:27:38 -08:00
Harald Schäfer 45099e7fcd Revert tgwarp again (#37161)
* Reapply "revert tg calib and opencl cleanup (#37113)" (#37115)

This reverts commit 667f3bb32f.

* revert msgq too

* msgq on master
2026-02-10 23:12:41 -08:00
Shane Smiskol 77f069cbe5 BigButton: don't round drawn content (#37158)
* unround icons

* unround rest
2026-02-10 21:57:34 -08:00
Shane Smiskol 1070dda3ee ui.py: fix stride (#37159)
fix uii.py
2026-02-10 21:56:45 -08:00
Jason Wen decd7d4c1c [TIZI/TICI] ui: exclude angleState from fade effects when rendering torque bar (#1686) 2026-02-11 00:35:03 -05:00
Shane Smiskol fcd5897650 BigButton: push up all content when pressed (#37157)
clean implementation
2026-02-10 21:29:14 -08:00
Jason Wen dc5dfe7f3b maneuversd: keep services happy (#1685) 2026-02-11 00:27:57 -05:00
Jason Wen f9c57ff285 Revert "CI: enable macos tests (#37005)"
This reverts commit c179a3ccb7.
2026-02-11 00:20:23 -05:00
Adeeb Shihadeh f1785c245a remove pytest-repeat (#37156) 2026-02-10 20:53:02 -08:00
commaci-public 6892b62761 [bot] Update Python packages (#37147)
* Update Python packages

* fix

* bump panda

* revert tinygrad

---------

Co-authored-by: Vehicle Researcher <user@comma.ai>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-02-10 20:48:34 -08:00
Jason Wen 3d3a5de409 [TIZI/TICI] ui: dynamic ICBM status (#1684)
* [TIZI/TICI] ui: dynamic ICBM status

* wat

* make sure to init

* make sure it exists

* send it for all
2026-02-10 22:58:59 -05:00
Jason Wen bef93ecf65 [TIZI/TICI] ui: fix Developer UI orders (#1682) 2026-02-10 22:24:18 -05:00
Daniel Koepping a18ddf12eb remove azure deps (#37084)
* remove azure deps

* fix lint

* restore scripts
2026-02-10 17:51:09 -08:00
Shane Smiskol 46ae67b607 BigButton: fix alignment and style (#37153)
* correct from bottom alignment

* temp

* fix scale animation w/ btn_y

* home settings are always 64

* cleanup

* some clean up

* make 23 const

* rev

* more
2026-02-10 17:15:59 -08:00
Shane Smiskol 4d3aeaba6d ui: remove dead side button (#37151)
* rm side button

* fix

* fix
2026-02-10 15:04:36 -08:00
Shane Smiskol ba67e468ab remove dead multilang for mici (#37150) 2026-02-10 14:53:25 -08:00
ZwX1616 e946e9de0b Revert "DM: Ford GT model" (#37148)
Revert "DM: Ford GT model (#37013)"

This reverts commit 1459d3519d.
2026-02-10 13:56:07 -08:00
Adeeb Shihadeh 7d2563880a show dependency tree in weekly uv lock job (#37146) 2026-02-10 09:31:50 -08:00
Andi Radulescu 43edc51cb6 bump numpy to 2.4.2 (#37145) 2026-02-10 09:20:52 -08:00
Andi Radulescu 9476a8a7f6 bump create-pull-request action to v8.1.0 (#37143)
The pinned SHA was v6.0.4, which is incompatible with actions/checkout@v6
and causes a "Duplicate header: Authorization" 400 error during git
remote operations. See peter-evans/create-pull-request#4272.
2026-02-10 09:19:56 -08:00
Andi Radulescu 053441fbb3 fix first-interaction action inputs for v3 (#37144)
v3 renamed inputs from kebab-case to snake_case (repo-token -> repo_token,
pr-message -> pr_message). The old names were silently ignored, causing
"Input required and not supplied: issue_message" errors.
2026-02-10 09:19:37 -08:00
DevTekVE 1179273217 Revert "sunnylink: shorter timeout for websocket reconnect" (#1683)
Revert "sunnylink: shorter timeout for websocket reconnect (#1681)"

This reverts commit c51b41e96a.
2026-02-10 11:28:51 -05:00
Daniel Koepping e35a1eca99 Process replay: move refs to ci-artifacts (#37049)
* rm upload

* use ci-artifacts

* sanitize

* rm ref_commit

* add ci

* handle exept

* bootstrap

* always

* fix

* replay

* keep ref_commit fork compatibility

* remove upload-only

* apply comments

* safe diffs in master

* Revert "safe diffs in master"

This reverts commit 369fccac786a67799193e9152488813c6df20414.

* continue on master diff

* Update .github/workflows/tests.yaml

Co-authored-by: Shane Smiskol <shane@smiskol.com>

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2026-02-09 21:37:20 -08:00
Harald Schäfer 3d11e8ef36 Revert "Chunk big model files (#37134)" (#37139)
This reverts commit a941e8f78f.
2026-02-09 20:58:22 -08:00
Jason Wen c51b41e96a sunnylink: shorter timeout for websocket reconnect (#1681)
* separate

* no need

* shorten

* lint
2026-02-09 23:46:39 -05:00
James Vecellio-Grant 73f720220b modeld: simplify model run processing (#37138)
Hi! The point of this pr is to make the model run easier to read. On the latest tinygrad numpy().flatten() empirically does the same thing as the internal contiguous().realize().uop.base.buffer.numpy(). numpy() is also documented (docstrings), which can assist new contributors in learning what each potential execution does. Torq_boi or yassine, I know you want proof in the code base, so here it is. As of tinygrad commit 2f55005:

 in tinygrad_repo/tinygrad/tensor.py
Lines 316-318 (def _buffer): ensure the tenso is contiguous() and realized() before accessing the raw buffer.
Line 378 (def numpy): Wraps the buffer access and adds a reshape to match the tensor shape.
self._buffer() is what executes contiguous().realize() and returns the buffer object.
Calling numpy() on that buffer object returns a 1D array (defined in tinygrad/device.py:193 via np.frombuffer).
The reshape(self.shape) at the end of Tensor.numpy() then adds dimensions to that 1D array. The added .flatten() removes those dimensions, flattening it back to a 1D array. Effectively the same as what is currently done, but less complex.
2026-02-09 20:24:25 -08:00
Shane Smiskol a1202eaf2a ui: delay nav bar animation (#37137)
* from da bounce

* try this

* you can get it to clean up wow
2026-02-09 17:16:36 -08:00
Harald Schäfer a941e8f78f Chunk big model files (#37134)
* file chunking

* try this

* more cleanup

* cleaner
2026-02-09 15:29:50 -08:00
Andi Radulescu 9aca13cf2d remove get_mcu_type from pandad.py (#37132) 2026-02-09 09:36:04 -08:00
Jason Wen 7722d14b89 Reapply "[TIZI/TICI] ui: drive stat cache is a json already"
This reverts commit 043eab5620.
2026-02-09 02:55:17 -05:00
Jason Wen 043eab5620 Revert "[TIZI/TICI] ui: drive stat cache is a json already"
This reverts commit 51d3f0dea2.
2026-02-09 02:54:58 -05:00
Jason Wen 51d3f0dea2 [TIZI/TICI] ui: drive stat cache is a json already 2026-02-09 02:47:35 -05:00
Jason Wen 8be8bbbfdb [TIZI/TICI] ui: Trips panel (#1679)
* init

* more

* change

* exist

* better title

* adjust

* more

* seems better

* slightly more

* slightly more

* center it

* final

* move

* no bc ew

* more less
2026-02-09 02:43:28 -05:00
Nayan 1f778c8c23 Device: Retain QuickBoot state after op switch (#1333)
Device: Retain QuickBoot state after SSH Update

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
2026-02-09 00:38:39 -05:00
Nayan 981494a354 [TIZI/TICI] ui: Visuals panel (#1496)
* commaai/openpilot:d05cb31e2e916fba41ba8167030945f427fd811b

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* sunnypilot: remove Qt

* cabana: revert to stock Qt

* commaai/openpilot:5198b1b079c37742c1050f02ce0aa6dd42b038b9

* commaai/openpilot:954b567b9ba0f3d1ae57d6aa7797fa86dd92ec6e

* commaai/openpilot:7534b2a160faa683412c04c1254440e338931c5e

* sum more

* bump opendbc

* not yet

* should've been symlink'ed

* raylib says wut

* quiet mode back

* more fixes

* no more

* too extra red diff on the side

* need to bring this back

* too extra

* let's update docs here

* Revert "let's update docs here"

This reverts commit 51fe03cd51.

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* multi-button

* Lint

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* Panels. With Icons. And Scroller.

* patience, grasshopper

* more patience, grasshopper

* sp raylib preview

* fix callback

* fix ui preview

* add ui previews

* introducing ui_state_sp for py

* param to control stock vs sp ui

* better

* add ui_update callback

* better padding

* init

* revert padding to 20

* new line, who dis

* this

* support for next line multi-button

* use inline=false

* uhh

* disabled colors

* hide em all

* lambdas

* NOT inline

* final touches

* hide HIDE

* ruff.. RUFF.. WHY RUFF

* listitem -> listitemsp

* Revert "add ui_update callback"

This reverts commit 4da32cc009.

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* scroller -> scroller_tici

* scroller -> scroller_tici

* remove line separator padding

* ui: `GuiApplicationExt`

* add to readme

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* uhhh. nope

* optimizations

* I THINK this is not needed, i don't see it used on the visuals panel...

* unhide for now... Why hidden tho?

* refresh controls

* missing

* blindspot

* standstill timer

* road name toggle

* more descriptions

* more descriptions

* update desc

* param turn signals

* sort

* fix

* always show desc if not available

* should be bool

* rocket fuel

* steering arc

* lint

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
2026-02-09 00:17:34 -05:00
Jason Wen 254f55ac15 [TIZI/TICI] ui: Hide vEgo and True vEgo (#1678) 2026-02-08 20:42:23 -05:00
James Vecellio-Grant 96b58024ab [MICI] ui: driving models selector (#1574)
* ui: models mici

* Update models.py

* Update models.py

* sync

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-08 19:54:33 -05:00
Jason Wen a9229e11a0 [TIZI/TICI] ui: standstill timer (#1677)
* standstill timer

* final
2026-02-08 19:40:04 -05:00
Jason Wen 020f503364 [TIZI/TICI] ui: Green Light and Lead Departure elements (#1676)
* init

* big for now

* only adjust for right dev ui for now

* final

* final final
2026-02-08 19:14:19 -05:00
Jason Wen c274dba36e [TIZI/TICI] ui: Smart Cruise Control elements (#1675)
* init

* punch

* lower

* colors
2026-02-08 18:28:36 -05:00
royjr 35c87a1519 [TIZI/TICI] ui: steering arc (#1628)
* init

* lint

* add toggle

* Update params_keys.h

* Update params_metadata.json

* Update params_keys.h

* bool

* decouple

* no

* make it perfect

* fade it

* only with torque bar

* dynamic

* in another PR

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-08 17:00:37 -05:00
Adeeb Shihadeh ac087d085e Build vendored artifacts in CI (#37127)
* Build vendored artifacts in CI

* parallel

* deterministic

* fix up

* fix gitignores

* lil more

* lil more consistency
2026-02-08 09:59:33 -08:00
Adeeb Shihadeh 46d65095af CI: garbage collect tmp jenkins branches (#37125) 2026-02-07 23:04:01 -08:00
github-actions[bot] 81bd8aa0e2 [bot] Update Python packages (#1662)
* Update Python packages

* bump

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-02-08 01:03:16 -05:00
Adeeb Shihadeh 667f3bb32f Revert "revert tg calib and opencl cleanup (#37113)" (#37115)
* Revert "revert tg calib and opencl cleanup (#37113)"

This reverts commit 51312afd3d.

* power draw is a lil higher

* just don't miss a cycle

* fix warp targets

* fix tinygrad dep
2026-02-07 21:36:44 -08:00
royjr c908189e73 ui: use correct signals while using PID with Developer UI (#1674)
* only if angleState

* pidState element
2026-02-08 00:32:12 -05:00
Adeeb Shihadeh c65cf18c75 Better memory usage debugging (#37120) 2026-02-07 21:00:56 -08:00
Adeeb Shihadeh 55a31d7657 replace tabulate with simple helper (#37122) 2026-02-07 18:27:16 -08:00
Adeeb Shihadeh ac17c35cfe bridge: move ZMQ handling over (#37118) 2026-02-07 15:18:00 -08:00
David bcb13a7229 ui diff replay: remove unused frame_data list for individual frame display (#37117)
Remove unused base64 encoding and simplify frame data handling in diff video report
2026-02-07 14:19:08 -08:00
Adeeb Shihadeh 0ce28803ec gitignore .context/ 2026-02-07 12:20:34 -08:00
Trey Moen db8cd9f411 fix: route fetch metadata when first log isnt uploaded (#37114)
* fix: route fetch metadata when first log isnt uploaded

* default

* simple

---------

Co-authored-by: Trey Moen <treymoen@amazon.com>
2026-02-07 11:52:28 -08:00
Harald Schäfer 51312afd3d revert tg calib and opencl cleanup (#37113)
* Revert "Remove all the OpenCL (#37105)"

This reverts commit d5cbb89d84.

* Revert "rm common/mat.h"

This reverts commit 4ce701150a.

* Revert "Calibrate in tg (#36621)"

This reverts commit 593c3a0c8e.
2026-02-07 09:10:29 -08:00
Shane Smiskol efc23644c7 Delete less dialogs (#37111)
* try

* revert

* this is fine
2026-02-06 22:59:05 -08:00
Shane Smiskol e531f844f6 bump opendbc (#37108)
bump
2026-02-06 20:15:12 -08:00
Shane Smiskol 46f74753cd clip: use wrap_text helper (#37102)
* they are same

* no duplication!

* rm rstrip
2026-02-06 17:11:17 -08:00
Adeeb Shihadeh d5cbb89d84 Remove all the OpenCL (#37105)
* Remove all the OpenCL

* lil more

* bump msgq
2026-02-06 16:36:47 -08:00
Adeeb Shihadeh 4ce701150a rm common/mat.h 2026-02-06 16:06:16 -08:00
Shane Smiskol 96fded0399 clip: clean up imports (#37104)
* wtf is this

* don't break import timing

* they are the same

* clean up

* good catch
2026-02-06 15:13:08 -08:00
felsager 12597856da long mpc: state name before subscript (#37101) 2026-02-06 14:26:20 -08:00
Harald Schäfer 593c3a0c8e Calibrate in tg (#36621)
* squash

* bump tg

* fix linmt

* Ready to merge

* cleaner

* match modeld

* more dead stuff
2026-02-06 14:13:46 -08:00
felsager 187d3a079c long_mpc: use log.capnp source enum (#37096) 2026-02-06 13:36:51 -08:00
felsager 9755520b87 longitudinal mpc tuning report: add sinusoidal oscillation scenario (#37100) 2026-02-06 11:30:49 -08:00
felsager 7099bd18e3 longitudinal mpc tuning: behind if main (#37099) 2026-02-06 10:35:54 -08:00
David cb670c2c3d clips: improve overlays for mici (#37088)
* adjust overlay sizes and wrap metadata text for mici

* comment

* adjust overlay rendering to dynamically calculate line height for wrapped metadata text

* render time first so we can use width in margin calculation

* update comment (to retry failed CI actually)

* increase metadata size on mici
2026-02-06 09:58:30 -08:00
Shane Smiskol f5b84e74f4 fix mici setup int enum 2026-02-05 23:42:16 -08:00
Shane Smiskol 2b8e887e44 mici setup: remove unused functions 2026-02-05 23:39:22 -08:00
Harald Schäfer 64f74dad27 Revert "long_mpc: use log.capnp source enum instead of list" (#37095)
Revert "long_mpc: use log.capnp source enum instead of list (#37093)"

This reverts commit 7e959c5a3e.
2026-02-05 16:23:28 -08:00
felsager 7e959c5a3e long_mpc: use log.capnp source enum instead of list (#37093) 2026-02-05 15:55:03 -08:00
Jason Young 28795d3065 bump opendbc (#37091) 2026-02-05 16:30:03 -05:00
royjr 8aed5a1a89 translations: remove arabic (#37087)
* remove arabic

* more
2026-02-05 09:28:01 -08:00
James Vecellio-Grant 4d65c52e6d modeld_v2: refactor abstract class to support off-policy models (#1672)
* modeld_v2: refactor abstract class to support off-policy models.

* whoops

* bump
2026-02-05 08:35:57 -05:00
Shane Smiskol a5c973be89 NavBar: fix no show animation (#37090)
* 1.5 not enough time on small screen

* ohhhh

* clean up
2026-02-04 23:52:59 -08:00
ugtthis 39dcc88330 UI: only show onroad_fade.png when engaged (#37051)
* only show when engaged

* retrigger CI

* fade animation 0.1

* nl

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2026-02-04 23:03:01 -08:00
Shane Smiskol fc6afd5ab8 Network menu improvements (#37077)
* try this

* that's handy

* todo, not sure what happens here

* set_text

* normalize

* scroll wifi

* clean up

* more

* better check
2026-02-04 22:58:16 -08:00
Shane Smiskol 177a1a3c8b BigButton: use UnifiedLabel (#37086)
* BigButton: remove unused scrolling

* start

* debug

* stash

* actually removing the hardcoded size for multioption fixes it

* back

* cursor does sub label

* clean  up

* more

* more

* try this for now

* nick suggest

* clean up

* more

* more
2026-02-04 22:25:28 -08:00
Shane Smiskol 1979a6d8e8 BigButton: remove unused scrolling (#37085)
* BigButton: remove unused scrolling

* clean up
2026-02-04 19:30:20 -08:00
Shane Smiskol 944c23f369 Stock LKAS: remove permanent alert (#37083)
rm perm
2026-02-04 17:06:11 -08:00
Shane Smiskol 2230933d4b Back to tethering BigButton (#37082)
Back to tethering big button
2026-02-04 16:38:24 -08:00
Jason Wen 3ea474dd58 tools: fix Python version comparison using normalized semantic version format (#37075) 2026-02-04 16:31:44 -08:00
Shane Smiskol 8879d481e5 comma four: new keyboard enter button (#37072)
* works

* enter dis

* clean up

* clean up

* no debug

* useless

* poadding
2026-02-04 16:04:49 -08:00
David 5e35feb3ab clips: allow mici UI (now default) (#37070)
fix: make big false by default and remove assertion
2026-02-04 11:25:09 -08:00
Jason Wen 5c12a7cfc3 Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1667) 2026-02-04 01:03:20 -05:00
Jason Wen f309be9038 DEC: refactor mode conditions with Experimental Mode 2026-02-04 00:31:55 -05:00
Jason Wen 959ebd22d8 Merge branch 'upstream/openpilot/master' into sync-20260201
# Conflicts:
#	.github/workflows/auto_pr_review.yaml
#	.github/workflows/docs.yaml
#	.github/workflows/repo-maintenance.yaml
#	.gitignore
#	docs/CARS.md
#	opendbc_repo
#	panda
#	pyproject.toml
#	selfdrive/controls/lib/longitudinal_planner.py
#	selfdrive/test/process_replay/ref_commit
#	tinygrad_repo
2026-02-04 00:14:58 -05:00
YassineYousfi 5b6436a90c CD210 model (#37050)
a27b3122-733e-4a65-938b-acfebebbe5e8/100
2026-02-03 19:14:02 -08:00
Harald Schäfer ee7601ae9d long planner: Min(stopping) is also important (#37074)
Min(stopping) is also important
2026-02-03 15:55:13 -08:00
Shane Smiskol 54cf8d6a5e four keyboard: fix keys lagging behind parent widget (#37073)
* fix keys lagging behind

* use parent rect

* use parent rect

* cmt
2026-02-03 15:55:05 -08:00
Harald Schäfer aac90dd11b Bump tg (#37069)
bump tg
2026-02-03 13:59:45 -08:00
Shane Smiskol 85b9f8962e Clean up four keyboard text rects (#37068)
* start clean up

* rm

* not really needed

* more

* clean up
2026-02-02 22:32:52 -08:00
Jason Wen 8f970bcb99 Reapply "latcontrol_torque: lower kp and lower friction threshold (commaai/openpilot#36619)" (#1581) (#1669)
* Reapply "latcontrol_torque: lower kp and lower friction threshold (commaai/openpilot#36619)" (#1581)

This reverts commit 7560497f

* bump
2026-02-02 22:13:37 -05:00
Shane Smiskol a668bc9eda comma four setup improvements (#37066)
* always check, no flickering from has inter -> waiting -> has inter from the reset

* 1s interval. i see read timeouts at 0.5s sometimes

* clean up

* cursor

* Revert "cursor"

This reverts commit 13ec6312aa7f71b58771f8789456e97c4481856a.

* clean up
2026-02-02 16:58:45 -08:00
Trey Moen fd50941cff chore: bump minimum Python version to 3.12.3 (#37052) 2026-02-02 08:13:49 -08:00
Adeeb Shihadeh 831f2396d9 bump opendbc 2026-02-02 08:08:09 -08:00
Adeeb Shihadeh 5fc4c2b25c ubloxd: remove kaitai (#37055)
* rm kaitai

* lil less

* bs

* lil less

* lil less
2026-02-01 20:00:55 -08:00
Adeeb Shihadeh b03e7821d4 replace smbus2 package with minimal implementation (#37061)
* replace smbus2 package with minimal implementation

* cleanup

* fix up
2026-02-01 17:26:58 -08:00
Adeeb Shihadeh 35241a5fb8 cleanup pyproject (#37060)
* cleanup pyproject

* lil more

* fix warning
2026-02-01 16:03:18 -08:00
Adeeb Shihadeh 5da6bf9e03 rm pytools package (#37059) 2026-02-01 15:46:40 -08:00
Adeeb Shihadeh 948d42b3e5 rm pyopencl package (#37058)
rm pyopencl
2026-02-01 15:42:42 -08:00
Adeeb Shihadeh 422de59898 acados: strip future-fstrings declaration (#37057)
* Revert "rm future-fstrings package (#37056)"

This reverts commit 7a990b99f7.

* Reapply "rm future-fstrings package (#37056)"

This reverts commit 8b93f6646eed6863ad67b9bab558d305ecb8b7b4.

* strip it

* cleanup
2026-02-01 15:24:42 -08:00
Adeeb Shihadeh 7a990b99f7 rm future-fstrings package (#37056) 2026-02-01 15:07:22 -08:00
Adeeb Shihadeh 0a84b00406 fix up status for in progress builds 2026-02-01 13:36:55 -08:00
Trey Moen e76e1e500c clips: use AugmentedRoadView instead of MainLayout (#37053)
Render only the road view in clips rather than the full main layout,
matching the updated UI module structure.
2026-02-01 13:21:00 -08:00
Adeeb Shihadeh cd70e23dc3 clips: direct rendering with raylib (#36935)
* good clips

* replace

* fix

* fix font

* lil more
2026-01-31 20:15:23 -08:00
Pádraic Slattery 1dfef69a3c chore: Update outdated GitHub Actions versions (#37020)
* chore: Update outdated GitHub Actions versions

* just the github ones

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-01-31 18:37:00 -08:00
Adeeb Shihadeh c35df583a5 tools: enable log caching by default (#36962) 2026-01-31 15:52:50 -08:00
King Art db3df61c34 fix non-determinism in modeld build (#37042)
* fix non-determinism in selfservice model build

also trim down model compile dependencies to the minimum required

* Apply suggestions from code review

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2026-01-30 17:16:56 -08:00
Shane Smiskol 32f0a2cbbc bump opendbc (#37046)
bump
2026-01-30 00:30:11 -08:00
Shane Smiskol 569099eb70 update docs 2026-01-30 00:09:44 -08:00
Shane Smiskol df7f426405 bump opendbc (#37043)
* bump opendbc

* update refs
2026-01-30 00:09:19 -08:00
T3d bddd20c425 Complete french translations in app_fr.po (#37023) 2026-01-29 10:36:51 -08:00
Shane Smiskol e89e4407c5 Tweak stockLkas alert (#37040)
* stockLkas alert is orange, small, mid prio, ldw vis alert

* copy exactly from existing ldw alert with prompt sound, black alert
2026-01-28 19:50:53 -08:00
Shane Smiskol d849d6f1d7 mici keyboard: bold SmallKey (#37035)
bold SmallKey
2026-01-27 21:28:50 -08:00
Shane Smiskol 0b958f7c9a onroad: fill bookmark icon when activated (#37034)
* bookmark fill

* and here's what i would have done

* add
2026-01-27 19:59:25 -08:00
felsager 2fc10e8299 Maneuver: log drel and use it in tuning report (#37033) 2026-01-27 17:15:39 -08:00
Shane Smiskol bf8cae5e7c mici ui: new icons (#37021)
* new icons

* add missing

* fixed tethering big icon, size of pairing comma, buttons now use 90percent white

* why o why

* newline

* fancy

* already default

* fixes

* add firehose

* ltl

* fix caps lock icon

---------

Co-authored-by: nickorie <nickorie@gmail.com>
2026-01-27 16:20:32 -08:00
Shane Smiskol 93015c1c17 ui: fix button label color (#37031)
label color
2026-01-27 15:40:09 -08:00
felsager 97329e46ae longitudinal maneuvers: add report for longitudinal mpc tuning (#37030) 2026-01-26 16:07:13 -08:00
felsager d76f756f42 long_mpc: simplify longitudinal planner by removing "modes" (#37014) 2026-01-26 15:02:57 -08:00
commaci-public 71a418d166 [bot] Update Python packages (#37028)
Update Python packages

Co-authored-by: Vehicle Researcher <user@comma.ai>
2026-01-26 09:14:57 -08:00
Kumar fb58e8f1f7 [TIZI/TICI] ui: Speed Limit (#1653)
* sla ui

remove dub

debug ahead

postition

maybe

posttion

think

* sunny will be mad

Reapply "test"

This reverts commit 7a35fd3053425b06c1e4cebf68b6c9676eb6e279.

Revert "test"

This reverts commit 1a79155d3cfc8e6e09a6fc38d13747883745ef6a.

test

* road name

* Revert "road name"

This reverts commit 02e69b008603c357f14b4793e8fc893e00b3d3a0.

* decouple

* dial it in

* match cur

* no magic numbers

* cleanup

* more cleanup

* match

* always draw ahead

* Revert "always draw ahead"

This reverts commit f695e00078.

* new

* type

* Revert "type"

This reverts commit 2dafa02407.

* default

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-26 01:54:42 -05:00
Candy0707 5dea009113 [TIZI/TICI] ui: Fix misaligned turn signals and blindspot indicators with sidebar (#1659)
* Fix Bug Turn and blind

* use separate y coord for left and right signals

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-24 22:50:39 -05:00
Adeeb Shihadeh de024fd4a7 pandad: pure Python capnp helpers (#37025)
* pandad: pure Python capnp helpers

* cleanup
2026-01-24 12:02:33 -08:00
Adeeb Shihadeh 7c90c0669a script for CI results (#37024) 2026-01-24 10:51:41 -08:00
dzid26 fc4a0fb944 [TIZI/TICI] ui: Blue "Exit Always Offroad" button (#1655)
Blue "Exit Always Offroad" button

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-24 02:11:38 -05:00
Kumar 5c01365125 [TIZI/TICI] ui: Road Name (#1654)
* road name

* decouple

* rename

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-24 02:04:42 -05:00
Kumar d7770ad55c [MICI] ui: display blindspot indicators when available (#1525)
* always bsm

* c4 bsm for c3x

* position

* sperate

* sp dir

* revert

* decouple

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-24 01:36:47 -05:00
Jason Wen 1bd3255f14 [TIZI/TICI] ui: MICI style blindspot indicators (#1657)
* introduce blinker

* add blind spot

* bigger

* nah

* lint
2026-01-24 01:04:25 -05:00
Kumar 76d50df466 [TIZI/TICI] ui: MICI style turn signals (#1504)
* mici turn signal for c3x

* sp dir

* decouple

* more

* ty

* refactor and slim down

* bigger

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-24 00:46:00 -05:00
Kumar 8c36739ebd [TIZI/TICI] ui: Rocket Fuel (#1337)
* rocket

* raylib

* extra

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-23 23:27:12 -05:00
Kacper Rączy 560ed80123 tools: seekable URLFile (#37022)
* Make URLFile seekable

* Return value in seek
2026-01-24 04:04:54 +00:00
Nayan 2e788ae54d [TIZI/TICI] ui: Steering panel (#1540)
* commaai/openpilot:d05cb31e2e916fba41ba8167030945f427fd811b

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* sunnypilot: remove Qt

* cabana: revert to stock Qt

* commaai/openpilot:5198b1b079c37742c1050f02ce0aa6dd42b038b9

* commaai/openpilot:954b567b9ba0f3d1ae57d6aa7797fa86dd92ec6e

* commaai/openpilot:7534b2a160faa683412c04c1254440e338931c5e

* sum more

* bump opendbc

* not yet

* should've been symlink'ed

* raylib says wut

* quiet mode back

* more fixes

* no more

* too extra red diff on the side

* need to bring this back

* too extra

* let's update docs here

* Revert "let's update docs here"

This reverts commit 51fe03cd51.

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* multi-button

* Lint

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* Panels. With Icons. And Scroller.

* patience, grasshopper

* more patience, grasshopper

* sp raylib preview

* fix callback

* fix ui preview

* add ui previews

* Option Control

* Need this

* sunnylink state

* introducing ui_state_sp for py

* poll from ui_state_sp

* cloudlog & ruff

* param to control stock vs sp ui

* better

* sponsor & pairing qr

* init panel elements

* backup & restore

* fruit loops

* update

* enable, disable, enable, disable

* handle layout updates

* not needed

* add ui_update callback

* change it up

* better padding

* this

* support for next line multi-button

* uhh

* disabled colors

* better

* listitem -> listitemsp

* listitem -> listitemsp

* Revert "add ui_update callback"

This reverts commit 4da32cc009.

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* simplify

* I. SAID. SIMPLIFY.

* AAARGGGGGG.....

* option control value fix

* left button

* more init

* simple_button, yay

* simple_button, yay

* more more init

* scroller -> scroller_tici

* scroller -> scroller_tici

* ui: `GuiApplicationExt`

* simple button

* simple button

* add to readme

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* optimizations

* change order

* subpanels

* lane change timer

* update toggles

* update toggles

* add cp_sp to ui_state

* mads

* add cp_sp to ui_state_sp

* fix ui crash

* update params

* ui_state changes

* descriptions

* Update scroller.py

* wrong pr

* listen nessa, yes nessa

* i've got something to confessa

* some bs

* # Conflicts:
#	selfdrive/ui/sunnypilot/layouts/settings/steering.py
#	selfdrive/ui/sunnypilot/layouts/settings/vehicle.py
#	system/ui/sunnypilot/widgets/list_view.py

* sine

* more

* Delete selfdrive/ui/sunnypilot/layouts/vehicle_settings/platform_selector.py

* Update styles.py

* allow sunnylink

* nah

* more

* sync

* lint

* revert

* button is always shown, just disabled if off

* revert

* Fix SimpleButtonActionSP not respecting enabled state

* some changes

* new pr

* some more

* ui: `ButtonSP`

* slight cleanup

* fixes

* no

* fix

* much better

* ui: `LineSeparatorSP`

* ui: add `inline` to `option_item_sp`

* small cleanup mads

* lane change

* allow changing title

* torque settings init

* lont

* more logic

* import directly

* more

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
Co-authored-by: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Co-authored-by: discountchubbs <alexgrant990@gmail.com>
2026-01-23 22:55:50 -05:00
Jason Wen a0a5c9b9ca ui: add set_title and improve state updates in ListViewSP (#1656) 2026-01-23 22:49:10 -05:00
Matt Purnell 12220ec82d cereal: update msgq imports (#36833)
Update outdated reference

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-01-23 17:11:23 -08:00
Shane Smiskol 3715fe85aa bump opendbc (#37019) 2026-01-23 00:55:12 -08:00
Shane Smiskol ba6e5f125d Fix bridge w/ ZMQ (#37018)
* fix

* can also do this

* 1 less +lines but more diff - Revert "can also do this"

This reverts commit 8e18218099af6d3bc852d8ef0069b80d9322d6ca.
2026-01-23 00:24:15 -08:00
ZwX1616 1459d3519d DM: Ford GT model (#37013)
* b483cec4-7816-4570-a774-be3a2c100098/50

* shipfest

* da4b8724-8998-45da-aa36-d8fb390492b9

* revert

* typo

* deprecates
2026-01-22 18:41:08 -08:00
felsager c9cfe2c727 LatcontrolTorque: move jerk calculation and filtering outside if else (#37011) 2026-01-21 12:32:56 -08:00
Jason Wen 27a8837422 Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1645) 2026-01-20 22:32:31 -05:00
felsager bc979ea6aa Latcontrol torque test: ensure desired lateral accel buffer is consistent (#37004) 2026-01-20 16:16:38 -08:00
Adeeb Shihadeh 79472cdf83 Revert "docs: comma 3X to comma four (#37009)"
This reverts commit a7dfd36c00.
2026-01-20 16:04:05 -08:00
Harald Schäfer adf6f28ebf LatcontrolTorque: always fill buffer (#36991) 2026-01-20 15:34:57 -08:00
Lukas a7dfd36c00 docs: comma 3X to comma four (#37009)
* comma 3X -> comma four

* add comma four ports image
2026-01-20 15:15:12 -08:00
Jason Wen 53327edb50 Merge branch 'upstream/openpilot/master' into sync-20260111
# Conflicts:
#	common/api.py
#	docs/CARS.md
#	opendbc_repo
#	panda
#	scripts/lint/lint.sh
#	selfdrive/car/car_specific.py
#	selfdrive/car/card.py
#	selfdrive/test/process_replay/ref_commit
#	system/hardware/hardwared.py
#	tinygrad_repo
2026-01-20 07:29:25 -05:00
Adeeb Shihadeh 6c7f3751e7 camerad: calculate buffer sizes with VENUS helpers (#37006)
* Revert "NV12 buffer shape helpers (#36683)"

This reverts commit 13efc421c4.

* camerad: calculate buffer sizes with VENUS helpers

* copy header:

* assert aligned

* python nv12 info

* debug

* handle padding

* use the helper
2026-01-19 17:18:22 -08:00
Mauricio Alvarez Leon c179a3ccb7 CI: enable macos tests (#37005)
enable macos tests
2026-01-19 16:45:45 -08:00
Harald Schäfer 13efc421c4 NV12 buffer shape helpers (#36683)
* Give this a try

* can codex debug?

* simpler

* Revert "simpler"

This reverts commit 572335008c1c719aa985d14bd740253ff94b94a9.

* better

* cleanup

* try again

* tie

* try this

* try this

* do tests fail without this?

* doesn't seem needed

* unused

* don't need duplicate

* passes CI?

* try this

* try this

* try this

* I don't understand this, so back to before

* keep that alignment

* set uv_height

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-01-19 16:27:41 -08:00
Adeeb Shihadeh 10db1edc7f merge common.util and common.utils (#36951)
* common: merge common.util and common.utils

* cleanup

* cleanup
2026-01-19 15:50:00 -08:00
Adeeb Shihadeh 039b85f355 bump opendbc (#37003)
* bump opendbc

* bump

* bump

* bump

* bump bump bump
2026-01-19 15:33:23 -08:00
Harald Schäfer 0b41b42f7b WMI model 🍉 (#36798)
* 1791ea0f-8667-4e0b-be73-084d912f6c4c/100

* eab53871-1f8c-45be-9a98-f6b3dd6a0adc/100

* dd075c9d-0c49-402e-b4f2-9adbe5301c84/100

* e8b5b1b0-2d37-4b62-bd39-21ff0d08ee68/100

* 1aff00c7-06c5-46a6-8a79-7e56f77d81bf/100

* 3547a2cc-1699-4e7d-a2ab-4eb87d0b8684/100

* 849aa9fb-dae6-4604-923e-050883def218/100

* 0e0f6dd2-96dc-4f34-a7cd-63bccc2f5616/100

* 887f923b-7e79-43c6-8f1f-053e1490f859/100

* 1fa82260-1171-4db5-9968-d34ce2e14694/100

* Revert "1fa82260-1171-4db5-9968-d34ce2e14694/100"

This reverts commit 855f5e4ddefd69a20cc4e9da004eb53f3e00d950.

* a27b3122-733e-4a65-938b-acfebebbe5e8/100

---------

Co-authored-by: Yassine Yousfi <yyousfi1@binghamton.edu>
2026-01-19 11:48:06 -08:00
commaci-public a46ff01cab [bot] Update Python packages (#36966)
* Update Python packages

* ty fixes

---------

Co-authored-by: Vehicle Researcher <user@comma.ai>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-01-19 11:39:21 -08:00
Nayan e7b6e62b82 [TIZI/TICI] ui: expose Interactivity Timeout option (#1497)
* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* Panels. With Icons. And Scroller.

* patience, grasshopper

* more patience, grasshopper

* sp raylib preview

* fix callback

* fix ui preview

* add ui previews

* Option Control

* Need this

* introducing ui_state_sp for py

* param to control stock vs sp ui

* better

* add ui_update callback

* better padding

* this

* listitem -> listitemsp

* Revert "add ui_update callback"

This reverts commit 4da32cc009.

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* simplify

* I. SAID. SIMPLIFY.

* AAARGGGGGG.....

* init

* option control value fix

* add all controls

* hide all controls

* lint

* scroller -> scroller_tici

* scroller -> scroller_tici

* ui: `GuiApplicationExt`

* add to readme

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* optimizations

* Removed hide for now

* refresh controls

* ugh

* global brightness

* initialize

* inline everything again

* change name

* Onroad Brightness reimpl

* Custom Interactive Timeout reimpl

* Global Brightness Override reimpl

* keep stock

* ui: Custom Interactive Timeout

* rename

* ui: Customizable Onroad Brightness

* lint

* lint

* Revert "Global Brightness Override reimpl"

This reverts commit 53522da4f8.

* Revert "Custom Interactive Timeout reimpl"

This reverts commit 459863a9bb.

* Revert "Onroad Brightness reimpl"

This reverts commit 4092d23e57.

* fixes

* lint

* reset on show/hide

* reset on show/hide for mici

* only set if true

* wrong var

* try this out

* use clear

* starts cleanup

* wake for all visual alerts and handle timeouts

* fixup: wake for all visual alerts and handle timeouts

* handle always wake if there's an event properly

* some

* slightly more

* need this back

* Reapply "ui: Global Brightness Override (#1579)"

This reverts commit a0c10be1ff.

* do not touch light sensor logic

* override properly and clip to 30% minimum

* wrap

* lint

* update immediately

* read

* max global brightness

* rename

* gotta do it for mici too lol

* update metadata

* desc

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
2026-01-19 01:42:24 -05:00
Jason Wen 3662a8e962 ui: Customizable Onroad Brightness (#1641)
* ui: Customizable Onroad Brightness

* fixes

* lint

* reset on show/hide

* reset on show/hide for mici

* only set if true

* wrong var

* try this out

* use clear

* starts cleanup

* wake for all visual alerts and handle timeouts

* fixup: wake for all visual alerts and handle timeouts

* handle always wake if there's an event properly

* some

* slightly more

* need this back

* Reapply "ui: Global Brightness Override (#1579)"

This reverts commit a0c10be1ff.

* do not touch light sensor logic

* override properly and clip to 30% minimum

* wrap

* lint

* update immediately

* read

* max global brightness

* rename

* gotta do it for mici too lol

* revert

* Revert "revert"

This reverts commit 121a082de1.

* no more

* ui

* more

* intenum

* simplify ONROAD_BRIGHTNESS_TIMER_VALUES

* no more toggle

* 15 seconds countdown for auto dark regardless

* auto dark refinement

* only consume if expired

* immediately set

* rename

* update sl metadata

* no more

---------

Co-authored-by: nayan <nayan8teen@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
2026-01-19 01:26:16 -05:00
Copilot 49b6ef7f48 SL: Fix MaxTimeOffroad metadata unit from seconds to minutes (#1650)
* Initial plan

* Fix MaxTimeOffroad metadata unit from seconds to minutes

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>
2026-01-17 14:36:19 -05:00
Matt Purnell 1f9efd9311 transformations: move Cython to pure Python (#36830)
* Remove cython for transformations

* Add new test

* Switch back to program to fix mac builds

* Convert to Python instead

* Fix failing builds

* lint

* Implement conversion in pure python/numpy

* Add more tests

* Fix bugs in tests
2026-01-16 22:31:26 -08:00
Shane Smiskol 7f8dbf24e7 Cabana: fix for internal source (#36998)
* fix for internal sources from cursor

* clean up

* more

* not needed

* clean up

* sure
2026-01-15 17:18:40 -08:00
Shane Smiskol 5e4b88201e Toyota: whitelist hybrids for standstill resume behaviour (#36996)
tioyota
2026-01-15 14:38:43 -08:00
Adeeb Shihadeh 1252188b4b sensord: tighten temperature threshold (#36994)
* sensord: tighten temperature threshold

* lil more
2026-01-13 14:33:13 -08:00
DevTekVE a0c10be1ff Revert "ui: Global Brightness Override (#1579)"
This reverts commit 1eb82fcc
2026-01-10 21:24:44 +01:00
Adeeb Shihadeh 15d3a166f7 enable pyopencl on arm64 (#36990) 2026-01-09 20:49:14 -08:00
Nayan a58db66a98 sunnylink: add units to param metadata (#1643)
add units
2026-01-09 18:40:09 -05:00
Harald Schäfer f51c2aeced Modeld: less lat smoothing (#36987)
* lat is plenty smooth!

* fix
2026-01-09 15:04:33 -08:00
Harald Schäfer 3edb3243f6 SC driving (#36986)
f1d30a23-4122-400a-80a6-557502284c36/200
2026-01-09 09:16:57 -08:00
YassineYousfi c693bc1247 MacroStiff Model 🟥🟩🟦🟨 (#36972)
* 8c06e95e-d7c0-4fd9-ba02-9f0b6848785e/400

* test

* test

* test now
2026-01-05 16:14:05 -08:00
Adeeb Shihadeh 5d3ab260e1 welcome lexus ls 2026-01-05 10:15:20 -08:00
Jason Young ea64c4c0ae VW: Enable torqued (#36983) 2026-01-04 21:35:13 -05:00
Adeeb Shihadeh 84bce8ae02 rm pygame (#36982)
* rm pygame

* lil more

* cleanup

* lil more
2026-01-04 17:52:10 -08:00
Jason Young 3c5974930a cleanup SecOC release gating (#36980) 2026-01-04 17:09:26 -05:00
Adeeb Shihadeh be854df32d remove unused dbus-next package (#36979) 2026-01-04 13:46:30 -08:00
Jason Wen e5e56614c9 ui: Customizable Interactive Timeout (#1640)
* ui: Custom Interactive Timeout

* rename

* lint
2026-01-04 00:33:32 -05:00
Nayan 1eb82fcc85 ui: Global Brightness Override (#1579)
* global brightness

* initialize

* keep stock

* lint

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-04 00:27:22 -05:00
Copilot 987f53e69a [TIZI/TICI] ui: sunnylink status on sidebar (#1638)
* Initial plan

* feat: add sunnylink status metric

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: extract sidebar constants

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* refactor: guard metric spacing

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: clarify sunnylink helpers

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* refactor: guard metric spacing edge cases

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: simplify spacing guards

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: normalize sunnylink params

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: harden sunnylink param parsing

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: add param decode helper

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: simplify sidebar metric spacing

Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>

* chore: update sunnylink status color logic for improved clarity

* sunnylink: update status handling to reflect offline state and improve fault indication

sunnylink: enhance status handling with temporary fault indication

* sunnylink: enhance status update logic for improved accuracy and clarity

* make it int

* Ugly with zero value, but done. Now we only need to remember to check the new sidebar if the old sidebar ever changes

* Revert "Ugly with zero value, but done. Now we only need to remember to check the new sidebar if the old sidebar ever changes"

This reverts commit 2d3b740e38.

* decouple

* no bad bot

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: devtekve <7696966+devtekve@users.noreply.github.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-03 21:01:21 -05:00
github-actions[bot] 9a04a5eaae [bot] Update Python packages (#1565)
* Update Python packages

* no

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-03 15:54:55 -05:00
Nayan 50b8ae9e09 sunnylink: update params metadata (#1636)
* sunnylink model controls

* cleanup more controls

* update verbiage

Co-authored-by: DevTekVE <devtekve@gmail.com>

---------

Co-authored-by: DevTekVE <devtekve@gmail.com>
2026-01-03 08:35:02 -05:00
YassineYousfi adbf68f771 FrameReader: add hwaccel arg and clear frames_cache (#36974) 2026-01-02 11:29:45 -08:00
YassineYousfi f62177a827 FrameReader: use hwaccel auto (#36973)
* FrameReader: use hwaccel auto

* rm main block
2026-01-01 19:06:31 -08:00
Alexandre Nobuharu Sato bb40d161e8 Add back badges for keep multilanguage support (#36967) 2026-01-01 15:13:18 -08:00
James Vecellio-Grant a30fc9bcd2 modeld: configurable camera offset (#1614)
* modeld: configurable camera offset

Negative Values: Shears the image to the left, moving the models center to the Right.

Positive Value: Shears the image to the right, moving the models center to the Left.

* modeld: camera offset class

* verify zero offset I @ A = A

* slithered and slunked

* Update params_metadata.json

* wait

* Update model_renderer.py

* Update model_renderer.py

* requested changes

* stricter

* Update model_renderer.py

* more

* return default

* Update params_metadata.json

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2026-01-01 14:23:01 -05:00
Shane Smiskol 84b1f363e4 Alert for stock LKAS (#36969)
* alert stock lkas

* high

* i didn't do this
2025-12-31 12:43:36 -08:00
Kumar 19a7d1d5d7 [TIZI/TICI] ui: update dmoji position and Developer UI adjustments (#1601)
* ui: improve layout and centering of bottom developer UI elements

* int

* less is more, y'all

* always show actual lat for all cars

* lint

* perfect

* cleanup

* too long

* inherit

* remove unused

* inir

* need to fix

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-31 00:27:53 -05:00
Jason Wen fb8f46cba9 Reimplement sunnypilot Terms of Service & sunnylink Consent Screens (#1633)
* tos reimpl

* nah

* simpler

* check consent on sunnylink panel - mici

* slight cleanup

* rename

* keep it off

* decouple

* more rename

* more decouple

* a bit more

* fix state

* decouple more

* a bit more

* wrong type

* rearrange

* don't do that

* final

* lint

* include

* more

---------

Co-authored-by: nayan <nayan8teen@gmail.com>
2025-12-31 00:08:36 -05:00
Nayan 70386c6b00 ui: fix Always Offroad button visibility (#1632)
always offroad button fix
2025-12-30 23:20:20 -05:00
James Vecellio-Grant edeede5e82 modeld_v2: conditional model compilation for metadrive testing (#1623)
* modeld_v2: conditional model compilation for PC

* full send

* shebang

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-29 22:03:08 -05:00
Adeeb Shihadeh a5348b8679 crcmod -> crcmod-plus (#36968) 2025-12-29 16:41:52 -08:00
James Vecellio-Grant 6df313b974 modeld_v2: remove dead test (#1621)
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-29 17:01:58 -05:00
James Vecellio-Grant 9442bc9aec modeld_v2: planplus model tuning (#1620)
* modeld: planplus model tuning

* little more

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-29 16:55:39 -05:00
Adeeb Shihadeh 63c9a85c6a FrameReader: use HW accel if available (#36964)
* FrameReader: add macOS hw accel

* sys

* more platforms

* logging
2025-12-28 21:38:54 -08:00
Adeeb Shihadeh adf9ec5360 tools: speed up Route() (#36963)
* tools: speed up Route()

* cleanup
2025-12-28 15:39:20 -08:00
commaci-public 883d1232d3 [bot] Update Python packages (#36606)
update

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2025-12-28 13:00:35 -08:00
Adeeb Shihadeh b58fddb83e replay: add --benchmark mode (#36957) 2025-12-28 12:20:45 -08:00
Adeeb Shihadeh ce1491df9c tools: add LRU eviction for log cache (#36959)
* tools: add LRU for log cache

* lil more

* cleanup:

* less syscall

* manifest

* cleanup

* cleanup

* lil more

* cleanup

* lil more

* simpler

* lil more
2025-12-28 11:45:19 -08:00
Adeeb Shihadeh ea01a53711 switch from mypy to ty (#36961) 2025-12-28 10:42:49 -08:00
Adeeb Shihadeh 85cdb2ed9a fix(url_file): ensure seek position is always an integer (#36960) 2025-12-27 23:15:18 -08:00
Adeeb Shihadeh 368947c88c msgq on macOS (#36958)
* msgq on macOS

* clean that up
2025-12-27 16:49:30 -08:00
DevTekVE 763049f068 SL: Re enable and validate ingestion of swaglogs (#1580)
* Re enable and validate ingestion
2025-12-27 11:49:26 -05:00
Trey Moen 3f1f7ad89c feat(esim): remove bootstrap (#36954)
feat: remove bootstrap
2025-12-24 09:04:34 -08:00
Nayan c6c644a3a6 [mici] ui: sunnypilot font on home menu (#1561)
use sp font on home

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-23 16:34:00 -05:00
dzid26 c876a83a31 ui: fix malformed dongle ID display on the PC if dongleID is not set (#1612) 2025-12-23 09:34:56 -05:00
Nayan a04a5b4284 ui: expand DeviceLayoutSP (#1560)
* commaai/openpilot:d05cb31e2e916fba41ba8167030945f427fd811b

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* sunnypilot: remove Qt

* cabana: revert to stock Qt

* commaai/openpilot:5198b1b079c37742c1050f02ce0aa6dd42b038b9

* commaai/openpilot:954b567b9ba0f3d1ae57d6aa7797fa86dd92ec6e

* commaai/openpilot:7534b2a160faa683412c04c1254440e338931c5e

* sum more

* bump opendbc

* not yet

* should've been symlink'ed

* raylib says wut

* quiet mode back

* more fixes

* no more

* too extra red diff on the side

* need to bring this back

* too extra

* let's update docs here

* Revert "let's update docs here"

This reverts commit 51fe03cd51.

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* multi-button

* Lint

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* sp raylib preview

* fix callback

* fix ui preview

* better padding

* this

* support for next line multi-button

* uhh

* disabled colors

* listitem -> listitemsp

* listitem -> listitemsp

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* ui: `GuiApplicationExt`

* simple button

* simple button

* add to readme

* use gui_app.sunnypilot_ui()

* i've got something to confessa

* init

* more init

* power buttons always visible

* uh, nope

* add reset to offroad only

* support wake up offroad

* flippity floppity

* dual button item sp

* use dual button item sp

* lint

* keep @devtekve from going blind

* more round

* some

* revert

* slight diff

* should've been inline

* cleanup power btns and offroad transitions

* bruh

* 1st row red diff

* 2nd row red diff

* 3rd row red diff

* slight diff

* move around

* more diff

* only when onroad we move to the top, not the toggle

* nah

* sort

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
Co-authored-by: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Co-authored-by: discountchubbs <alexgrant990@gmail.com>
2025-12-23 00:51:35 -05:00
Matt Purnell 373894a81f docs: Update branch installation instructions in README (#1610)
* Update branch installation instructions

* Add another link

* Add limited support link

* Incorporate suggested link

* Tweak wording
2025-12-23 00:42:24 -05:00
Jason Wen 34ce746869 ui: DualButtonActionSP and dual_button_item_sp helpers (#1608) 2025-12-22 09:29:01 -05:00
Matt Purnell e96b0da9d7 ci: Add unit test to prevent MADS DM regressions (#1602)
* monitoring/tests: Add unit test to prevent MADS regressions

* dm: remove TODO

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-21 23:07:01 -05:00
Jason Wen 6d7910ed74 ui: add inline to option_item_sp (#1600) 2025-12-21 22:56:51 -05:00
Jason Wen e54ddf30b8 ci: restore workflows from source branch for reset and squash (#1607) 2025-12-21 22:48:45 -05:00
Nayan 3093bb0b66 ui: fix sunnylink paired/sponsorship state (#1603)
* fix

* no point polling when disabled
2025-12-21 22:26:11 -05:00
Adeeb Shihadeh a8cfa2e2fe bump msgq (#36950) 2025-12-21 17:22:57 -08:00
Adeeb Shihadeh c8eed43538 misc system/hardware/ cleanup (#36949)
* misc system/hardware/ cleanup

* lil more

* pc is kinda base

* lil more

* lil more

* lil more

* int

* lil more?
2025-12-21 17:02:39 -08:00
Adeeb Shihadeh 29a2f576f5 unpin raylib-python-cffi (#36948) 2025-12-21 16:49:15 -08:00
Adeeb Shihadeh 31ec0096e4 ui: fix raylib init spam (#36947)
* lil more

* not none

* don't need that either

* too spammy now?
2025-12-21 16:21:35 -08:00
Adeeb Shihadeh 8728c7dde3 killing car_specific.py, part 3 (#36946)
* mv that

* lil more

* todo

* cleanup
2025-12-21 15:42:53 -08:00
Jason Wen 9c7c84bd03 ui: simplify non-inline action button positioning in ListViewSP (#1599)
ui: update non-inline action button positioning in `ListViewSP`
2025-12-20 23:30:30 -05:00
Jason Wen 6c6be573c7 ui: LineSeparatorSP (#1598) 2025-12-20 22:50:58 -05:00
Jason Wen 8904300565 Toyota: Enforce Factory Longitudinal Control (#1596)
* Toyota: enforce factory longitudinal control support

* sunnylink!

* bump

* bruh
2025-12-20 22:40:40 -05:00
Jason Wen 09c4b933a8 ui: capitalize button texts in Vehicle panel (#1597) 2025-12-20 22:14:19 -05:00
Jason Wen 1a1178140f ui: include MADS enabled state to engaged check (#1595) 2025-12-20 21:35:51 -05:00
Dean Lee e9a37d99c3 Fix incorrect msgq path in prefix.h (#36943) 2025-12-20 16:33:52 -08:00
Adeeb Shihadeh 67742699cc card: move drivable gears to opendbc (#36942)
* card: move drivable gears to opendbc

* it's not none

* bump opendbc

* mypy
2025-12-20 15:22:30 -08:00
Adeeb Shihadeh de975d5af9 card: remove MockCarstate (#36941) 2025-12-20 15:04:13 -08:00
Jason Wen 452aa67581 DM: fix upstream merge overwrite with latActive check (#1594)
* Update enabled condition to include latActive

* Todo-sp
2025-12-20 15:20:24 -05:00
Kumar 5bf2ac1657 [TIZI/TICI] ui: chevron metrics (#1487)
* chevron info

* sp dir

* rename

* decouple from stock model renderer

* pain

* RED DIFF: get from ui state directly

* built in

* banned

* no magic

* space

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-19 22:06:27 -05:00
Kumar f42dbf0c34 [TIZI/TICI] ui: rainbow path (#1486)
* rainbow

* use monotonic

* sp dir

* lint

* decouple from stock model renderer

* call in ui state directly

* it's a boolean

* too long

* nope

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-19 17:36:43 -05:00
zikeji 40f838260b sunnylink: block remote modification of SSH key parameters (#1591)
* feat: add blocked parameter names

* add unit test to validate

* test: use cached method

* move it out

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-19 16:31:01 -05:00
Nayan f8487cae23 sunnylink: elliptic curve keys support and improve key path handling (#1566)
* support ecdsa for mici

* lint

* ugh

* ugh ughain

* more

* symmetrical AES key derivation and some missing key handling

* cleanup

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-19 15:49:24 -05:00
Jason Wen 2e576178cb ci: fix duplicate if syntax error (#1590) 2025-12-19 15:31:29 -05:00
royjr 5578b7e754 ui: lateral-only and longitudinal-only UI statuses support (#1539)
* init

* add only colors

* fix LAT_ONLY on mici

* better ball

* hide wheel on LONG_ONLY

* hide torquebar on LONG_ONLY

* simpler

* dont block demo

* path only on long

* lanelines only on lat

* hide on override

* better

* same LANE_LINE_COLORS for mads

* use mads colors

* Revert "use mads colors"

This reverts commit 556321e5debe44e33d4ad98f440f0ed9f961fdf5.

* slight decouple confidence ball

* slight decouple model renderer

* slight decouple augmented road view

* decouple status update

* decouple and override with our own, no overriding with steering if long only

* fix

* fix it

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-19 14:36:10 -05:00
eFini c3143f3833 Multilang: update zh translation (#36933) 2025-12-19 09:38:23 -08:00
Maxime Desroches 1c2f9e6190 bump version to 0.10.4 2025-12-18 23:26:59 -08:00
Maxime Desroches 654338f9c7 update release instructions 2025-12-18 22:52:14 -08:00
Maxime Desroches dfd7a8c8d7 AGNOS 16 (#36915)
* stage

* prod

* bump reset
2025-12-18 22:02:46 -08:00
Shane Smiskol bb8a5bd476 Fix slow DM onboarding (#36932)
* slow

* interesting

* check

* clean up
2025-12-18 20:50:34 -08:00
Nayan 57e7c0b2c1 [comma 4] ui: sunnylink panel (#1544)
* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* sp raylib preview

* fix callback

* fix ui preview

* sunnylink state

* introducing ui_state_sp for py

* poll from ui_state_sp

* cloudlog & ruff

* param to control stock vs sp ui

* better

* better padding

* this

* listitem -> listitemsp

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* ui: `GuiApplicationExt`

* add to readme

* use gui_app.sunnypilot_ui()

* use gui_app.sunnypilot_ui()

* fetch only when connected to network

* init sunnylink panels

* cleanup

* lint

* flippity floppity

* fix backup/restore status

* show contributor tier

* sunnylink-mici

* icons

* fix

* add uploader

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-18 23:15:52 -05:00
Shane Smiskol e4359e9acb api_get: use session (#36930)
* use session

* prob better for now

* todo

* same for firehose

* no more stutters!

* cmt
2025-12-18 17:15:47 -08:00
Maxime Desroches 13b8a67ae2 reset: fix button overlap (#36929)
fix
2025-12-18 16:03:45 -08:00
Kumar 93f98a8a36 [TIZI/TICI] ui: Developer Metrics (#1523)
* devui

* clean up

* clean up

* optimize text measurement for better rendering performance

* sp dir

* decouple from stock HudRenderer

* rename

* fetch mode in _update_state

* wrong type

* start decoupling elements

* decouple elements

* un-ew this pls

* fully decouple developer UI elements

* rename

* more decouple

* full send

* final

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-18 05:01:16 -05:00
Shane Smiskol 89d9fdca82 WifiUi: tune wifi strengths (#36923)
* tune wifi strengths

* android nor ios show none or slash. it's always 1, 2, or 3 bars

* match here

* clean up
2025-12-17 23:15:22 -08:00
Jason Wen b52d0df6e3 ci: enable mici Raylib UI Preview in sunnypilot (#1588) 2025-12-18 02:08:20 -05:00
Shane Smiskol a478b64ff3 WifiUi: fix clicking (#36919)
* fix

* rm

* rename

* need this in case user swipes back to starting pos

* better

* better

* clean up

* cmt
2025-12-17 21:55:31 -08:00
Shane Smiskol b3c2daf9e5 Revert "Widget: track mouse events (#36922)"
https://github.com/commaai/openpilot/pull/36920#issuecomment-3668453692

This reverts commit 792a9b715c.
2025-12-17 21:32:06 -08:00
Shane Smiskol 792a9b715c Widget: track mouse events (#36922)
* track

* fix

* rm
2025-12-17 21:30:40 -08:00
James Vecellio-Grant f3598ce3ed ci: fix sunnypilot unit tests (#1584)
This PR aims to fix sunnypilot pytest that was broken on MacOS due to calling capnp to_dict, which isn't supported on pycapnp library for Mac.

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-18 00:29:37 -05:00
Shane Smiskol 631d6d9ef4 Widget: mouse handlers don't use bool (#36921)
* not used

* lint
2025-12-17 21:26:52 -08:00
Jason Wen 2b51adff11 sunnylink: Vehicle Selector support (#1587)
* sunnylink: Vehicle Selector support

* shebang
2025-12-18 00:20:42 -05:00
Jason Wen f5b3d87e25 ci: add GitHub app token for authenticated pushes (#1586) 2025-12-18 00:03:48 -05:00
James Vecellio-Grant 28fa7d5ed9 sync: update message queues and upstream merge conflicts (#1585)
* bug: fix sp message queues and protected method access

* more

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-17 23:54:39 -05:00
Shane Smiskol 6249211745 Update canError alert texts (#36918)
* hmm

* hmm it's small

* can

* ?

* variant?

* unknown
2025-12-17 19:57:57 -08:00
James Vecellio-Grant 7560497f15 Revert "latcontrol_torque: lower kp and lower friction threshold (commaai/openpilot#36619)" (#1581)
* Revert " latcontrol_torque: delay independent jerk and lower kp and lower friction threshold (#36619)"

This reverts commit f01391a7d9

* revert opendbc_repo

* bump

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-17 21:32:18 -05:00
Jason Wen 5999079838 Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1583)
* comma four: fix missing WiFi show_event (#36858)

* can't do this

* can do this

* comma four: rm duplicate wifi show_event

* comma four: fix WiFi panel not starting at the top (#36859)

* fix

* fix

* NavWidget: disable nav bar for vertical scrollers (#36857)

* disable nav bar vert scroller

* cmt

* ui: improve network sort (#36855)

* better sort

* clean up

* comma four: reset WiFi SSID scroll on show (#36861)

reset scroll

* WifiUi: fix infinite wraps (#36863)

* fix infinite wrap

* fix selection

* Revert "fix selection"

This reverts commit 555c57922409312bf5d9efedf571994f157b9e44.

* revert

* revert

* revert

* revert

* cleaner

* cleaner

* mypy!!

* WifiUi: remove delayed network panel open (#36865)

not used

* comma four: fix WiFi scroll to (#36864)

* fix selection

* stash

* Revert "stash"

This reverts commit d04ed66b090641072c86b8ed7ed86dbdbf67fbd9.

* clean up

* clean up

* move

* fix

* WifiUi: pause updates while user is scrolling (#36866)

* pause updates while user is scrolling

* clean up

* WifiUi: pause updates while user is interacting (#36868)

int not scroll

* Widget: implement layout function (#36869)

* we can implement layout to fix flashing

* reorder

* fix faster than normal snap and reduce duplicate calculations

* yes

* comma four: follow current network (#36862)

* stay

* whoops

* whoops

* fix

* fix div by z

* we can implement layout to fix flashing

* Revert "we can implement layout to fix flashing"

This reverts commit 7278a1e2a6117aec775ef4fabee2fd68b3d064f3.

* random

* clean up

* wtf

* rev

* smooth

* we can implement layout to fix flashing

* snap looks so much better

* fix

* rev

* better name

* cmt

* less random

* even less random

* simpler

* cmt

* clean up

* clean up

* clean up

* GuiScrollPanel2: fix possible crash (#36870)

fix crash

* WifiUi: tweak unselected button size (#36871)

looks too spaces

* rm dead unlog_ci_segment.py

* joystickd: add cruise control resume (#36876)

* Add cruise control resume logic based on conditions

* simple

* bump opendbc (#36878)

* bump

* update docs

* bump

* gotta go fast

* sensord: remove last of dual IMU support (#36881)

* Toyota: prevent roll in ICE after pressing resume while wanting to stay stopped (#36877)

* bump

* only show alert when user can leave standstill

* cmt

* stash

* bump

* bump to master

* test_onroad: absolute memory usage test (#36885)

* test_onroad: absolute memory usage test

* show msgq size

* reduce a little

* bump msgq

* Revert "bump msgq"

This reverts commit 683d0ae9fc754f7b72e2bc4b256e9a3b0a60a127.

* Reduce pub-sub memory usage by 10x (#36884)

less mem

* four: hide untoggleable toggles (#36890)

* hide toggles

* enabled is redundant

* bump msgq (#36891)

* bump msgq

* update prefix

* ui: generic hold gesture (#36893)

* generic

* fix

* use in home

* clean up

* rm

* clean up

* four: simpler steer saturated alert (#36894)

* looks good

* fix

* cleanup

* test_onroad: relax memory threshold (#36895)

* Update RELEASES.md for version 0.10.3

* Update RELEASES.md

* ui: override default interactive timeout (#36898)

* impl

* fix one place

* don't need in setup

* fix onboarding

* need here too

* ui: default text color 90% white (#36899)

default 90%

* onboarding: fixup DM RHD detection (#36900)

* helper

* fix

* use it

* prop

* bigger box

* huh

* comma four: simpler DM onboarding (#36896)

* rm confirm mode

* kinda works

* how

* disabled

* do this

* do this

* wait

* here

* something

* fade in

* 4s

* clean up

* copy

* help

* 30deg center

* stuff

* reset_interactive_timeout

* rm

* simple

* simple

* copy

* 1.5x

* smooth opacity

* power off slider

* fix

* new icons and gradient and rounded

* final check

* fix

* how the hell did this work

* clean up

* clean up

* flip

* cmt

* uh yeah

* remove this

* revert this

* lint

* 45

* clean up

* fix

* no show time

* question

* rm

* no use

* ()

* lint

* call

* ui: fix not showing networks if viewing right after startup

* Fix tici DM dialog memory leak (#36790)

* not finished

* no

* debug

* clean up

* clean up

* Revert "ui: generic hold gesture (#36893)"

This reverts commit 9768109ec1.

* setup: go back to main page once connected (#36902)

* call

* break

* print

* fix

* rm

* debug

* fix

* yeah ideally wifiui has no clue about this

* clean up

* clean up

* clean up

* only need this

* cu

* rm

* fix

* CI: tmp disable macOS due to brew bug (#36906)

* need update?

* try this

* x

* just disable it

* lil more release notes

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
Co-authored-by: YassineYousfi <yyousfi1@binghamton.edu>
2025-12-17 21:18:47 -05:00
Jason Wen 2458a6d115 Merge branch 'upstream/openpilot/master' into sync-20251217
# Conflicts:
#	docs/CARS.md
#	opendbc_repo
2025-12-17 21:09:26 -05:00
Shane Smiskol 2213f8f8a4 MultiOptionDialog: tap activates current option (#36911)
* works

* clean up
2025-12-17 17:10:12 -08:00
Shane Smiskol 4e85568370 MultiOptionDialog: support no default (#36912)
fix
2025-12-17 17:02:19 -08:00
Shane Smiskol 88a4f2baf1 Onboarding: no buttons if no frame (#36909)
no buttons if no frame
2025-12-17 16:27:43 -08:00
Adeeb Shihadeh 4bfc28dec0 lil more release notes 2025-12-17 10:19:05 -08:00
Adeeb Shihadeh be2818a131 CI: tmp disable macOS due to brew bug (#36906)
* need update?

* try this

* x

* just disable it
2025-12-17 09:37:30 -08:00
Shane Smiskol 1646fd94b8 setup: go back to main page once connected (#36902)
* call

* break

* print

* fix

* rm

* debug

* fix

* yeah ideally wifiui has no clue about this

* clean up

* clean up

* clean up

* only need this

* cu

* rm

* fix
2025-12-17 01:55:17 -08:00
Shane Smiskol 3fbd928b98 Revert "ui: generic hold gesture (#36893)"
This reverts commit 9768109ec1.
2025-12-17 01:53:17 -08:00
Shane Smiskol d2125aafd4 Fix tici DM dialog memory leak (#36790)
* not finished

* no

* debug

* clean up

* clean up
2025-12-17 01:23:49 -08:00
Shane Smiskol b9c3b1219a ui: fix not showing networks if viewing right after startup 2025-12-16 23:45:34 -08:00
Shane Smiskol 99983d39c3 comma four: simpler DM onboarding (#36896)
* rm confirm mode

* kinda works

* how

* disabled

* do this

* do this

* wait

* here

* something

* fade in

* 4s

* clean up

* copy

* help

* 30deg center

* stuff

* reset_interactive_timeout

* rm

* simple

* simple

* copy

* 1.5x

* smooth opacity

* power off slider

* fix

* new icons and gradient and rounded

* final check

* fix

* how the hell did this work

* clean up

* clean up

* flip

* cmt

* uh yeah

* remove this

* revert this

* lint

* 45

* clean up

* fix

* no show time

* question

* rm

* no use

* ()

* lint

* call
2025-12-16 23:16:45 -08:00
Shane Smiskol 31e46f929d onboarding: fixup DM RHD detection (#36900)
* helper

* fix

* use it

* prop

* bigger box

* huh
2025-12-16 22:42:13 -08:00
Shane Smiskol cecce82015 ui: default text color 90% white (#36899)
default 90%
2025-12-16 20:34:51 -08:00
Shane Smiskol a112e6e882 ui: override default interactive timeout (#36898)
* impl

* fix one place

* don't need in setup

* fix onboarding

* need here too
2025-12-16 19:31:49 -08:00
YassineYousfi c69c076acb Update RELEASES.md 2025-12-16 19:28:21 -08:00
Adeeb Shihadeh 6069c87b07 Update RELEASES.md for version 0.10.3 2025-12-16 19:21:00 -08:00
Adeeb Shihadeh 90ed6d739c test_onroad: relax memory threshold (#36895) 2025-12-16 18:14:47 -08:00
Shane Smiskol 95350ad854 four: simpler steer saturated alert (#36894)
* looks good

* fix

* cleanup
2025-12-16 16:56:19 -08:00
Shane Smiskol 9768109ec1 ui: generic hold gesture (#36893)
* generic

* fix

* use in home

* clean up

* rm

* clean up
2025-12-16 16:19:53 -08:00
Adeeb Shihadeh 4fa4237e3f bump msgq (#36891)
* bump msgq

* update prefix
2025-12-16 15:51:35 -08:00
Shane Smiskol 4624d8f936 four: hide untoggleable toggles (#36890)
* hide toggles

* enabled is redundant
2025-12-16 15:42:59 -08:00
Adeeb Shihadeh bcdeec3133 Reduce pub-sub memory usage by 10x (#36884)
less mem
2025-12-16 13:27:14 -08:00
Adeeb Shihadeh 545f7c6f2a test_onroad: absolute memory usage test (#36885)
* test_onroad: absolute memory usage test

* show msgq size

* reduce a little

* bump msgq

* Revert "bump msgq"

This reverts commit 683d0ae9fc754f7b72e2bc4b256e9a3b0a60a127.
2025-12-15 22:00:39 -08:00
Shane Smiskol 507f420927 Toyota: prevent roll in ICE after pressing resume while wanting to stay stopped (#36877)
* bump

* only show alert when user can leave standstill

* cmt

* stash

* bump

* bump to master
2025-12-15 19:19:41 -08:00
Adeeb Shihadeh 752ef8696a sensord: remove last of dual IMU support (#36881) 2025-12-15 19:04:11 -08:00
Shane Smiskol 9e4c2bcacf bump opendbc (#36878)
* bump

* update docs

* bump

* gotta go fast
2025-12-15 16:41:16 -08:00
Shane Smiskol 9d9e5aa02d joystickd: add cruise control resume (#36876)
* Add cruise control resume logic based on conditions

* simple
2025-12-15 15:36:28 -08:00
Jason Wen a1d0f6aa55 ci: use Brewfile for macOS setup and update Homebrew cache keys (#1576)
* ci: use Brewfile for macOS setup and update Homebrew cache keys

* Brewfile
2025-12-14 23:50:44 -05:00
Nayan e7554170b8 ui: SimpleButtonActionSP (#1502)
* commaai/openpilot:d05cb31e2e916fba41ba8167030945f427fd811b

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* bump opendbc

* sunnypilot: remove Qt

* cabana: revert to stock Qt

* commaai/openpilot:5198b1b079c37742c1050f02ce0aa6dd42b038b9

* commaai/openpilot:954b567b9ba0f3d1ae57d6aa7797fa86dd92ec6e

* commaai/openpilot:7534b2a160faa683412c04c1254440e338931c5e

* sum more

* bump opendbc

* not yet

* should've been symlink'ed

* raylib says wut

* quiet mode back

* more fixes

* no more

* too extra red diff on the side

* need to bring this back

* too extra

* let's update docs here

* Revert "let's update docs here"

This reverts commit 51fe03cd51.

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* multi-button

* Lint

* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* sp raylib preview

* fix callback

* fix ui preview

* better padding

* this

* support for next line multi-button

* uhh

* disabled colors

* listitem -> listitemsp

* listitem -> listitemsp

* add show_description method

* remove padding from line separator.
like, WHY? 😩😩

* ui: `GuiApplicationExt`

* simple button

* simple button

* add to readme

* use gui_app.sunnypilot_ui()

* i've got something to confessa

* sync

* revert

* Fix SimpleButtonActionSP not respecting enabled state

* some more

* ui: `ButtonSP`

* slight cleanup

* fixes

* fix

* unused

* try this

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
Co-authored-by: DevTekVE <devtekve@gmail.com>
Co-authored-by: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Co-authored-by: discountchubbs <alexgrant990@gmail.com>
2025-12-14 23:18:49 -05:00
Jason Wen 9c2fd8d2be ui: ButtonSP (#1575)
* ui: `ButtonSP`

* final

* revert for now

* revert
2025-12-14 22:44:51 -05:00
Adeeb Shihadeh e2fd6f34e9 rm dead unlog_ci_segment.py 2025-12-13 12:56:32 -08:00
Jason Wen d9bbc8f5bb ci: update prebuilt exclusions (#1572) 2025-12-13 15:17:20 -05:00
Shane Smiskol a3c638697f WifiUi: tweak unselected button size (#36871)
looks too spaces
2025-12-13 06:26:27 -08:00
Shane Smiskol f287d487e5 GuiScrollPanel2: fix possible crash (#36870)
fix crash
2025-12-13 06:16:31 -08:00
Shane Smiskol 7cabab69a1 comma four: follow current network (#36862)
* stay

* whoops

* whoops

* fix

* fix div by z

* we can implement layout to fix flashing

* Revert "we can implement layout to fix flashing"

This reverts commit 7278a1e2a6117aec775ef4fabee2fd68b3d064f3.

* random

* clean up

* wtf

* rev

* smooth

* we can implement layout to fix flashing

* snap looks so much better

* fix

* rev

* better name

* cmt

* less random

* even less random

* simpler

* cmt

* clean up

* clean up

* clean up
2025-12-13 06:15:31 -08:00
Shane Smiskol 716ad288bb Widget: implement layout function (#36869)
* we can implement layout to fix flashing

* reorder

* fix faster than normal snap and reduce duplicate calculations

* yes
2025-12-13 05:45:42 -08:00
Shane Smiskol 1c135f7ff2 WifiUi: pause updates while user is interacting (#36868)
int not scroll
2025-12-13 05:28:53 -08:00
Shane Smiskol 1504e10380 WifiUi: pause updates while user is scrolling (#36866)
* pause updates while user is scrolling

* clean up
2025-12-13 05:14:21 -08:00
Shane Smiskol 65008d281f comma four: fix WiFi scroll to (#36864)
* fix selection

* stash

* Revert "stash"

This reverts commit d04ed66b090641072c86b8ed7ed86dbdbf67fbd9.

* clean up

* clean up

* move

* fix
2025-12-13 04:33:27 -08:00
Shane Smiskol 2e8586fab5 WifiUi: remove delayed network panel open (#36865)
not used
2025-12-13 04:11:36 -08:00
Shane Smiskol 6c5be6ddab WifiUi: fix infinite wraps (#36863)
* fix infinite wrap

* fix selection

* Revert "fix selection"

This reverts commit 555c57922409312bf5d9efedf571994f157b9e44.

* revert

* revert

* revert

* revert

* cleaner

* cleaner

* mypy!!
2025-12-13 04:08:01 -08:00
Shane Smiskol 7a324fc377 comma four: reset WiFi SSID scroll on show (#36861)
reset scroll
2025-12-13 01:50:55 -08:00
Shane Smiskol f4dea7977b ui: improve network sort (#36855)
* better sort

* clean up
2025-12-13 01:44:05 -08:00
Shane Smiskol e9255d1e9c NavWidget: disable nav bar for vertical scrollers (#36857)
* disable nav bar vert scroller

* cmt
2025-12-13 01:41:01 -08:00
Shane Smiskol 350dc6a50f comma four: fix WiFi panel not starting at the top (#36859)
* fix

* fix
2025-12-13 01:39:45 -08:00
Shane Smiskol 3206784dd8 comma four: rm duplicate wifi show_event 2025-12-13 01:35:10 -08:00
Shane Smiskol 0dd59d0404 comma four: fix missing WiFi show_event (#36858)
* can't do this

* can do this
2025-12-13 01:32:06 -08:00
Jason Wen a33e01ca96 Sync: commaai/openpilot:mastersunnypilot/openpilot:master (#1571) 2025-12-13 01:58:07 -05:00
Jason Wen 03c8494dbc Merge branch 'upstream/openpilot/master' into sync-20251213
# Conflicts:
#	README.md
#	common/api.py
#	docs/CARS.md
#	opendbc_repo
#	panda
#	selfdrive/ui/mici/layouts/offroad_alerts.py
#	system/ui/README.md
#	system/version.py
2025-12-13 01:50:42 -05:00
James Vecellio-Grant cab2a28e10 ui: Developer panel extension (#1521)
* ui: developer panel

* comment out

* double translate

* quickboot and more efficient file checking

* use HtmlModalSP!

* ui: `HtmlModalSP`

* less

* lint

* less

* just use existing dir on PC

* grammar

* match official

* rename

* biiig

---------

Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-13 00:50:57 -05:00
Shane Smiskol cc119b2a37 comma four: adjust Wifi scroller sizes (#36854)
* adjust sizes

* back
2025-12-12 21:37:26 -08:00
Harald Schäfer 9421e1cbfe Dark Souls 2 (#36849)
4b78e2e6-660f-4155-9105-81d4d8c658cd/400
2025-12-12 18:04:16 -08:00
Jason Wen 46257aca02 ui: HtmlModalSP (#1570)
* ui: `HtmlModalSP`

* less
2025-12-12 03:16:57 -05:00
James Vecellio-Grant 436ff5aa42 ui: OSM panel (#1515)
* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* sp raylib preview

* fix callback

* fix ui preview

* dialog txt

* compare vs what used to be done before InputDialog

* merge origin raylib toggles

* tree dialog

* less trees for the planet

* the heck

* save the trees we got icons

* Update process.py

* Remove 'sunnypilot_ui' 

Removed 'sunnypilot_ui' parameter from params_keys.h

* Update raylib_screenshots.py

Removed the parameter setting for 'sunnypilot_ui' in the test.

* ui: fuzzy search helper

* better tree. fully dynamic and stuff

* rm

* more indent

* Squashed commit of the following:

commit 6b5b686fa5
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 17:16:17 2025 -0800

    more indent

commit 76bc538ac7
Merge: 53eb821dc4 c53e2134e2
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 24 17:15:48 2025 -0800

    Merge branch 'master' into rl-tree-dialog

commit 53eb821dc4
Merge: 82e1ebe97e 844f4cbc74
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 24 11:54:55 2025 -0800

    Merge branch 'master' into rl-tree-dialog

commit 82e1ebe97e
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 10:23:35 2025 -0800

    rm

commit da3ff45bb6
Merge: 41da513fca a829a1b972
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 10:19:08 2025 -0800

    Merge remote-tracking branch 'origin/rl-tree-dialog' into rl-tree-dialog

commit 41da513fca
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 10:18:43 2025 -0800

    better tree. fully dynamic and stuff

commit b2950149fb
Merge: 4fb8e4beed 924e5a3211
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 10:17:51 2025 -0800

    Merge remote-tracking branch 'origin/input-dialog' into rl-tree-dialog

commit a829a1b972
Merge: 848290d07e 9edc36ca66
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 24 10:16:28 2025 -0800

    Merge branch 'master' into rl-tree-dialog

commit 4fb8e4beed
Merge: 848290d07e af4f0f8372
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 24 10:16:20 2025 -0800

    Merge remote-tracking branch 'origin/fuzzy-dialog' into rl-tree-dialog

commit af4f0f8372
Merge: 1d5f0ab282 3cd55260d9
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 24 06:39:29 2025 -0800

    Merge branch 'master' into fuzzy-dialog

commit 1d5f0ab282
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Sun Nov 23 11:28:59 2025 -0800

    ui: fuzzy search helper

commit 848290d07e
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 21:08:07 2025 -0800

    Update raylib_screenshots.py

    Removed the parameter setting for 'sunnypilot_ui' in the test.

commit 6694928a46
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 21:06:57 2025 -0800

    Remove 'sunnypilot_ui'

    Removed 'sunnypilot_ui' parameter from params_keys.h

commit b3c90ef7b2
Merge: 0d3bc959c8 457b6634fd
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 21:06:04 2025 -0800

    Merge branch 'master' into rl-tree-dialog

commit 924e5a3211
Merge: a4ee4ba76d d92d2cb683
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 19:33:18 2025 -0800

    Merge branch 'master' into input-dialog

commit a4ee4ba76d
Merge: e911de5968 4f13a0f775
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 16:24:31 2025 -0800

    Merge branch 'master' into input-dialog

commit e911de5968
Merge: cea6e00819 0ba5cbea91
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 13:50:33 2025 -0800

    Merge branch 'master' into input-dialog

commit cea6e00819
Merge: d7b8ce86ed 8184cd8a6a
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 12:01:45 2025 -0800

    Merge branch 'master' into input-dialog

commit 0d3bc959c8
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Wed Nov 19 20:29:30 2025 -0800

    Update process.py

commit 4f3c19ffb5
Author: James Vecellio <alexgrant990@gmail.com>
Date:   Wed Nov 19 20:28:59 2025 -0800

    save the trees we got icons

commit ae5c44355d
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 13:38:04 2025 -0800

    the heck

commit 066438ad10
Merge: 9532675814 e74460f3a8
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 12:18:17 2025 -0800

    Merge remote-tracking branch 'origin/rl-tree-dialog' into rl-tree-dialog

commit 9532675814
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 12:17:52 2025 -0800

    less trees for the planet

commit e74460f3a8
Merge: c347db376a 423a7d2ed0
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Wed Nov 19 09:37:44 2025 -0800

    Merge branch 'rl-sp-toggles' into rl-tree-dialog

commit c347db376a
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 09:36:33 2025 -0800

    tree dialog

commit c9bd67b261
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 09:34:08 2025 -0800

    merge origin raylib toggles

commit d7b8ce86ed
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 17 20:21:33 2025 -0800

    compare vs what used to be done before InputDialog

commit 2d3d104658
Merge: ded02895f4 f1025f6ee9
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 17 19:24:20 2025 -0800

    Merge branch 'master' into input-dialog

commit ded02895f4
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Mon Nov 17 19:22:01 2025 -0800

    dialog txt

commit 9778a925b0
Merge: cb03d08397 08e85808c5
Author: Jason Wen <haibin.wen3@gmail.com>
Date:   Sun Nov 16 03:16:58 2025 -0500

    input dialog

commit 423a7d2ed0
Author: nayan <nayan8teen@gmail.com>
Date:   Sun Nov 16 11:15:28 2025 -0500

    fix ui preview

commit e4e10d4b87
Author: nayan <nayan8teen@gmail.com>
Date:   Sun Nov 16 11:15:22 2025 -0500

    fix callback

commit 362e9ce04b
Author: nayan <nayan8teen@gmail.com>
Date:   Sun Nov 16 09:53:28 2025 -0500

    sp raylib preview

commit 3946e643f6
Author: nayan <nayan8teen@gmail.com>
Date:   Sat Nov 15 20:24:20 2025 -0500

    optimizations

commit 0c37a38596
Author: nayan <nayan8teen@gmail.com>
Date:   Sat Nov 15 09:42:12 2025 -0500

    Lint

commit 9c5acf61c0
Author: nayan <nayan8teen@gmail.com>
Date:   Sat Nov 15 09:29:07 2025 -0500

    SP Toggles

commit 121b304fe0
Author: nayan <nayan8teen@gmail.com>
Date:   Sat Nov 15 09:28:58 2025 -0500

    init styles

commit 47d848293b
Author: nayan <nayan8teen@gmail.com>
Date:   Sat Nov 15 09:28:43 2025 -0500

    param to control stock vs sp ui

* Squashed commit of the following:

commit 70ad001add
Merge: 142663c490 844f4cbc74
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Mon Nov 24 11:54:58 2025 -0800

    Merge branch 'master' into rl-progress-bar

commit 142663c490
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Sat Nov 22 20:12:44 2025 -0800

    smoother updating

commit 4476e418dd
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Sat Nov 22 09:55:17 2025 -0800

    easier to see

commit ad66c22e88
Merge: 0c46ef5948 457b6634fd
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Sat Nov 22 07:45:05 2025 -0800

    Merge branch 'master' into rl-progress-bar

commit 0c46ef5948
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Sat Nov 22 07:42:59 2025 -0800

    freaking test dir

commit 11c19aad24
Merge: 7785238d54 8184cd8a6a
Author: James Vecellio-Grant <159560811+Discountchubbs@users.noreply.github.com>
Date:   Fri Nov 21 12:01:36 2025 -0800

    Merge branch 'master' into rl-progress-bar

commit 7785238d54
Author: discountchubbs <alexgrant990@gmail.com>
Date:   Wed Nov 19 07:47:10 2025 -0800

    raylib: progress bar

* OSM panel

* fetching

* only show if fav_param is used in the call

* flattened and custom search query

* conditional for mypy

* sunny's new x,y makes this even easier!

* download all

* add back the rough estimate

* not sure i like the 'Download'

* simplify the path

* actual size as of today

* format

* more simple

* only show on download or delete

* loathing loathing, unadulterated loathing, i loathe it all

* loathing loathing, unadulterated loathing, i loathe it all

* # Conflicts:
#	system/ui/sunnypilot/lib/styles.py
#	system/ui/sunnypilot/widgets/tree_dialog.py

* search

* st

* Update osm.py

* one second updates:

 its heavy process, which isnt really noticeable during downloads ayways. the once a second ensures responsiveness on the ui, while also maintaining 20fps on device for country/state downloads.

* efficient? i hope

* big boi texts

* big boi texts

* use our own classes

* need to clear all params when delete all

* more

* collateral lol

* do not behave as selected if canceled during US->States dialog

* more

* instead of timestamp, let's just show formatted time

* disable button when downloading dbs

* should be the buttons being disabled

* well gotta re-enable them too

* empty country

* might be bigger now

* fixes for mapd manager

* should stay as a json

* sanitize it a bit

* revert

* only nuke if the cancel button is called

* always try to update the labels

* Revert "always try to update the labels"

This reverts commit ba0988fc06.

* re-enable button after download is complete

* disable all while downloading (till we could cancel and re-download)

* fix progress bar not filling up as intended for smaller total counts

* revert

* use new

---------

Co-authored-by: nayan <nayan8teen@gmail.com>
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-12 02:40:33 -05:00
Jason Wen 928672999b ui: consolidate NoElideButtonAction (#1569) 2025-12-12 02:31:06 -05:00
Shane Smiskol 9947206ccd comma four: fix wrapping steer right (#36848)
rm extra space
2025-12-11 21:52:24 -08:00
James Vecellio-Grant b2e7dffa59 modeld_v2: support planplus outputs (#1532)
* conditional concatenation

* v13

* modifucatuins
2025-12-11 23:24:45 -05:00
Bruce Wayne 0871a35c10 Revert "Dark Souls Model (#36764)"
This reverts commit 83dad85cdd.
2025-12-11 19:43:53 -08:00
Suyog Shinde 2d91aa5abc locationd: fix velocity calibration using wrong pose field (#36844) 2025-12-11 19:24:32 -08:00
Matt Purnell 13693e3a0a loggerd: Fix test that fails on non-TICI devices (#36846)
Only check for TICI files on TICI
2025-12-11 18:19:59 -08:00
Shane Smiskol edede31c32 athenad: get ES256 key (#36845)
* fix

* why not format

* fix typing

* cast
2025-12-11 18:00:43 -08:00
Adeeb Shihadeh c61ed10015 USB GPU benchmarking (#36840)
* test boot time

* lil nicer

* cleanup

* revert that

---------

Co-authored-by: Comma Device <device@comma.ai>
2025-12-11 13:04:59 -08:00
Adeeb Shihadeh 1391434f54 setup: fix uv install fail (#36839)
* pipefail

* curl retry
2025-12-11 11:22:08 -08:00
YassineYousfi d8125f50d2 dm: speedup stat filters convergence (#36756)
* dm: speedup stat filters convergence

* lint
2025-12-11 09:38:53 -08:00
Dean Lee a49273d9d4 remove unused #include "common/params.h" from hardware.h (#36827)
remove include
2025-12-11 09:22:30 -08:00
rj-lynch ff5b75d164 Refactor CarSpecificEvents Class extracting BRAND_EXTRA_GEARS (#36805)
* Brand Extra Gears Dict added. Gear data removed from CarSpecificEvents Update method, data now held in global variable.

* Added elif for Ford and Nissan events creation. BRAND_EXTRA_GEARS now extracted from CarSpecificEvents

* Amended Chrysler and Toyota create_common_events calls.

* format

* can do this!

* consis

* whoops

* type

---------

Co-authored-by: RJ <ryan@DESKTOP-4S0L5O5.localdomain>
Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-12-10 16:35:35 -08:00
Shane Smiskol 53b7adedc2 Fix UI timing test (#36823)
* why did no one tell me about this?!

* not necessary
2025-12-10 00:29:03 -08:00
Shane Smiskol f78bacf96b mici ui replay: temp remove swipes (#36818)
hmm it IS nondeterm
2025-12-09 15:38:43 -08:00
Shane Smiskol dfd56a46d2 mici cameraview: log timings (#36816)
missing from mici
2025-12-09 15:37:13 -08:00
clintonsteiner 6bbc3f4d1c pyproject: remove pytools pinning (#36812)
* pyproject: remove pytools pinning

* issue requiring pin is fixed
* https://github.com/inducer/pyopencl/issues/827

* uv lock

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2025-12-09 11:04:03 -08:00
Harald Schäfer 34fed9f908 URLFILE: Need to catch max retry (#36815)
Need to catch max retry
2025-12-09 10:19:10 -08:00
Adeeb Shihadeh c85db43705 camerad: misc labeling/cleanup (#36809)
* what's 2c

* include

* no idea what this means

* register comments
2025-12-08 20:14:19 -08:00
Shane Smiskol 8d9e203130 raylib ui diff: swipe around (#36807)
* swipe support

* swipe around

* same
2025-12-08 19:25:09 -08:00
Adeeb Shihadeh d5f6946502 camerad: probe os first 2025-12-08 18:48:58 -08:00
「 crwusiz 」 48a42a9c53 UI: Color Constants Uppercase (#36796) 2025-12-08 18:43:31 -08:00
Adeeb Shihadeh fb807cc007 ui: video diff tool (#36737)
* video diff

* format

* duplicate

* try

* WINDOWED

* ?

* correct res

* Revert "correct res"

This reverts commit f90991192fce93a31d1b581a4f0ff93a7a972337.

* save to report/

* add duplicate

* work?

* fix

* more

* more

* and this

* ffmpeg

* branch

* uncmt

* test preview

* Revert "uncmt"

This reverts commit b02404dbbe515fd861717f831c7bb0243442ddbc.

* create openpilot_master_ui_mici_raylib

* ahh

* push to master

* copy and always run

* test

* does cmt break it?

* who did this

* fix?

* fix that

* hmm

* hmm

* ah this was moving it, and then the job below didn't run on master

* google ai overview lied to me

* use markdown to start

* need to add to one branch

* ????

* oof

* no

* this work?

* test

* try this

* clean up master branch name

* more cleanup

more cleanup

* don't fail for no diff!

don't fail for no diff!

* back

* add to cmt

* test it

* should work

* fix that

* back

* clean up

* clean up

* save to report

* pull_request_target

* sort

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-12-08 18:39:47 -08:00
Matt Purnell 7119412d35 updated: fix skipped test case (#36786)
Fix three failing tests
2025-12-08 16:41:45 -08:00
Chechulin Serhii fadf7ff1e5 ui: feature Ukrainian translation (#36646)
* Add Ukrainian lang

* update_translations.py

* Add Ukrainian strings

* Small patch to display translated update states

* Revert "Small patch to display translated update states"

This reverts commit b0545f4e109f451a21e4e5884259dbb881d7a58e.

* Revert "update_translations.py"

This reverts commit 79eea20c33f1b1d542b62a782ab1b67bc9277026.

* fix so these meaningless edits
2025-12-08 16:40:29 -08:00
Matt Purnell cce2e4d357 tools: Handle smaller terminal sizes in replay (#36766)
* Only show help if there's room for it

* show less

* wording
2025-12-08 16:38:35 -08:00
Dean Lee 4e74e0f755 cabana: fix UI hang when switching streams (#36735)
fix UI hang when switching streams
2025-12-08 16:36:55 -08:00
Dean Lee a6645a1be1 cabana: add automatic session save/restore (#36736)
adds auto session save/store
2025-12-08 16:36:35 -08:00
「 crwusiz 」 239d690a43 Multilang: update kor translation (#36795) 2025-12-08 16:32:56 -08:00
James Vecellio-Grant 323b793a83 ui: software panel (#1518)
* param to control stock vs sp ui

* init styles

* SP Toggles

* Lint

* optimizations

* sp raylib preview

* fix callback

* fix ui preview

* dialog txt

* compare vs what used to be done before InputDialog

* introducing ui_state_sp for py

* raylib: input dialog

* raylib: SP Toggles

* raylib: SP Panels

* raylib: Option Control

* init

* param to control stock vs sp ui

* better

* tree dialog, progress bar widget cool stuff

* merge origin raylib toggles

* tree dialog

* less trees for the planet

* the heck

* add ui_update callback

* save the trees we got icons

* Update process.py

* yesssssssssss

* utilize ON_COLOR constant form op system

* Revert "add ui_update callback"

This reverts commit 4da32cc009.

* # Conflicts:
#	system/ui/sunnypilot/widgets/list_view.py
#	system/ui/sunnypilot/widgets/option_control.py

* Merge remote-tracking branch 'openpilot/master' into nov-19-sync

* ui: `GuiApplicationExt`

* add to readme

* scroller_tici :)

* use gui_app.sunnypilot_ui()

* # Conflicts:
#	selfdrive/ui/layouts/main.py
#	selfdrive/ui/sunnypilot/layouts/settings/cruise.py
#	selfdrive/ui/sunnypilot/layouts/settings/display.py
#	selfdrive/ui/sunnypilot/layouts/settings/models.py
#	selfdrive/ui/sunnypilot/layouts/settings/navigation.py
#	selfdrive/ui/sunnypilot/layouts/settings/osm.py
#	selfdrive/ui/sunnypilot/layouts/settings/steering.py
#	selfdrive/ui/sunnypilot/layouts/settings/sunnylink.py
#	selfdrive/ui/sunnypilot/layouts/settings/trips.py
#	selfdrive/ui/sunnypilot/layouts/settings/vehicle.py
#	selfdrive/ui/sunnypilot/layouts/settings/visuals.py
#	system/ui/sunnypilot/widgets/option_control.py

* init value

* Remove 'sunnypilot_ui' 

Removed 'sunnypilot_ui' parameter from params_keys.h

* Update raylib_screenshots.py

Removed the parameter setting for 'sunnypilot_ui' in the test.

* easier to see

* Update progress_bar.py

* try something

* adjust placement

* more simple

* smoothing updating components

* ui: fuzzy search helper

* ui_state_sp

* description!

* fuzzy af searching

* better tree. fully dynamic and stuff

* rm

* rearrange

* license

* idk how maybe the merge

* more indent

* more indent

* cleanup

* temporaily revert ui_state_sp

* only show if fav_param is used in the call

* conditional for mypy

* mypy

* conditional for mypy

* str concatenation to reduce line len

* level

* sunny's new x,y makes this even easier!

* refreshing half a second seems legit.

* software stuffs

* rm

* add

* loathing loathing, unadulterated loathing, i loathe it all

* loathing loathing, unadulterated loathing, i loathe it all

* # Conflicts:
#	system/ui/sunnypilot/lib/styles.py
#	system/ui/sunnypilot/widgets/tree_dialog.py

* search

* ds

* hide on advanced controls

* some

* handle toggle confirmation

* sunny, NO

* nayan, NO !!

* easier

* move

* move it!

* add more

* need to show current branch

---------

Co-authored-by: nayan <nayan8teen@gmail.com>
Co-authored-by: Jason Wen <haibin.wen3@gmail.com>
2025-12-07 01:36:02 -05:00
Jason Wen 96c2650ac4 ui: improve TreeOptionDialog node selection and item handling (#1563) 2025-12-07 01:31:00 -05:00
Shane Smiskol d4d6134d3b UnifiedLabel: fix clipping descenders (#36793)
* fix

* can also do this

* but then y is off. this is from font_scale I think

* fix

* cmt
2025-12-05 18:18:58 -08:00
Robbe Derks 0965650f61 Bump panda (#36783)
* panda bump

* try this one

* this breaks it?

* still broken, right?

* fixed?

* second try
2025-12-05 23:12:39 +01:00
Shane Smiskol 224e2c271b Revert "ui: fix dialog memory leak" (#36787)
Revert "ui: fix dialog memory leak (#36767)"

This reverts commit 45b7d60263.
2025-12-04 16:51:18 -08:00
Harald Schäfer e72e5d4ebe beeps in key (#36765)
beeps in keyt
2025-12-04 13:11:27 -08:00
Shane Smiskol f962a36fd8 Fix ui crashing replay/selfdrived (#36760)
* fix

* clean up

* type hint
2025-12-04 02:39:41 -08:00
Dean Lee 2947af42fc ui: fix TraningGuide leak (#36763)
* fix TraningGuide leak

* other thing

* this is truly the simplest way

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-12-04 02:23:37 -08:00
Shane Smiskol cd9b08492e ui: small TrainingGuide clean up 2025-12-04 02:00:45 -08:00
Shane Smiskol 45b7d60263 ui: fix dialog memory leak (#36767)
* weakref alternative

* and here

* clean up

* fix

* rm
2025-12-04 01:56:38 -08:00
Dean Lee 93f2076c7e ui: fix crash caused by double shader unload in CameraView (#36778)
fix double free isuue
2025-12-04 01:54:11 -08:00
Shane Smiskol 4edbc7d0cf DriverCameraDialog: proper clean up (#36775)
* fixes leak

* wait can't do this, we need close after all

* wait can't do this, we need close after all

* clean up memory
2025-12-03 22:19:30 -08:00
Shane Smiskol cc7dd066d2 ui: call modal hide_event (#36772)
* start, not fully working since hide is called before last render

* clean up
2025-12-03 21:55:05 -08:00
Shane Smiskol 9e55577cc7 Clean up DM dialog CameraView bound method (#36770)
* clean up

* why not?

* clean up
2025-12-03 20:41:58 -08:00
Shane Smiskol 7ea6cfcbdf remove unecessary function 2025-12-03 20:00:19 -08:00
Harald Schäfer 83dad85cdd Dark Souls Model (#36764)
a4cf2707-3d69-49ea-af8b-f91cd3285249/400
2025-12-03 12:55:33 -08:00
Maxime Desroches 5fd0906164 allow restarting processes after crash (#36755)
more
2025-12-02 17:10:24 -08:00
Maxime Desroches e7d349bf36 Revert "ui: restart if crash (#36746)" (#36754)
This reverts commit fa18bb9261.
2025-12-02 16:45:09 -08:00
Bruce Wayne 5393308d03 Logreader: print errors 2025-12-02 15:54:21 -08:00
YassineYousfi dc02a2d385 dm: adjust cold start pose offsets (#36739)
* dm: adjust cold start offsets and thresholds

* change just offsets for now
2025-12-02 15:17:59 -08:00
Chechulin Serhii 63563c3561 ui: fix - translate display text of updater_state (#36649)
* Add updater_state translation

* Move STATE_TO_DISPLAY_TEXT on top
2025-12-02 13:13:13 -08:00
Dean Lee ae6250e685 ui/CameraView: use consistent 2-space indentation (#36748)
use consistent 2-space indentation
2025-12-02 13:09:24 -08:00
Shane Smiskol ae402d3ac7 Revert "ui: speed up mici/AugmentedRoadView by optimizing _calc_frame_matrix caching" (#36749)
Revert "ui: speed up `mici/AugmentedRoadView` by optimizing _calc_frame_matri…"

This reverts commit 1052435391.
2025-12-02 13:02:01 -08:00
Harald Schäfer cfb0a1c18c URLFile multirange (#36740)
* url file multirange

* cleanup urlfile

* time

* fixup

* raise

* Diskfile
2025-12-01 23:11:03 -08:00
Maxime Desroches fa18bb9261 ui: restart if crash (#36746)
* simpler

* mypy your are going to be replaced very soon
2025-12-01 22:55:14 -08:00
Trey Moen cabfa7b735 Revert "esim: remove bootstrap and delete (#36732)" (#36747)
This reverts commit 6d04251517.
2025-12-01 22:45:11 -08:00
Maxime Desroches 65e551c671 Handle invalid frame fd when creating EGL image (#36743)
catch
2025-12-01 21:32:07 -08:00
Maxime Desroches 62b7abcd91 Fix raylib ui spamming API calls (#36745)
fix
2025-12-01 21:13:43 -08:00
Maxime Desroches dc654b439a Revert "Fix raylib ui spamming API calls (#36700)" (#36744)
This reverts commit 26261387f8.
2025-12-01 20:48:04 -08:00
Dean Lee 693c83f74c replay: fix dangling pointers in logging calls (#36738)
fix dangling pointers in logging calls
2025-12-01 13:32:21 -08:00
Trey Moen 8ffe3f287e fix: openpilot build on ubuntu aarch64 (#36675)
breaks on linux
2025-11-30 16:09:50 -08:00
Dean Lee 749e236bc0 ui: fix EGL_BAD_MATCH error when running profile_onroad.py on device (#36608)
fix failed to create EGL image:12297 error on device
2025-11-30 16:06:33 -08:00
Adeeb Shihadeh 151d256dd6 add param for agnos power monitor 2025-11-30 15:29:40 -08:00
Adeeb Shihadeh 436e3dec3e manager: write power monitor flag atomically (#36734) 2025-11-30 15:14:31 -08:00
Adeeb Shihadeh 7521fd11e2 common: rename atomic_write_in_dir -> atomic_write (#36733)
rename
2025-11-30 15:08:32 -08:00
MVL ff755ed4bf Honda - Rename AcuraWatch Plus to AcuraWatch (#36726)
* Rename AcuraWatch Plus to AcuraWatch

* Rename AcuraWatch Plus to AcuraWatch
2025-11-30 15:04:17 -08:00
Trey Moen 6d04251517 esim: remove bootstrap and delete (#36732)
init
2025-11-30 14:43:29 -08:00
Adeeb Shihadeh 970afa9683 bump to 0.10.3 2025-11-30 14:19:37 -08:00
David cd7e362333 ui: Add RECORD=1 for direct frame recording (#36729)
* ui: add real-time video recording functionality with ffmpeg support

* fix: record at consistent frame rate

* add spaces

* fix type

* refactor: RECORD_FRAMES variable and related logic

* fix: remove unnecessary texture check

* support missing output extension

* add wait for close with timeout

* fix: ensure RECORD_OUTPUT has the correct file extension

* flush on close and terminate if times out closing

* ffmpeg hide banner

* reduce ffmpeg spam

* refactor: streamline ffmpeg arguments for video encoding

* refactor: move size arg to variable and add yub420p conversion for native support

* use render_width and render_height for size

* fix: ensure even dimensions for video encoding when recording

* rm itertools

* simple

* cleanup

* docs

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2025-11-30 13:34:37 -08:00
Shane Smiskol 85a162dd43 more scons nodes 2025-11-30 02:48:05 -08:00
Dean Lee 8de8946374 ui: skip _draw_set_speed when alpha is 0 (#36709)
* Skip _draw_set_speed when alpha is 0 to reduce unnecessary draw calls

* Update selfdrive/ui/mici/onroad/hud_renderer.py

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-11-29 03:15:41 -08:00
Dean Lee f1c2b1df7f ui: fix CameraView crash in mici due to stale frame (#36710)
fix CameraView crash caused by stale frame
2025-11-29 03:14:23 -08:00
Shane Smiskol 1b20567c98 Mici keyboard: alpha filter for key bg (#36720)
* filter

* tune

* fix
2025-11-29 02:30:32 -08:00
Dean Lee 6c39f6bb53 ui: Fix scroll logic for non-scrollable content (bounds_size > content_size) to prevent jitter (#36693)
* Fix scroll logic for non-scrollable content to prevent jitter

* one thing

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-11-29 02:21:15 -08:00
Shane Smiskol 22003fd10a rl.BLANK 2025-11-29 02:15:38 -08:00
Shane Smiskol 088fc1cab1 Unified label: add scrolling (#36717)
* almost

* works!

* clean up

* fix

* trash

* Revert "trash"

This reverts commit 951d63382810d444fe08103f406a8c490cfcbe25.

* fix some bugs and use

* clean up

* clean up

* fix clipping

* clean up

* fix
2025-11-29 02:15:10 -08:00
Shane Smiskol cb718618d1 fix multi option dialog text centering 2025-11-29 02:12:09 -08:00
Shane Smiskol d6de3572ca UnifiedLabel: split render (#36719)
* split

* rect
2025-11-29 01:26:17 -08:00
Shane Smiskol d8c316faef Fix wifi settings NavWidget 2025-11-29 00:56:43 -08:00
Shane Smiskol 65f18c363b Mici advanced network settings (#36716)
* add back

* forgot

* clean up
2025-11-28 23:41:55 -08:00
Shane Smiskol c32e2898ac mici: split wifi and network settings (#36715)
* split

* clean up

* better
2025-11-28 23:29:13 -08:00
Harald Schäfer d3532d7d6f URLFile: catch more (#36712)
* catch

* linter has a point
2025-11-28 17:25:54 -08:00
Jason Young f07a40deb4 regen CARS.md (#36711) 2025-11-28 13:08:07 -05:00
Dean Lee 1052435391 ui: speed up mici/AugmentedRoadView by optimizing _calc_frame_matrix caching (#36669)
speed up AugmentedRoadView by optimizing _calc_frame_matrix caching
2025-11-27 05:58:53 -08:00
Shane Smiskol ce596424cf Fix steering arc artifacts (#36707)
* fix arc artifacts

* works but how

* also this

* Revert "also this"

This reverts commit e8d5ed9af15568dcb178dd6da7a14d2c6191010e.

* clean up

* nl

* clean up

* more

* print

* print
2025-11-27 04:16:38 -08:00
Shane Smiskol 3959200a5b Scroll panel 2: use float for offset (#36705)
* use float internally

* use it everywhere -- this fixes all the problemS?!

* round it everywhere

* this looks so much better than before

* rm
2025-11-27 03:25:30 -08:00
Dean Lee f8d0f22344 ui: ensure auto-scroll stops correctly near target (#36686)
ensure auto-scroll stops correctly near target
2025-11-27 03:22:15 -08:00
Calvin Park 0a0fadb16a Skip onboarding on PC (#36688)
* Skip onboarding on PC

* do this instead

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-11-27 02:44:13 -08:00
Dean Lee d0489062b5 ui: remove unused members and variables (#36677)
remove unused members and variables
2025-11-27 02:28:51 -08:00
Dean Lee 630e14fd7f ui: avoid unnecessary text cache invalidation in UnifiedLabel (#36676)
avoid unnecessary text cache invalidation in UnifiedLabel
2025-11-27 02:28:13 -08:00
Najib Muhammad 394f580f16 fix the CI Weekly Report workflow so it does not fail on forks (#36664) 2025-11-27 02:26:29 -08:00
Dean Lee 4ef82c4119 ui: optimize matrix operations in scroller rendering (#36668)
optimize matrix operations
2025-11-27 02:20:49 -08:00
Dean Lee 4bd6fb0995 ui: fix unconditional rl.end_scissor_mode() call in MiciLabel (#36660)
fix incorrect end_scissor_mode usage
2025-11-27 02:17:16 -08:00
Logesh R ae534ddeab docs: Fix "Turn the speed blue" tutorial for Raylib UI (#36591)
* docs: Fix "Turn the speed blue" tutorial for Raylib UI

* just

* obv

* not replay

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-11-27 02:07:56 -08:00
David ae6ada4162 lint: Add PLE rule to ruff (#36595)
* update linting rules to include new PLE (pylint error) rule

* fix lint error
2025-11-27 01:52:25 -08:00
Dean Lee b8d55987c2 ui: extract and optimize mouse event processing (#36564)
* extract and optimize mouse event processing

* rm slot

* merge mici mastere

* add mouse

---------

Co-authored-by: Shane Smiskol <shane@smiskol.com>
2025-11-27 01:50:36 -08:00
Shane Smiskol 26261387f8 Fix raylib ui spamming API calls (#36700)
* intern

* start

* move

* common caching

* use constant for slep

* works

* add gating back

* clean up

* more

* match cache logic

* hate this circular

* not needed since sync

* no need for lock?

* even qt had something like _load_initial_state for tests, keep

* clean up

* clean up

* clean up

* loading json as string works, else it will fail to parse json, catch that and log, and next api call will overwrite

* move over firehose

* clean up

* fix test

* no

* flip

* more

* match qt

* consistent

* clean up

* cmt

* fix test!
2025-11-27 01:37:16 -08:00
Shane Smiskol 946fd3f387 NavWidget: draw black above top of widget when dismissing (#36702)
draw rec
2025-11-27 01:00:33 -08:00
Shane Smiskol 50a797b0be De-duplicate firehose layout (#36703)
* Reapply "De-duplicate firehose layout (#36701)"

This reverts commit 302e448b93.

* fix

* was here
2025-11-27 01:00:03 -08:00
Shane Smiskol 302e448b93 Revert "De-duplicate firehose layout (#36701)"
This reverts commit dd51bf2021.
2025-11-27 00:52:50 -08:00
Shane Smiskol dd51bf2021 De-duplicate firehose layout (#36701)
* consistent name

* dedup

* FMT

* not sure why two
2025-11-27 00:46:33 -08:00
YassineYousfi 49178539f3 dm: DriverProb (#36687)
* wip

* ci

* fix
2025-11-25 18:52:35 -08:00
felsager f01391a7d9 latcontrol_torque: delay independent jerk and lower kp and lower friction threshold (#36619) 2025-11-25 10:23:02 -08:00
Bruce Wayne c67afb45ae dead test 2025-11-24 14:20:20 -08:00
Adeeb Shihadeh d0c3972cc7 update release branches (#36671)
* update release branches

* Update README.md
2025-11-21 18:55:01 -08:00
Adeeb Shihadeh be8c5491b1 even shorter 2025-11-21 14:25:21 -08:00
Adeeb Shihadeh ebc11fdbc8 make "update available" alert clickable (#36670)
* click to update

* that's it

* lil more
2025-11-21 13:44:22 -08:00
Adeeb Shihadeh a981f78e2f use release branch from system.version 2025-11-21 11:23:54 -08:00
527 changed files with 16091 additions and 8470 deletions
+6 -6
View File
@@ -12,12 +12,12 @@ jobs:
issues: write
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: false
# Label PRs
- uses: actions/labeler@v5.0.0
- uses: actions/labeler@v6
with:
dot: true
configuration-path: .github/labeler.yaml
@@ -55,13 +55,13 @@ jobs:
repo: context.repo.repo,
issue_number: prNumber
});
const hasDevC3Label = labels.some(label => label.name === process.env.PR_LABEL);
const hasTrustLabel = labels.some(label => label.name === process.env.TRUST_FORK_PR_LABEL);
console.log(`PR #${prNumber} has ${process.env.PR_LABEL} label: ${hasDevC3Label}`);
console.log(`PR #${prNumber} has ${process.env.TRUST_FORK_PR_LABEL} label: ${hasTrustLabel}`);
core.setOutput('has-dev', hasDevC3Label ? 'true' : 'false');
core.setOutput('has-trust', hasTrustLabel ? 'true' : 'false');
@@ -81,7 +81,7 @@ jobs:
});
console.log(`Removed '${process.env.TRUST_FORK_PR_LABEL}' label from PR #${prNumber} as it received new commits`);
// Add a comment to the PR
await github.rest.issues.createComment({
owner: context.repo.owner,
+1 -1
View File
@@ -17,7 +17,7 @@ jobs:
permissions:
contents: write
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
@@ -140,7 +140,7 @@ jobs:
run: |
echo '${{ needs.setup.outputs.model_matrix }}' > matrix.json
built=(); while IFS= read -r line; do built+=("$line"); done < <(
ls output | sed -E 's/^model-//' | sed -E 's/-[0-9]+$//' | sed -E 's/ \([^)]*\)//' | awk '{gsub(/^ +| +$/, ""); print}'
find output -maxdepth 1 -name 'model-*' -printf "%f\n" | sed -E 's/^model-//' | sed -E 's/-[0-9]+$//' | sed -E 's/ \([^)]*\)//' | awk '{gsub(/^ +| +$/, ""); print}'
)
jq -c --argjson built "$(printf '%s\n' "${built[@]}" | jq -R . | jq -s .)" \
'map(select(.display_name as $n | ($built | index($n | gsub("^ +| +$"; "")) | not)))' matrix.json > retry_matrix.json
@@ -168,6 +168,7 @@ jobs:
if: ${{ !cancelled() && (needs.get_and_build.result != 'failure' || needs.retry_get_and_build.result == 'success' || (needs.retry_failed_models.outputs.retry_matrix != '[]' && needs.retry_failed_models.outputs.retry_matrix != '')) }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
model: ${{ fromJson(needs.setup.outputs.model_matrix) }}
+2 -2
View File
@@ -38,10 +38,10 @@ jobs:
report:
needs: [ci_matrix_run]
runs-on: ubuntu-latest
if: always()
if: always() && github.repository == 'commaai/openpilot'
steps:
- name: Get job results
uses: actions/github-script@v7
uses: actions/github-script@v8
id: get-job-results
with:
script: |
+2 -2
View File
@@ -22,7 +22,7 @@ jobs:
steps:
- uses: commaai/timeout@v1
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
@@ -34,7 +34,7 @@ jobs:
mkdocs build
# Push to docs.comma.ai
- uses: actions/checkout@v4
- uses: actions/checkout@v6
if: github.ref == 'refs/heads/master' && github.repository == 'sunnypilot/sunnypilot'
with:
path: openpilot-docs
+41 -4
View File
@@ -5,7 +5,44 @@ on:
types: [created, edited]
jobs:
# TODO: gc old branches in a separate job in this workflow
cleanup-branches:
runs-on: ubuntu-latest
permissions:
contents: write
steps:
- name: Delete stale Jenkins branches
uses: actions/github-script@v8
with:
script: |
const cutoff = Date.now() - 24 * 60 * 60 * 1000;
const prefixes = ['tmp-jenkins', '__jenkins'];
for await (const response of github.paginate.iterator(github.rest.repos.listBranches, {
owner: context.repo.owner,
repo: context.repo.repo,
per_page: 100,
})) {
for (const branch of response.data) {
if (!prefixes.some(p => branch.name.startsWith(p))) continue;
const { data: commit } = await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: branch.commit.sha,
});
const commitDate = new Date(commit.commit.committer.date).getTime();
if (commitDate < cutoff) {
console.log(`Deleting branch: ${branch.name} (last commit: ${commit.commit.committer.date})`);
await github.rest.git.deleteRef({
owner: context.repo.owner,
repo: context.repo.repo,
ref: `heads/${branch.name}`,
});
}
}
}
scan-comments:
runs-on: ubuntu-latest
if: ${{ github.event.issue.pull_request }}
@@ -15,7 +52,7 @@ jobs:
steps:
- name: Check for trigger phrase
id: check_comment
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
const triggerPhrase = "trigger-jenkins";
@@ -35,7 +72,7 @@ jobs:
- name: Checkout repository
if: steps.check_comment.outputs.result == 'true'
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: refs/pull/${{ github.event.issue.number }}/head
@@ -49,7 +86,7 @@ jobs:
- name: Delete trigger comment
if: steps.check_comment.outputs.result == 'true' && always()
uses: actions/github-script@v7
uses: actions/github-script@v8
with:
script: |
await github.rest.issues.deleteComment({
@@ -0,0 +1,151 @@
name: "mici raylib ui preview"
on:
push:
branches:
- master
pull_request_target:
types: [assigned, opened, synchronize, reopened, edited]
branches:
- 'master'
paths:
- 'selfdrive/assets/**'
- 'selfdrive/ui/**'
- 'system/ui/**'
workflow_dispatch:
env:
UI_JOB_NAME: "Create mici raylib UI Report"
REPORT_NAME: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
SHA: ${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && github.sha || github.event.pull_request.head.sha }}
BRANCH_NAME: "openpilot/pr-${{ github.event.number }}-mici-raylib-ui"
MASTER_BRANCH_NAME: "openpilot_master_ui_mici_raylib"
# All report files are pushed here
REPORT_FILES_BRANCH_NAME: "mici-raylib-ui-reports"
jobs:
preview:
if: github.repository == 'sunnypilot/sunnypilot'
name: preview
runs-on: ubuntu-latest
timeout-minutes: 20
permissions:
contents: read
pull-requests: write
actions: read
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Waiting for ui generation to end
uses: lewagon/wait-on-check-action@v1.3.4
with:
ref: ${{ env.SHA }}
check-name: ${{ env.UI_JOB_NAME }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
allowed-conclusions: success
wait-interval: 20
- name: Getting workflow run ID
id: get_run_id
run: |
echo "run_id=$(curl https://api.github.com/repos/${{ github.repository }}/commits/${{ env.SHA }}/check-runs | jq -r '.check_runs[] | select(.name == "${{ env.UI_JOB_NAME }}") | .html_url | capture("(?<number>[0-9]+)") | .number')" >> $GITHUB_OUTPUT
- name: Getting proposed ui # filename: pr_ui/mici_ui_replay.mp4
id: download-artifact
uses: dawidd6/action-download-artifact@v6
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ steps.get_run_id.outputs.run_id }}
search_artifacts: true
name: mici-raylib-report-1-${{ env.REPORT_NAME }}
path: ${{ github.workspace }}/pr_ui
- name: Getting master ui # filename: master_ui_raylib/mici_ui_replay.mp4
uses: actions/checkout@v6
with:
repository: sunnypilot/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/master_ui_raylib
ref: ${{ env.MASTER_BRANCH_NAME }}
- name: Saving new master ui
if: github.ref == 'refs/heads/master' && github.event_name == 'push'
working-directory: ${{ github.workspace }}/master_ui_raylib
run: |
git checkout --orphan=new_master_ui_mici_raylib
git rm -rf *
git branch -D ${{ env.MASTER_BRANCH_NAME }}
git branch -m ${{ env.MASTER_BRANCH_NAME }}
git config user.name "GitHub Actions Bot"
git config user.email "<>"
mv ${{ github.workspace }}/pr_ui/* .
git add .
git commit -m "mici raylib video for commit ${{ env.SHA }}"
git push origin ${{ env.MASTER_BRANCH_NAME }} --force
- name: Setup FFmpeg
uses: AnimMouse/setup-ffmpeg@ae28d57dabbb148eff63170b6bf7f2b60062cbae
- name: Finding diff
if: github.event_name == 'pull_request_target'
id: find_diff
run: |
# Find the video file from PR
pr_video="${{ github.workspace }}/pr_ui/mici_ui_replay_proposed.mp4"
mv "${{ github.workspace }}/pr_ui/mici_ui_replay.mp4" "$pr_video"
master_video="${{ github.workspace }}/pr_ui/mici_ui_replay_master.mp4"
mv "${{ github.workspace }}/master_ui_raylib/mici_ui_replay.mp4" "$master_video"
# Run report
export PYTHONPATH=${{ github.workspace }}
baseurl="https://github.com/sunnypilot/ci-artifacts/raw/refs/heads/${{ env.BRANCH_NAME }}"
diff_exit_code=0
python3 ${{ github.workspace }}/selfdrive/ui/tests/diff/diff.py "${{ github.workspace }}/pr_ui/mici_ui_replay_master.mp4" "${{ github.workspace }}/pr_ui/mici_ui_replay_proposed.mp4" "diff.html" --basedir "$baseurl" --no-open || diff_exit_code=$?
# Copy diff report files
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.html ${{ github.workspace }}/pr_ui/
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.mp4 ${{ github.workspace }}/pr_ui/
REPORT_URL="https://sunnypilot.github.io/ci-artifacts/diff_pr_${{ github.event.number }}.html"
if [ $diff_exit_code -eq 0 ]; then
DIFF="✅ Videos are identical! [View Diff Report]($REPORT_URL)"
else
DIFF="❌ <strong>Videos differ!</strong> [View Diff Report]($REPORT_URL)"
fi
echo "DIFF=$DIFF" >> "$GITHUB_OUTPUT"
- name: Saving proposed ui
if: github.event_name == 'pull_request_target'
working-directory: ${{ github.workspace }}/master_ui_raylib
run: |
# Overwrite PR branch w/ proposed ui, and master ui at this point in time for future reference
git config user.name "GitHub Actions Bot"
git config user.email "<>"
git checkout --orphan=${{ env.BRANCH_NAME }}
git rm -rf *
mv ${{ github.workspace }}/pr_ui/* .
git add .
git commit -m "mici raylib video for PR #${{ github.event.number }}"
git push origin ${{ env.BRANCH_NAME }} --force
# Append diff report to report files branch
git fetch origin ${{ env.REPORT_FILES_BRANCH_NAME }}
git checkout ${{ env.REPORT_FILES_BRANCH_NAME }}
cp ${{ github.workspace }}/selfdrive/ui/tests/diff/report/diff.html diff_pr_${{ github.event.number }}.html
git add diff_pr_${{ github.event.number }}.html
git commit -m "mici raylib ui diff report for PR #${{ github.event.number }}" || echo "No changes to commit"
git push origin ${{ env.REPORT_FILES_BRANCH_NAME }}
- name: Comment Video on PR
if: github.event_name == 'pull_request_target'
uses: thollander/actions-comment-pull-request@v2
with:
message: |
<!-- _(run_id_video_mici_raylib **${{ github.run_id }}**)_ -->
## mici raylib UI Preview
${{ steps.find_diff.outputs.DIFF }}
comment_tag: run_id_video_mici_raylib
pr_number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+2 -2
View File
@@ -16,9 +16,9 @@ jobs:
if: github.repository == 'commaai/openpilot'
steps:
- name: Checkout
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Checkout master
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
ref: master
path: base
+1 -1
View File
@@ -29,7 +29,7 @@ jobs:
running-workflow-name: 'build prebuilt'
repo-token: ${{ secrets.GITHUB_TOKEN }}
check-regexp: ^((?!.*(build master-ci).*).)*$
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- run: git lfs pull
+1 -1
View File
@@ -58,7 +58,7 @@ jobs:
path: ${{ github.workspace }}/pr_ui
- name: Getting master ui
uses: actions/checkout@v4
uses: actions/checkout@v6
with:
repository: sunnypilot/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
+1 -1
View File
@@ -30,7 +30,7 @@ jobs:
running-workflow-name: 'build __nightly'
repo-token: ${{ secrets.GITHUB_TOKEN }}
check-regexp: ^((?!.*(build prebuilt).*).)*$
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
fetch-depth: 0
+20 -7
View File
@@ -8,20 +8,20 @@ on:
env:
BASE_IMAGE: sunnypilot-base
BUILD: release/ci/docker_build_sp.sh base
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
jobs:
update_translations:
runs-on: ubuntu-latest
if: github.repository == 'sunnypilot/sunnypilot'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- uses: ./.github/workflows/setup-with-retry
- name: Update translations
run: |
${{ env.RUN }} "python3 selfdrive/ui/update_translations.py --vanish"
- name: Create Pull Request
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
commit-message: "Update translations"
@@ -39,18 +39,26 @@ jobs:
image: ghcr.io/sunnypilot/sunnypilot-base:latest
if: github.repository == 'sunnypilot/sunnypilot'
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- name: uv lock
if: github.repository == 'commaai/openpilot'
run: |
python3 -m ensurepip --upgrade
pip3 install uv
uv lock --upgrade
- name: uv pip tree
id: pip_tree
run: |
echo 'PIP_TREE<<EOF' >> $GITHUB_OUTPUT
uv pip tree >> $GITHUB_OUTPUT
echo 'EOF' >> $GITHUB_OUTPUT
- name: bump submodules
run: |
git config --global --add safe.directory '*'
git config submodule.msgq.update none
git config submodule.rednose_repo.update none
git config submodule.teleoprtc_repo.update none
git config submodule.tinygrad.update none
git submodule update --remote
git add .
@@ -61,7 +69,7 @@ jobs:
python selfdrive/car/docs.py
git add docs/CARS.md
- name: Create Pull Request
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0
with:
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
token: ${{ github.repository == 'commaai/openpilot' && secrets.ACTIONS_CREATE_PR_PAT || secrets.GITHUB_TOKEN }}
@@ -70,5 +78,10 @@ jobs:
branch: auto-package-updates
base: master
delete-branch: true
body: 'Automatic PR from repo-maintenance -> package_updates'
body: |
Automatic PR from repo-maintenance -> package_updates
```
${{ steps.pip_tree.outputs.PIP_TREE }}
```
labels: bot
+2 -2
View File
@@ -13,7 +13,7 @@ jobs:
stale:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
exempt-all-milestones: true
@@ -34,7 +34,7 @@ jobs:
stale_drafts:
runs-on: ubuntu-latest
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
exempt-all-milestones: true
@@ -200,37 +200,28 @@ jobs:
sudo rm -rf ${OUTPUT_DIR}
mkdir -p ${OUTPUT_DIR}
rsync -am${RUNNER_DEBUG:+v} \
--include='**/panda/board/' \
--include='**/panda/board/obj' \
--include='**/panda/board/obj/panda.bin.signed' \
--include='**/panda/board/obj/panda_h7.bin.signed' \
--include='**/panda/board/obj/bootstub.panda.bin' \
--include='**/panda/board/obj/bootstub.panda_h7.bin' \
--exclude='.sconsign.dblite' \
--exclude='*.a' \
--exclude='*.o' \
--exclude='*.os' \
--exclude='*.pyc' \
--exclude='moc_*' \
--exclude='*.cc' \
--exclude='__pycache__' \
--exclude='Jenkinsfile' \
--exclude='supercombo.onnx' \
--exclude='**/panda/board/*' \
--exclude='**/panda/board/obj/**' \
--exclude='**/panda/certs/' \
--exclude='**/panda/crypto/' \
--exclude='**/release/' \
--exclude='**/.github/' \
--exclude='**/selfdrive/ui/replay/' \
--exclude='**/__pycache__/' \
--exclude='**/selfdrive/ui/*.h' \
--exclude='**/selfdrive/ui/**/*.h' \
--exclude='**/selfdrive/ui/qt/offroad/sunnypilot/' \
--exclude='${{env.SCONS_CACHE_DIR}}' \
--exclude='**/.git/' \
--exclude='**/SConstruct' \
--exclude='**/SConscript' \
--exclude='**/.venv/' \
--exclude='selfdrive/modeld/models/driving_vision.onnx' \
--exclude='selfdrive/modeld/models/driving_policy.onnx' \
--exclude='sunnypilot/modeld*/models/supercombo.onnx' \
--exclude='third_party/*x86*' \
--exclude='third_party/*Darwin*' \
--delete-excluded \
--chown=comma:comma \
${BUILD_DIR}/ ${OUTPUT_DIR}/
@@ -49,6 +49,7 @@ jobs:
with:
fetch-depth: 0 # Fetch all history for all branches
token: ${{ secrets.GITHUB_TOKEN }}
persist-credentials: false
- name: Wait for Tests
uses: ./.github/workflows/wait-for-action # Path to where you place the action
@@ -173,10 +174,37 @@ jobs:
echo ' pushurl = ${{ env.LFS_PUSH_URL }}' >> .lfsconfig
echo ' locksverify = false' >> .lfsconfig
- name: Push changes if there are diffs
id: push-changes # Add an id so we can reference this step
- name: Restore workflows from source
run: |
TARGET_BRANCH="${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}"
SOURCE_BRANCH="${{ inputs.source_branch || env.DEFAULT_SOURCE_BRANCH }}"
# Ensure we are on the target branch
git checkout $TARGET_BRANCH
echo "Restoring .github/workflows from $SOURCE_BRANCH"
git checkout origin/$SOURCE_BRANCH -- .github/workflows
if ! git diff --cached --quiet; then
echo "Workflows differ. Committing restoration."
git commit -m "chore: restore .github/workflows from $SOURCE_BRANCH"
else
echo "Workflows match $SOURCE_BRANCH."
fi
- uses: actions/create-github-app-token@v2
id: ci-token
with:
app-id: ${{ secrets.CI_GITHUB_ACTIONS_TOKEN_APP_ID }}
private-key: ${{ secrets.CI_GITHUB_ACTIONS_TOKEN_APP_PRIVATE_KEY }}
- name: Push changes if there are diffs
id: push-changes
run: |
TARGET_BRANCH="${{ inputs.target_branch || env.DEFAULT_TARGET_BRANCH }}"
# Use the App Token to set the remote URL with authentication
git remote set-url origin "https://x-access-token:${{ steps.ci-token.outputs.token }}@github.com/${{ github.repository }}.git"
# Fetch the latest from remote
git fetch origin $TARGET_BRANCH
@@ -188,7 +216,7 @@ jobs:
exit 0
fi
# If we get here, there are diffs, so push
# Push with the authenticated origin
if ! git push origin $TARGET_BRANCH --force; then
echo "Failed to push changes to $TARGET_BRANCH"
exit 1
+64 -23
View File
@@ -20,12 +20,10 @@ concurrency:
env:
PYTHONWARNINGS: error
BASE_IMAGE: sunnypilot-base
AZURE_TOKEN: ${{ secrets.AZURE_COMMADATACI_OPENPILOTCI_TOKEN }}
DOCKER_LOGIN: docker login ghcr.io -u ${{ github.actor }} -p ${{ secrets.GITHUB_TOKEN }}
BUILD: release/ci/docker_build_sp.sh base
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e FILEREADER_CACHE=1 -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
RUN: docker run --shm-size 2G -v $PWD:/tmp/openpilot -w /tmp/openpilot -e CI=1 -e PYTHONWARNINGS=error -e PYTHONPATH=/tmp/openpilot -e NUM_JOBS -e JOB_ID -e GITHUB_ACTION -e GITHUB_REF -e GITHUB_HEAD_REF -e GITHUB_SHA -e GITHUB_REPOSITORY -e GITHUB_RUN_ID -v $GITHUB_WORKSPACE/.ci_cache/scons_cache:/tmp/scons_cache -v $GITHUB_WORKSPACE/.ci_cache/comma_download_cache:/tmp/comma_download_cache -v $GITHUB_WORKSPACE/.ci_cache/openpilot_cache:/tmp/openpilot_cache $BASE_IMAGE /bin/bash -c
PYTEST: pytest --continue-on-collection-errors --durations=0 -n logical
@@ -41,7 +39,7 @@ jobs:
env:
STRIPPED_DIR: /tmp/releasepilot
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- name: Getting LFS files
@@ -93,7 +91,7 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- name: Setup docker push
@@ -107,22 +105,22 @@ jobs:
build_mac:
name: build macOS
if: false # tmp disable due to brew install not working
runs-on: ${{ ((github.repository == 'commaai/openpilot') && ((github.event_name != 'pull_request') || (github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))) && 'namespace-profile-macos-8x14' || 'macos-latest' }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- run: echo "CACHE_COMMIT_DATE=$(git log -1 --pretty='format:%cd' --date=format:'%Y-%m-%d-%H:%M')" >> $GITHUB_ENV
- name: Homebrew cache
uses: ./.github/workflows/auto-cache
if: false # disabling the cache for now because it is breaking macos builds...
with:
save: false # No need save here if we manually save it later conditionally
path: ~/Library/Caches/Homebrew
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
key: brew-macos-${{ hashFiles('tools/Brewfile') }}-${{ github.sha }}
restore-keys: |
brew-macos-${{ env.CACHE_COMMIT_DATE }}
brew-macos
brew-macos-${{ hashFiles('tools/Brewfile') }}
brew-macos-
- name: Install dependencies
run: ./tools/mac_setup.sh
env:
@@ -133,7 +131,7 @@ jobs:
if: github.ref == 'refs/heads/master'
with:
path: ~/Library/Caches/Homebrew
key: brew-macos-${{ env.CACHE_COMMIT_DATE }}-${{ github.sha }}
key: brew-macos-${{ hashFiles('tools/Brewfile') }}-${{ github.sha }}
- run: git lfs pull
- name: Getting scons cache
uses: ./.github/workflows/auto-cache
@@ -164,7 +162,7 @@ jobs:
env:
PYTHONWARNINGS: default
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
@@ -181,7 +179,7 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
@@ -207,22 +205,23 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
id: setup-step
- name: Cache test routes
id: dependency-cache
uses: actions/cache@v4
uses: actions/cache@v5
with:
path: .ci_cache/comma_download_cache
key: proc-replay-${{ hashFiles('selfdrive/test/process_replay/ref_commit', 'selfdrive/test/process_replay/test_processes.py') }}
key: proc-replay-${{ hashFiles('selfdrive/test/process_replay/test_processes.py') }}
- name: Build openpilot
run: |
${{ env.RUN }} "scons -j$(nproc)"
- name: Run replay
timeout-minutes: ${{ contains(runner.name, 'nsc') && (steps.dependency-cache.outputs.cache-hit == 'true') && ((steps.setup-step.outputs.duration < 18) && 1 || 2) || 20 }}
continue-on-error: ${{ github.ref == 'refs/heads/master' }}
run: |
${{ env.RUN }} "selfdrive/test/process_replay/test_processes.py -j$(nproc) && \
chmod -R 777 /tmp/comma_download_cache"
@@ -230,16 +229,32 @@ jobs:
id: print-diff
if: always()
run: cat selfdrive/test/process_replay/diff.txt
- uses: actions/upload-artifact@v4
- uses: actions/upload-artifact@v6
if: always()
continue-on-error: true
with:
name: process_replay_diff.txt
path: selfdrive/test/process_replay/diff.txt
- name: Upload reference logs
if: false # TODO: move this to github instead of azure
- name: Checkout ci-artifacts
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
uses: actions/checkout@v4
with:
repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
path: ${{ github.workspace }}/ci-artifacts
- name: Push refs
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
working-directory: ${{ github.workspace }}/ci-artifacts
run: |
${{ env.RUN }} "unset PYTHONWARNINGS && AZURE_TOKEN='$AZURE_TOKEN' python3 selfdrive/test/process_replay/test_processes.py -j$(nproc) --upload-only"
git checkout --orphan process-replay
git rm -rf .
git config user.name "GitHub Actions Bot"
git config user.email "<>"
cp ${{ github.workspace }}/selfdrive/test/process_replay/fakedata/*.zst .
echo "${{ github.sha }}" > ref_commit
git add .
git commit -m "process-replay refs for ${{ github.repository }}@${{ github.sha }}"
git push origin process-replay --force
- name: Run regen
if: false
timeout-minutes: 4
@@ -257,7 +272,7 @@ jobs:
|| fromJSON('["ubuntu-24.04"]') }}
if: false # FIXME: Started to timeout recently
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
@@ -281,7 +296,7 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
@@ -293,7 +308,33 @@ jobs:
source selfdrive/test/setup_xvfb.sh &&
python3 selfdrive/ui/tests/test_ui/raylib_screenshots.py"
- name: Upload Raylib UI Report
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: raylib-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/test_ui/raylib_report/screenshots
create_mici_raylib_ui_report:
name: Create mici raylib UI Report
runs-on: ${{
(github.repository == 'commaai/openpilot') &&
((github.event_name != 'pull_request') ||
(github.event.pull_request.head.repo.full_name == 'commaai/openpilot'))
&& fromJSON('["namespace-profile-amd64-8x16", "namespace-experiments:docker.builds.local-cache=separate"]')
|| fromJSON('["ubuntu-24.04"]') }}
steps:
- uses: actions/checkout@v6
with:
submodules: true
- uses: ./.github/workflows/setup-with-retry
- name: Build openpilot
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Create mici raylib UI Report
run: >
${{ env.RUN }} "PYTHONWARNINGS=ignore &&
source selfdrive/test/setup_xvfb.sh &&
WINDOWED=1 python3 selfdrive/ui/tests/diff/replay.py"
- name: Upload Raylib UI Report
uses: actions/upload-artifact@v6
with:
name: mici-raylib-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/diff/report
+51
View File
@@ -0,0 +1,51 @@
name: vendor third_party
on:
workflow_dispatch:
jobs:
build:
if: github.ref != 'refs/heads/master'
strategy:
matrix:
os: [ubuntu-24.04, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v6
with:
submodules: true
- name: Build
run: third_party/build.sh
- name: Package artifacts
run: |
git add -A third_party/
git diff --cached --name-only -- third_party/ | tar -cf /tmp/third_party_build.tar -T -
- uses: actions/upload-artifact@v4
with:
name: third-party-${{ runner.os }}
path: /tmp/third_party_build.tar
commit:
needs: build
runs-on: ubuntu-24.04
permissions:
contents: write
steps:
- uses: actions/checkout@v6
- uses: actions/download-artifact@v4
with:
path: /tmp/artifacts
- name: Commit vendored libraries
run: |
for f in /tmp/artifacts/*/third_party_build.tar; do
tar xf "$f"
done
git add third_party/
if git diff --cached --quiet; then
echo "No changes to commit"
exit 0
fi
git config user.name "github-actions[bot]"
git config user.email "github-actions[bot]@users.noreply.github.com"
git commit -m "third_party: rebuild vendor libraries"
git push
+5
View File
@@ -99,6 +99,11 @@ Pipfile
.history
.ionide
.claude/
.context/
PLAN.md
TASK.md
### JetBrains ###
!.idea/customTargets.xml
!.idea/tools/*
+1 -1
View File
@@ -15,7 +15,7 @@
url = https://github.com/commaai/teleoprtc
[submodule "tinygrad"]
path = tinygrad_repo
url = https://github.com/commaai/tinygrad.git
url = https://github.com/sunnypilot/tinygrad.git
[submodule "sunnypilot/neural_network_data"]
path = sunnypilot/neural_network_data
url = https://github.com/sunnypilot/neural-network-data.git
+3 -1
View File
@@ -9,4 +9,6 @@ WORKDIR ${OPENPILOT_PATH}
COPY . ${OPENPILOT_PATH}/
RUN scons --cache-readonly -j$(nproc)
ENV UV_BIN="/home/batman/.local/bin/"
ENV PATH="$UV_BIN:$PATH"
RUN UV_PROJECT_ENVIRONMENT=$VIRTUAL_ENV uv run scons --cache-readonly -j$(nproc)
Vendored
+1 -1
View File
@@ -22,7 +22,7 @@ shopt -s huponexit # kill all child processes when the shell exits
export CI=1
export PYTHONWARNINGS=error
export LOGPRINT=debug
#export LOGPRINT=debug # this has gotten too spammy...
export TEST_DIR=${env.TEST_DIR}
export SOURCE_DIR=${env.SOURCE_DIR}
export GIT_BRANCH=${env.GIT_BRANCH}
+2 -58
View File
@@ -11,66 +11,10 @@ Join the official sunnypilot community forum to stay up to date with all the lat
https://docs.sunnypilot.ai/ is your one stop shop for everything from features to installation to FAQ about the sunnypilot
## 🚘 Running on a dedicated device in a car
* A supported device to run this software
* a [comma three](https://comma.ai/shop/products/three) or a [C3X](https://comma.ai/shop/comma-3x)
* This software
* One of [the 325+ supported cars](https://github.com/sunnypilot/sunnypilot/blob/master/docs/CARS.md). We support Honda, Toyota, Hyundai, Nissan, Kia, Chrysler, Lexus, Acura, Audi, VW, Ford, and more. If your car is not supported but has adaptive cruise control and lane-keeping assist, it's likely able to run sunnypilot.
* A [car harness](https://comma.ai/shop/products/car-harness) to connect to your car
Detailed instructions for [how to mount the device in a car](https://comma.ai/setup).
First, check out this list of items you'll need to [get started](https://community.sunnypilot.ai/t/getting-started-using-sunnypilot-in-your-supported-car/251).
## Installation
Please refer to [Recommended Branches](#recommended-branches) to find your preferred/supported branch. This guide will assume you want to install the latest `staging` branch.
### If you want to use our newest branches (our rewrite)
> [!TIP]
>You can see the rewrite state on our [rewrite project board](https://github.com/orgs/sunnypilot/projects/2), and to install the new branches, you can use the following links
* sunnypilot not installed or you installed a version before 0.8.17?
1. [Factory reset/uninstall](https://github.com/commaai/openpilot/wiki/FAQ#how-can-i-reset-the-device) the previous software if you have another software/fork installed.
2. After factory reset/uninstall and upon reboot, select `Custom Software` when given the option.
3. Input the installation URL per [Recommended Branches](#recommended-branches). Example: ```https://staging.sunnypilot.ai```.
4. Complete the rest of the installation following the onscreen instructions.
* sunnypilot already installed and you installed a version after 0.8.17?
1. On the comma three/3X, go to `Settings` ▶️ `Software`.
2. At the `Download` option, press `CHECK`. This will fetch the list of latest branches from sunnypilot.
3. At the `Target Branch` option, press `SELECT` to open the Target Branch selector.
4. Scroll to select the desired branch per Recommended Branches (see below). Example: `staging`
### Recommended Branches
| Branch | Installation URL |
|:---------------:|:---------------------------------------------:|
| `release` | `https://release.sunnypilot.ai` |
| `staging` | `https://staging.sunnypilot.ai` |
| `dev` | `https://dev.sunnypilot.ai` |
| `custom-branch` | `https://install.sunnypilot.ai/{branch_name}` |
> [!TIP]
> You can use sunnypilot/targetbranch as an install URL. Example: 'sunnypilot/staging'.
> [!NOTE]
> Do you require further assistance with software installation? Join the [sunnypilot community forum](https://community.sunnypilot.ai/new-topic?category=general/qa) and create a topic in the General/Q&A Category channel.
<details>
<summary>Older legacy branches</summary>
### If you want to use our older legacy branches (*not recommended*)
> [**IMPORTANT**]
> It is recommended to [re-flash AGNOS](https://flash.comma.ai/) if you intend to downgrade from the new branches.
> You can still restore the latest sunnylink backup made on the old branches.
| Branch | Installation URL |
|:------------:|:--------------------------------:|
| `release-c3` | https://release-c3.sunnypilot.ai |
| `staging-c3` | https://staging-c3.sunnypilot.ai |
| `dev-c3` | https://dev-c3.sunnypilot.ai |
</details>
Next, refer to the sunnypilot community forum for [installation instructions](https://community.sunnypilot.ai/t/read-before-installing-sunnypilot/254), as well as a complete list of [Recommended Branch Installations](https://community.sunnypilot.ai/t/recommended-branch-installations/235).
## 🎆 Pull Requests
We welcome both pull requests and issues on GitHub. Bug fixes are encouraged.
+13
View File
@@ -1,3 +1,16 @@
Version 0.10.4 (2026-02-17)
========================
* Lexus LS 2018 support thanks to Hacheoy!
Version 0.10.3 (2025-12-17)
========================
* New driving model #36249
* New temporal policy architecture
* New on-policy training physics noise model
* New driver monitoring model #36409
* Trained on a new dataset, including comma four data
* Improved inter-process communication memory efficiency
Version 0.10.2 (2025-11-19)
========================
* comma four support
-2
View File
@@ -14,7 +14,6 @@ Decider('MD5-timestamp')
SetOption('num_jobs', max(1, int(os.cpu_count()/2)))
AddOption('--kaitai', action='store_true', help='Regenerate kaitai struct parsers')
AddOption('--asan', action='store_true', help='turn on ASAN')
AddOption('--ubsan', action='store_true', help='turn on UBSan')
AddOption('--mutation', action='store_true', help='generate mutation-ready code')
@@ -203,7 +202,6 @@ SConscript(['rednose/SConscript'])
# Build system services
SConscript([
'system/ubloxd/SConscript',
'system/loggerd/SConscript',
])
+1 -1
View File
@@ -13,7 +13,7 @@ cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in schema_files])
# Build messaging
services_h = env.Command(['services.h'], ['services.py'], 'python3 ' + cereal_dir.path + '/services.py > $TARGET')
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc'], LIBS=[msgq, common, 'pthread'])
env.Program('messaging/bridge', ['messaging/bridge.cc', 'messaging/msgq_to_zmq.cc', 'messaging/bridge_zmq.cc'], LIBS=[msgq, common, 'pthread'])
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
+1
View File
@@ -153,6 +153,7 @@ struct ModelManagerSP @0xaedffd8f31e7b55d {
navigation @1;
vision @2;
policy @3;
offPolicy @4;
}
}
+9 -3
View File
@@ -87,6 +87,7 @@ struct OnroadEvent @0xc4fa6047f024e718 {
laneChange @50;
lowMemory @51;
stockAeb @52;
stockLkas @98;
ldw @53;
carUnrecognized @54;
invalidLkasSetting @55;
@@ -1477,6 +1478,11 @@ struct ProcLog {
cmdline @15 :List(Text);
exe @16 :Text;
# from /proc/<pid>/smaps_rollup (proportional/private memory)
memPss @17 :UInt64; # Pss — shared pages split by mapper count
memPssAnon @18 :UInt64; # Pss_Anon — private anonymous (heap, stack)
memPssShmem @19 :UInt64; # Pss_Shmem — proportional MSGQ/tmpfs share
}
struct CPUTimes {
@@ -2524,13 +2530,10 @@ struct Event {
controlsState @7 :ControlsState;
selfdriveState @130 :SelfdriveState;
gyroscope @99 :SensorEventData;
gyroscope2 @100 :SensorEventData;
accelerometer @98 :SensorEventData;
accelerometer2 @101 :SensorEventData;
magnetometer @95 :SensorEventData;
lightSensor @96 :SensorEventData;
temperatureSensor @97 :SensorEventData;
temperatureSensor2 @123 :SensorEventData;
pandaStates @81 :List(PandaState);
peripheralState @80 :PeripheralState;
radarState @13 :RadarState;
@@ -2693,5 +2696,8 @@ struct Event {
liveLocationKalman @72 :LiveLocationKalman;
liveTracksDEPRECATED @16 :List(LiveTracksDEPRECATED);
onroadEventsDEPRECATED @68: List(Car.OnroadEventDEPRECATED);
gyroscope2DEPRECATED @100 :SensorEventData;
accelerometer2DEPRECATED @101 :SensorEventData;
temperatureSensor2DEPRECATED @123 :SensorEventData;
}
}
+18 -6
View File
@@ -1,10 +1,8 @@
# 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
from msgq import fake_event_handle, drain_sock_raw, MultiplePublishersError, IpcError, \
Context, Poller, SubSocket, PubSocket, SocketEventHandle, toggle_fake_events, \
set_fake_prefix, get_fake_prefix, delete_fake_prefix, wait_for_one_event
import msgq
import os
import capnp
import time
@@ -13,11 +11,25 @@ from typing import Optional, List, Union, Dict
from cereal import log
from cereal.services import SERVICE_LIST
from openpilot.common.util import MovingAverage
from openpilot.common.utils import MovingAverage
NO_TRAVERSAL_LIMIT = 2**64-1
def pub_sock(endpoint: str) -> PubSocket:
service = SERVICE_LIST.get(endpoint)
segment_size = service.queue_size if service else 0
return msgq.pub_sock(endpoint, segment_size)
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket:
service = SERVICE_LIST.get(endpoint)
segment_size = service.queue_size if service else 0
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
timeout=timeout, segment_size=segment_size)
def reset_context():
msgq.context = Context()
+8 -7
View File
@@ -25,15 +25,16 @@ void msgq_to_zmq(const std::vector<std::string> &endpoints, const std::string &i
}
void zmq_to_msgq(const std::vector<std::string> &endpoints, const std::string &ip) {
auto poller = std::make_unique<ZMQPoller>();
auto pub_context = std::make_unique<MSGQContext>();
auto sub_context = std::make_unique<ZMQContext>();
std::map<SubSocket *, PubSocket *> sub2pub;
auto poller = std::make_unique<BridgeZmqPoller>();
auto pub_context = std::make_unique<Context>();
auto sub_context = std::make_unique<BridgeZmqContext>();
std::map<BridgeZmqSubSocket *, PubSocket *> sub2pub;
for (auto endpoint : endpoints) {
auto pub_sock = new MSGQPubSocket();
auto sub_sock = new ZMQSubSocket();
pub_sock->connect(pub_context.get(), endpoint);
auto pub_sock = new PubSocket();
auto sub_sock = new BridgeZmqSubSocket();
size_t queue_size = services.at(endpoint).queue_size;
pub_sock->connect(pub_context.get(), endpoint, true, queue_size);
sub_sock->connect(sub_context.get(), endpoint, ip, false);
poller->registerSocket(sub_sock);
+170
View File
@@ -0,0 +1,170 @@
#include "cereal/messaging/bridge_zmq.h"
#include <cassert>
#include <cstring>
#include <unistd.h>
static size_t fnv1a_hash(const std::string &str) {
const size_t fnv_prime = 0x100000001b3;
size_t hash_value = 0xcbf29ce484222325;
for (char c : str) {
hash_value ^= (unsigned char)c;
hash_value *= fnv_prime;
}
return hash_value;
}
// FIXME: This is a hack to get the port number from the socket name, might have collisions.
static int get_port(std::string endpoint) {
size_t hash_value = fnv1a_hash(endpoint);
int start_port = 8023;
int max_port = 65535;
return start_port + (hash_value % (max_port - start_port));
}
BridgeZmqContext::BridgeZmqContext() {
context = zmq_ctx_new();
}
BridgeZmqContext::~BridgeZmqContext() {
if (context != nullptr) {
zmq_ctx_term(context);
}
}
void BridgeZmqMessage::init(size_t sz) {
size = sz;
data = new char[size];
}
void BridgeZmqMessage::init(char *d, size_t sz) {
size = sz;
data = new char[size];
memcpy(data, d, size);
}
void BridgeZmqMessage::close() {
if (size > 0) {
delete[] data;
}
data = nullptr;
size = 0;
}
BridgeZmqMessage::~BridgeZmqMessage() {
close();
}
int BridgeZmqSubSocket::connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate, bool check_endpoint) {
sock = zmq_socket(context->getRawContext(), ZMQ_SUB);
if (sock == nullptr) {
return -1;
}
zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0);
if (conflate) {
int arg = 1;
zmq_setsockopt(sock, ZMQ_CONFLATE, &arg, sizeof(int));
}
int reconnect_ivl = 500;
zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl));
full_endpoint = "tcp://" + address + ":";
if (check_endpoint) {
full_endpoint += std::to_string(get_port(endpoint));
} else {
full_endpoint += endpoint;
}
return zmq_connect(sock, full_endpoint.c_str());
}
void BridgeZmqSubSocket::setTimeout(int timeout) {
zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int));
}
Message *BridgeZmqSubSocket::receive(bool non_blocking) {
zmq_msg_t msg;
assert(zmq_msg_init(&msg) == 0);
int flags = non_blocking ? ZMQ_DONTWAIT : 0;
int rc = zmq_msg_recv(&msg, sock, flags);
Message *ret = nullptr;
if (rc >= 0) {
ret = new BridgeZmqMessage;
ret->init((char *)zmq_msg_data(&msg), zmq_msg_size(&msg));
}
zmq_msg_close(&msg);
return ret;
}
BridgeZmqSubSocket::~BridgeZmqSubSocket() {
if (sock != nullptr) {
zmq_close(sock);
}
}
int BridgeZmqPubSocket::connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint) {
sock = zmq_socket(context->getRawContext(), ZMQ_PUB);
if (sock == nullptr) {
return -1;
}
full_endpoint = "tcp://*:";
if (check_endpoint) {
full_endpoint += std::to_string(get_port(endpoint));
} else {
full_endpoint += endpoint;
}
// ZMQ pub sockets cannot be shared between processes, so we need to ensure pid stays the same.
pid = getpid();
return zmq_bind(sock, full_endpoint.c_str());
}
int BridgeZmqPubSocket::sendMessage(Message *message) {
assert(pid == getpid());
return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT);
}
int BridgeZmqPubSocket::send(char *data, size_t size) {
assert(pid == getpid());
return zmq_send(sock, data, size, ZMQ_DONTWAIT);
}
BridgeZmqPubSocket::~BridgeZmqPubSocket() {
if (sock != nullptr) {
zmq_close(sock);
}
}
void BridgeZmqPoller::registerSocket(BridgeZmqSubSocket *socket) {
assert(num_polls + 1 < (sizeof(polls) / sizeof(polls[0])));
polls[num_polls].socket = socket->getRawSocket();
polls[num_polls].events = ZMQ_POLLIN;
sockets.push_back(socket);
num_polls++;
}
std::vector<BridgeZmqSubSocket *> BridgeZmqPoller::poll(int timeout) {
std::vector<BridgeZmqSubSocket *> ret;
int rc = zmq_poll(polls, num_polls, timeout);
if (rc < 0) {
return ret;
}
for (size_t i = 0; i < num_polls; i++) {
if (polls[i].revents) {
ret.push_back(sockets[i]);
}
}
return ret;
}
+72
View File
@@ -0,0 +1,72 @@
#pragma once
#include <cstddef>
#include <string>
#include <vector>
#include <zmq.h>
#include "msgq/ipc.h"
class BridgeZmqContext {
public:
BridgeZmqContext();
void *getRawContext() { return context; }
~BridgeZmqContext();
private:
void *context = nullptr;
};
class BridgeZmqMessage : public Message {
public:
void init(size_t size);
void init(char *data, size_t size);
void close();
size_t getSize() { return size; }
char *getData() { return data; }
~BridgeZmqMessage();
private:
char *data = nullptr;
size_t size = 0;
};
class BridgeZmqSubSocket {
public:
int connect(BridgeZmqContext *context, std::string endpoint, std::string address, bool conflate = false, bool check_endpoint = true);
void setTimeout(int timeout);
Message *receive(bool non_blocking = false);
void *getRawSocket() { return sock; }
~BridgeZmqSubSocket();
private:
void *sock = nullptr;
std::string full_endpoint;
};
class BridgeZmqPubSocket {
public:
int connect(BridgeZmqContext *context, std::string endpoint, bool check_endpoint = true);
int sendMessage(Message *message);
int send(char *data, size_t size);
void *getRawSocket() { return sock; }
~BridgeZmqPubSocket();
private:
void *sock = nullptr;
std::string full_endpoint;
int pid = -1;
};
class BridgeZmqPoller {
public:
void registerSocket(BridgeZmqSubSocket *socket);
std::vector<BridgeZmqSubSocket *> poll(int timeout);
private:
static constexpr size_t MAX_BRIDGE_ZMQ_POLLERS = 128;
std::vector<BridgeZmqSubSocket *> sockets;
zmq_pollitem_t polls[MAX_BRIDGE_ZMQ_POLLERS] = {};
size_t num_polls = 0;
};
+9 -7
View File
@@ -2,6 +2,7 @@
#include <cassert>
#include "cereal/services.h"
#include "common/util.h"
extern ExitHandler do_exit;
@@ -21,14 +22,14 @@ static std::string recv_zmq_msg(void *sock) {
}
void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string &ip) {
zmq_context = std::make_unique<ZMQContext>();
msgq_context = std::make_unique<MSGQContext>();
zmq_context = std::make_unique<BridgeZmqContext>();
msgq_context = std::make_unique<Context>();
// Create ZMQPubSockets for each endpoint
for (const auto &endpoint : endpoints) {
auto &socket_pair = socket_pairs.emplace_back();
socket_pair.endpoint = endpoint;
socket_pair.pub_sock = std::make_unique<ZMQPubSocket>();
socket_pair.pub_sock = std::make_unique<BridgeZmqPubSocket>();
int ret = socket_pair.pub_sock->connect(zmq_context.get(), endpoint);
if (ret != 0) {
printf("Failed to create ZMQ publisher for [%s]: %s\n", endpoint.c_str(), zmq_strerror(zmq_errno()));
@@ -48,7 +49,7 @@ void MsgqToZmq::run(const std::vector<std::string> &endpoints, const std::string
for (auto sub_sock : msgq_poller->poll(100)) {
// Process messages for each socket
ZMQPubSocket *pub_sock = sub2pub.at(sub_sock);
BridgeZmqPubSocket *pub_sock = sub2pub.at(sub_sock);
for (int i = 0; i < MAX_MESSAGES_PER_SOCKET; ++i) {
auto msg = std::unique_ptr<Message>(sub_sock->receive(true));
if (!msg) break;
@@ -71,7 +72,7 @@ void MsgqToZmq::zmqMonitorThread() {
// Set up ZMQ monitor for each pub socket
for (int i = 0; i < socket_pairs.size(); ++i) {
std::string addr = "inproc://op-bridge-monitor-" + std::to_string(i);
zmq_socket_monitor(socket_pairs[i].pub_sock->sock, addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), addr.c_str(), ZMQ_EVENT_ACCEPTED | ZMQ_EVENT_DISCONNECTED);
void *monitor_socket = zmq_socket(zmq_context->getRawContext(), ZMQ_PAIR);
zmq_connect(monitor_socket, addr.c_str());
@@ -108,7 +109,8 @@ void MsgqToZmq::zmqMonitorThread() {
if (++pair.connected_clients == 1) {
// Create new MSGQ subscriber socket and map to ZMQ publisher
pair.sub_sock = std::make_unique<MSGQSubSocket>();
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1");
size_t queue_size = services.at(pair.endpoint).queue_size;
pair.sub_sock->connect(msgq_context.get(), pair.endpoint, "127.0.0.1", false, true, queue_size);
sub2pub[pair.sub_sock.get()] = pair.pub_sock.get();
registerSockets();
}
@@ -128,7 +130,7 @@ void MsgqToZmq::zmqMonitorThread() {
// Clean up monitor sockets
for (int i = 0; i < pollitems.size(); ++i) {
zmq_socket_monitor(socket_pairs[i].pub_sock->sock, nullptr, 0);
zmq_socket_monitor(socket_pairs[i].pub_sock->getRawSocket(), nullptr, 0);
zmq_close(pollitems[i].socket);
}
cv.notify_one();
+5 -6
View File
@@ -7,9 +7,8 @@
#include <string>
#include <vector>
#define private public
#include "msgq/impl_msgq.h"
#include "msgq/impl_zmq.h"
#include "cereal/messaging/bridge_zmq.h"
class MsgqToZmq {
public:
@@ -22,16 +21,16 @@ protected:
struct SocketPair {
std::string endpoint;
std::unique_ptr<ZMQPubSocket> pub_sock;
std::unique_ptr<BridgeZmqPubSocket> pub_sock;
std::unique_ptr<MSGQSubSocket> sub_sock;
int connected_clients = 0;
};
std::unique_ptr<MSGQContext> msgq_context;
std::unique_ptr<ZMQContext> zmq_context;
std::unique_ptr<Context> msgq_context;
std::unique_ptr<BridgeZmqContext> zmq_context;
std::mutex mutex;
std::condition_variable cv;
std::unique_ptr<MSGQPoller> msgq_poller;
std::map<SubSocket *, ZMQPubSocket *> sub2pub;
std::map<SubSocket *, BridgeZmqPubSocket *> sub2pub;
std::vector<SocketPair> socket_pairs;
};
+3 -2
View File
@@ -50,7 +50,7 @@ SubMaster::SubMaster(const std::vector<const char *> &service_list, const std::v
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);
SubSocket *socket = SubSocket::create(message_context.context(), name, address ? address : "127.0.0.1", true, true, serv.queue_size);
assert(socket != 0);
bool is_polled = inList(poll, name) || poll.empty();
if (is_polled) poller_->registerSocket(socket);
@@ -187,7 +187,8 @@ SubMaster::~SubMaster() {
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);
service serv = services.at(std::string(name));
PubSocket *socket = PubSocket::create(message_context.context(), name, true, serv.queue_size);
assert(socket);
sockets_[name] = socket;
}
+29 -22
View File
@@ -1,37 +1,44 @@
#!/usr/bin/env python3
from enum import IntEnum
from typing import Optional
# TODO: this should be automatically determined using the capnp schema
class QueueSize(IntEnum):
BIG = 10 * 1024 * 1024 # 10MB - video frames, large AI outputs
MEDIUM = 2 * 1024 * 1024 # 2MB - high freq (CAN), livestream
SMALL = 250 * 1024 # 250KB - most services
class Service:
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None):
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None,
queue_size: QueueSize = QueueSize.SMALL):
self.should_log = should_log
self.frequency = frequency
self.decimation = decimation
self.queue_size = queue_size
_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.),
"lightSensor": (True, 100., 100),
"temperatureSensor": (True, 2., 200),
"temperatureSensor2": (True, 2., 200),
"gpsNMEA": (True, 9.),
"deviceState": (True, 2., 1),
"touch": (True, 20., 1),
"can": (True, 100., 2053), # decimation gives ~3 msgs in a full segment
"controlsState": (True, 100., 10),
"can": (True, 100., 2053, QueueSize.BIG), # decimation gives ~3 msgs in a full segment
"controlsState": (True, 100., 10, QueueSize.MEDIUM),
"selfdriveState": (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),
"sendcan": (True, 100., 139, QueueSize.MEDIUM),
"logMessage": (True, 0.),
"errorLogMessage": (True, 0., 1),
"liveCalibration": (True, 4., 4),
@@ -43,7 +50,7 @@ _services: dict[str, tuple] = {
"carOutput": (True, 100., 10),
"longitudinalPlan": (True, 20., 10),
"driverAssistance": (True, 20., 20),
"procLog": (True, 0.5, 15),
"procLog": (True, 0.5, 15, QueueSize.BIG),
"gpsLocationExternal": (True, 10., 10),
"gpsLocation": (True, 1., 1),
"ubloxGnss": (True, 10.),
@@ -65,7 +72,7 @@ _services: dict[str, tuple] = {
"wideRoadEncodeIdx": (False, 20., 1),
"wideRoadCameraState": (True, 20., 20),
"drivingModelData": (True, 20., 10),
"modelV2": (True, 20.),
"modelV2": (True, 20., None, QueueSize.BIG),
"managerState": (True, 2., 1),
"uploaderState": (True, 0., 1),
"navInstruction": (True, 1., 10),
@@ -77,10 +84,14 @@ _services: dict[str, tuple] = {
"rawAudioData": (False, 20.),
"bookmarkButton": (True, 0., 1),
"audioFeedback": (True, 0., 1),
"roadEncodeData": (False, 20., None, QueueSize.BIG),
"driverEncodeData": (False, 20., None, QueueSize.BIG),
"wideRoadEncodeData": (False, 20., None, QueueSize.BIG),
"qRoadEncodeData": (False, 20., None, QueueSize.BIG),
# sunnypilot
"modelManagerSP": (False, 1., 1),
"backupManagerSP": (False, 1., 1),
"modelManagerSP": (False, 1., 1, QueueSize.BIG),
"backupManagerSP": (False, 1., 1, QueueSize.BIG),
"selfdriveStateSP": (True, 100., 10),
"longitudinalPlanSP": (True, 20., 10),
"onroadEventsSP": (True, 1., 1),
@@ -88,23 +99,19 @@ _services: dict[str, tuple] = {
"carControlSP": (True, 100., 10),
"carStateSP": (True, 100., 10),
"liveMapDataSP": (True, 1., 1),
"modelDataV2SP": (True, 20.),
"modelDataV2SP": (True, 20., None, QueueSize.BIG),
"liveLocationKalman": (True, 20.),
# debug
"uiDebug": (True, 0., 1),
"testJoystick": (True, 0.),
"alertDebug": (True, 20., 5),
"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.),
"livestreamWideRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamRoadEncodeData": (False, 20., None, QueueSize.MEDIUM),
"livestreamDriverEncodeData": (False, 20., None, QueueSize.MEDIUM),
"customReservedRawData0": (True, 0.),
"customReservedRawData1": (True, 0.),
"customReservedRawData2": (True, 0.),
@@ -122,13 +129,13 @@ def build_header():
h += "#include <map>\n"
h += "#include <string>\n"
h += "struct service { std::string name; bool should_log; float frequency; int decimation; };\n"
h += "struct service { std::string name; bool should_log; float frequency; int decimation; size_t queue_size; };\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, %f, %d}},\n' % \
(k, k, should_log, v.frequency, decimation)
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \
(k, k, should_log, v.frequency, decimation, v.queue_size)
h += "};\n"
h += "#endif\n"
+1 -6
View File
@@ -19,11 +19,6 @@ if GetOption('extras'):
# Cython bindings
params_python = envCython.Program('params_pyx.so', 'params_pyx.pyx', LIBS=envCython['LIBS'] + [_common, 'zmq', 'json11'])
SConscript([
'transformations/SConscript',
])
Import('transformations_python')
common_python = [params_python, transformations_python]
common_python = [params_python]
Export('common_python')
+3 -3
View File
@@ -18,9 +18,9 @@ class Api:
return self.service.get_token(payload_extra, expiry_hours)
def api_get(endpoint, method='GET', timeout=None, access_token=None, **params):
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, **params)
def api_get(endpoint, method='GET', timeout=None, access_token=None, session=None, **params):
return CommaConnectApi(None).api_get(endpoint, method, timeout, access_token, session, **params)
def get_key_pair():
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
return CommaConnectApi(None).get_key_pair()
+8 -6
View File
@@ -6,9 +6,9 @@ from datetime import datetime, timedelta, UTC
from openpilot.system.hardware.hw import Paths
from openpilot.system.version import get_version
# name : jwt signature algorithm
KEYS = {"id_rsa" : "RS256",
"id_ecdsa" : "ES256"}
# name: jwt signature algorithm
KEYS = {"id_rsa": "RS256",
"id_ecdsa": "ES256"}
class BaseApi:
@@ -51,7 +51,7 @@ class BaseApi:
ascii_encoded_text = normalized_text.encode('ascii', 'ignore')
return ascii_encoded_text.decode()
def api_get(self, endpoint, method='GET', timeout=None, access_token=None, json=None, **params):
def api_get(self, endpoint, method='GET', timeout=None, access_token=None, session=None, json=None, **params):
headers = {}
if access_token is not None:
headers['Authorization'] = "JWT " + access_token
@@ -59,10 +59,12 @@ class BaseApi:
version = self.remove_non_ascii_chars(get_version())
headers['User-Agent'] = self.user_agent + version
return requests.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
# TODO: add session to Api
req = requests if session is None else session
return req.request(method, f"{self.api_host}/{endpoint}", timeout=timeout, headers=headers, json=json, params=params)
@staticmethod
def get_key_pair():
def get_key_pair() -> tuple[str, str, str] | tuple[None, None, None]:
for key in KEYS:
if os.path.isfile(Paths.persist_root() + f'/comma/{key}') and os.path.isfile(Paths.persist_root() + f'/comma/{key}.pub'):
with open(Paths.persist_root() + f'/comma/{key}') as private, open(Paths.persist_root() + f'/comma/{key}.pub') as public:
+6 -6
View File
@@ -4,27 +4,27 @@ from openpilot.common.utils import run_cmd, run_cmd_default
@cache
def get_commit(cwd: str = None, branch: str = "HEAD") -> str:
def get_commit(cwd: str | None = 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:
def get_commit_date(cwd: str | None = 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:
def get_short_branch(cwd: str | None = None) -> str:
return run_cmd_default(["git", "rev-parse", "--abbrev-ref", "HEAD"], cwd=cwd)
@cache
def get_branch(cwd: str = None) -> str:
def get_branch(cwd: str | None = 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:
def get_origin(cwd: str | None = 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)
@@ -34,7 +34,7 @@ def get_origin(cwd: str = None) -> str:
@cache
def get_normalized_origin(cwd: str = None) -> str:
def get_normalized_origin(cwd: str | None = None) -> str:
return get_origin(cwd) \
.replace("git@", "", 1) \
.replace(".git", "", 1) \
+81
View File
@@ -0,0 +1,81 @@
import os
import fcntl
import ctypes
# I2C constants from /usr/include/linux/i2c-dev.h
I2C_SLAVE = 0x0703
I2C_SLAVE_FORCE = 0x0706
I2C_SMBUS = 0x0720
# SMBus transfer types
I2C_SMBUS_READ = 1
I2C_SMBUS_WRITE = 0
I2C_SMBUS_BYTE_DATA = 2
I2C_SMBUS_I2C_BLOCK_DATA = 8
I2C_SMBUS_BLOCK_MAX = 32
class _I2cSmbusData(ctypes.Union):
_fields_ = [
("byte", ctypes.c_uint8),
("word", ctypes.c_uint16),
("block", ctypes.c_uint8 * (I2C_SMBUS_BLOCK_MAX + 2)),
]
class _I2cSmbusIoctlData(ctypes.Structure):
_fields_ = [
("read_write", ctypes.c_uint8),
("command", ctypes.c_uint8),
("size", ctypes.c_uint32),
("data", ctypes.POINTER(_I2cSmbusData)),
]
class SMBus:
def __init__(self, bus: int):
self._fd = os.open(f'/dev/i2c-{bus}', os.O_RDWR)
def __enter__(self) -> 'SMBus':
return self
def __exit__(self, *args) -> None:
self.close()
def close(self) -> None:
if hasattr(self, '_fd') and self._fd >= 0:
os.close(self._fd)
self._fd = -1
def _set_address(self, addr: int, force: bool = False) -> None:
ioctl_arg = I2C_SLAVE_FORCE if force else I2C_SLAVE
fcntl.ioctl(self._fd, ioctl_arg, addr)
def _smbus_access(self, read_write: int, command: int, size: int, data: _I2cSmbusData) -> None:
ioctl_data = _I2cSmbusIoctlData(read_write, command, size, ctypes.pointer(data))
fcntl.ioctl(self._fd, I2C_SMBUS, ioctl_data)
def read_byte_data(self, addr: int, register: int, force: bool = False) -> int:
self._set_address(addr, force)
data = _I2cSmbusData()
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_BYTE_DATA, data)
return int(data.byte)
def write_byte_data(self, addr: int, register: int, value: int, force: bool = False) -> None:
self._set_address(addr, force)
data = _I2cSmbusData()
data.byte = value & 0xFF
self._smbus_access(I2C_SMBUS_WRITE, register, I2C_SMBUS_BYTE_DATA, data)
def read_i2c_block_data(self, addr: int, register: int, length: int, force: bool = False) -> list[int]:
self._set_address(addr, force)
if not (0 <= length <= I2C_SMBUS_BLOCK_MAX):
raise ValueError(f"length must be 0..{I2C_SMBUS_BLOCK_MAX}")
data = _I2cSmbusData()
data.block[0] = length
self._smbus_access(I2C_SMBUS_READ, register, I2C_SMBUS_I2C_BLOCK_DATA, data)
read_len = int(data.block[0]) or length
read_len = min(read_len, length)
return [int(b) for b in data.block[1 : read_len + 1]]
+1 -1
View File
@@ -1 +1 @@
#define DEFAULT_MODEL "The Cool People (Default)"
#define DEFAULT_MODEL "CD210 (Default)"
+11 -2
View File
@@ -71,6 +71,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"LastGPSPosition", {PERSISTENT, STRING}},
{"LastManagerExitReason", {CLEAR_ON_MANAGER_START, STRING}},
{"LastOffroadStatusPacket", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, JSON}},
{"LastAgnosPowerMonitorShutdown", {CLEAR_ON_MANAGER_START, STRING}},
{"LastPowerDropDetected", {CLEAR_ON_MANAGER_START, STRING}},
{"LastUpdateException", {CLEAR_ON_MANAGER_START, STRING}},
{"LastUpdateRouteCount", {PERSISTENT, INT, "0"}},
@@ -114,6 +115,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"SnoozeUpdate", {CLEAR_ON_MANAGER_START | CLEAR_ON_OFFROAD_TRANSITION, BOOL}},
{"SshEnabled", {PERSISTENT | BACKUP, BOOL}},
{"TermsVersion", {PERSISTENT, STRING}},
{"TorqueBar", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TrainingVersion", {PERSISTENT, STRING}},
{"UbloxAvailable", {PERSISTENT, BOOL}},
{"UpdateAvailable", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BOOL}},
@@ -135,14 +137,17 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"ApiCache_DriveStats", {PERSISTENT, JSON}},
{"AutoLaneChangeBsmDelay", {PERSISTENT | BACKUP, BOOL, "0"}},
{"AutoLaneChangeTimer", {PERSISTENT | BACKUP, INT, "0"}},
{"BlinkerLateralReengageDelay", {PERSISTENT | BACKUP, INT, "0"}}, // seconds
{"BlinkerMinLateralControlSpeed", {PERSISTENT | BACKUP, INT, "20"}}, // MPH or km/h
{"BlinkerPauseLateralControl", {PERSISTENT | BACKUP, INT, "0"}},
{"Brightness", {PERSISTENT | BACKUP, INT, "0"}},
{"CarList", {PERSISTENT, JSON}},
{"CarParamsSP", {CLEAR_ON_MANAGER_START | CLEAR_ON_ONROAD_TRANSITION, BYTES}},
{"CarParamsSPCache", {CLEAR_ON_MANAGER_START, BYTES}},
{"CarParamsSPPersistent", {PERSISTENT, BYTES}},
{"CarPlatformBundle", {PERSISTENT | BACKUP, JSON}},
{"ChevronInfo", {PERSISTENT | BACKUP, INT, "4"}},
{"CompletedSunnylinkConsentVersion", {PERSISTENT, STRING, "0"}},
{"CustomAccIncrementsEnabled", {PERSISTENT | BACKUP, BOOL, "0"}},
{"CustomAccLongPressIncrement", {PERSISTENT | BACKUP, INT, "5"}},
{"CustomAccShortPressIncrement", {PERSISTENT | BACKUP, INT, "1"}},
@@ -152,6 +157,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"EnableGithubRunner", {PERSISTENT | BACKUP, BOOL}},
{"GreenLightAlert", {PERSISTENT | BACKUP, BOOL, "0"}},
{"GithubRunnerSufficientVoltage", {CLEAR_ON_MANAGER_START , BOOL}},
{"HasAcceptedTermsSP", {PERSISTENT, STRING, "0"}},
{"HideVEgoUI", {PERSISTENT | BACKUP, BOOL, "0"}},
{"IntelligentCruiseButtonManagement", {PERSISTENT | BACKUP , BOOL}},
{"InteractivityTimeout", {PERSISTENT | BACKUP, INT, "0"}},
@@ -164,12 +170,12 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"OffroadMode", {CLEAR_ON_MANAGER_START, BOOL}},
{"Offroad_TiciSupport", {CLEAR_ON_MANAGER_START, JSON}},
{"OnroadScreenOffBrightness", {PERSISTENT | BACKUP, INT, "0"}},
{"OnroadScreenOffControl", {PERSISTENT | BACKUP, BOOL}},
{"OnroadScreenOffTimer", {PERSISTENT | BACKUP, INT, "15"}},
{"OnroadUploads", {PERSISTENT | BACKUP, BOOL, "1"}},
{"QuickBootToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
{"QuietMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RainbowMode", {PERSISTENT | BACKUP, BOOL, "0"}},
{"RocketFuel", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ShowAdvancedControls", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ShowTurnSignals", {PERSISTENT | BACKUP, BOOL, "0"}},
{"StandstillTimer", {PERSISTENT | BACKUP, BOOL, "0"}},
@@ -211,16 +217,19 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"SubaruStopAndGo", {PERSISTENT | BACKUP, BOOL, "0"}},
{"SubaruStopAndGoManualParkingBrake", {PERSISTENT | BACKUP, BOOL, "0"}},
{"TeslaCoopSteering", {PERSISTENT | BACKUP, BOOL, "0"}},
{"ToyotaEnforceStockLongitudinal", {PERSISTENT | BACKUP, BOOL, "0"}},
{"DynamicExperimentalControl", {PERSISTENT | BACKUP, BOOL, "0"}},
{"BlindSpot", {PERSISTENT | BACKUP, BOOL, "0"}},
// sunnypilot model params
{"CameraOffset", {PERSISTENT | BACKUP, FLOAT, "0.0"}},
{"LagdToggle", {PERSISTENT | BACKUP, BOOL, "1"}},
{"LagdToggleDelay", {PERSISTENT | BACKUP, FLOAT, "0.2"}},
{"LagdValueCache", {PERSISTENT, FLOAT, "0.2"}},
{"LaneTurnDesire", {PERSISTENT | BACKUP, BOOL, "0"}},
{"LaneTurnValue", {PERSISTENT | BACKUP, FLOAT, "19.0"}},
{"PlanplusControl", {PERSISTENT | BACKUP, FLOAT, "1.0"}},
// mapd
{"MapAdvisorySpeedLimit", {CLEAR_ON_ONROAD_TRANSITION, FLOAT}},
@@ -241,7 +250,7 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"OsmStateTitle", {PERSISTENT, STRING}},
{"OsmWayTest", {PERSISTENT, STRING}},
{"RoadName", {CLEAR_ON_ONROAD_TRANSITION, STRING}},
{"RoadNameToggle", {PERSISTENT, STRING}},
{"RoadNameToggle", {PERSISTENT | BACKUP, BOOL, "0"}},
// Speed Limit
{"SpeedLimitMode", {PERSISTENT | BACKUP, INT, "1"}},
+3 -9
View File
@@ -3,15 +3,9 @@ from numbers import Number
class PIDController:
def __init__(self, k_p, k_i, k_d=0., pos_limit=1e308, neg_limit=-1e308, rate=100):
self._k_p = k_p
self._k_i = k_i
self._k_d = k_d
if isinstance(self._k_p, Number):
self._k_p = [[0], [self._k_p]]
if isinstance(self._k_i, Number):
self._k_i = [[0], [self._k_i]]
if isinstance(self._k_d, Number):
self._k_d = [[0], [self._k_d]]
self._k_p: list[list[float]] = [[0], [k_p]] if isinstance(k_p, Number) else k_p
self._k_i: list[list[float]] = [[0], [k_i]] if isinstance(k_i, Number) else k_i
self._k_d: list[list[float]] = [[0], [k_d]] if isinstance(k_d, Number) else k_d
self.set_limits(pos_limit, neg_limit)
+5 -1
View File
@@ -13,7 +13,11 @@ public:
if (prefix.empty()) {
prefix = util::random_string(15);
}
msgq_path = Path::shm_path() + "/" + prefix;
#ifdef __APPLE__
msgq_path = "/tmp/msgq_" + prefix;
#else
msgq_path = "/dev/shm/msgq_" + prefix;
#endif
bool ret = util::create_directories(msgq_path, 0777);
assert(ret);
setenv("OPENPILOT_PREFIX", prefix.c_str(), 1);
+4 -2
View File
@@ -1,4 +1,5 @@
import os
import platform
import shutil
import uuid
@@ -9,9 +10,10 @@ from openpilot.system.hardware.hw import Paths
from openpilot.system.hardware.hw import DEFAULT_DOWNLOAD_CACHE_ROOT
class OpenpilotPrefix:
def __init__(self, prefix: str = None, create_dirs_on_enter: bool = True, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
def __init__(self, prefix: str | None = None, create_dirs_on_enter: bool = True, clean_dirs_on_exit: bool = True, shared_download_cache: bool = False):
self.prefix = prefix if prefix else str(uuid.uuid4().hex[0:15])
self.msgq_path = os.path.join(Paths.shm_path(), self.prefix)
shm_path = "/tmp" if platform.system() == "Darwin" else "/dev/shm"
self.msgq_path = os.path.join(shm_path, "msgq_" + self.prefix)
self.create_dirs_on_enter = create_dirs_on_enter
self.clean_dirs_on_exit = clean_dirs_on_exit
self.shared_download_cache = shared_download_cache
+1 -1
View File
@@ -6,7 +6,7 @@ import time
from setproctitle import getproctitle
from openpilot.common.util import MovingAverage
from openpilot.common.utils import MovingAverage
from openpilot.system.hardware import PC
+3 -3
View File
@@ -1,7 +1,7 @@
import os
from uuid import uuid4
from openpilot.common.utils import atomic_write_in_dir
from openpilot.common.utils import atomic_write
class TestFileHelpers:
@@ -15,5 +15,5 @@ class TestFileHelpers:
assert f.read() == "test"
os.remove(path)
def test_atomic_write_in_dir(self):
self.run_atomic_write_func(atomic_write_in_dir)
def test_atomic_write(self):
self.run_atomic_write_func(atomic_write)
-5
View File
@@ -1,5 +0,0 @@
Import('env', 'envCython')
transformations = env.Library('transformations', ['orientation.cc', 'coordinates.cc'])
transformations_python = envCython.Program('transformations.so', 'transformations.pyx')
Export('transformations', 'transformations_python')
@@ -102,3 +102,36 @@ class TestNED:
np.testing.assert_allclose(converter.ned2ecef(ned_offsets_batch),
ecef_positions_offset_batch,
rtol=1e-9, atol=1e-7)
def test_errors(self):
# Test wrong shape/type for geodetic2ecef
# numpy_wrap raises IndexError for scalar input
with np.testing.assert_raises(IndexError):
coord.geodetic2ecef(1.0)
with np.testing.assert_raises_regex(ValueError, "Geodetic must be size 3"):
coord.geodetic2ecef([0, 0])
with np.testing.assert_raises_regex(ValueError, "Geodetic must be size 3"):
coord.geodetic2ecef([0, 0, 0, 0])
with np.testing.assert_raises(TypeError):
coord.geodetic2ecef(['a', 'b', 'c'])
# Test LocalCoord constructor errors
with np.testing.assert_raises(ValueError):
coord.LocalCoord.from_geodetic([0, 0])
with np.testing.assert_raises(ValueError):
coord.LocalCoord.from_geodetic(1)
with np.testing.assert_raises(TypeError):
coord.LocalCoord.from_geodetic(['a', 'b', 'c'])
# Test wrong shape/type for ecef2geodetic
with np.testing.assert_raises(ValueError):
coord.ecef2geodetic([1, 2])
with np.testing.assert_raises(ValueError):
coord.ecef2geodetic([1, 2, 3, 4])
with np.testing.assert_raises(IndexError):
coord.ecef2geodetic(1.0)
@@ -1,4 +1,5 @@
import numpy as np
import pytest
from openpilot.common.transformations.orientation import euler2quat, quat2euler, euler2rot, rot2euler, \
rot2quat, quat2rot, \
@@ -59,3 +60,32 @@ class TestOrientation:
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)
def test_inputs(self):
with pytest.raises(ValueError):
euler2quat([1, 2])
with pytest.raises(ValueError):
quat2rot([1, 2, 3])
with pytest.raises(IndexError):
rot2quat(np.zeros((2, 2)))
def test_euler_rot_consistency(self):
rpy = [0.1, 0.2, 0.3]
R = euler2rot(rpy)
# R -> q -> R
q = rot2quat(R)
R_new = quat2rot(q)
np.testing.assert_allclose(R, R_new, atol=1e-15)
# q -> R -> Euler (quat2euler) -> R
rpy_new = quat2euler(q)
R_new2 = euler2rot(rpy_new)
np.testing.assert_allclose(R, R_new2, atol=1e-15)
# R -> Euler (rot2euler) -> R
rpy_from_rot = rot2euler(R)
R_new3 = euler2rot(rpy_from_rot)
np.testing.assert_allclose(R, R_new3, atol=1e-15)
@@ -1,72 +0,0 @@
# cython: language_level=3
from libcpp cimport bool
cdef extern from "orientation.cc":
pass
cdef extern from "orientation.hpp":
cdef cppclass Quaternion "Eigen::Quaterniond":
Quaternion()
Quaternion(double, double, double, double)
double w()
double x()
double y()
double z()
cdef cppclass Vector3 "Eigen::Vector3d":
Vector3()
Vector3(double, double, double)
double operator()(int)
cdef cppclass Matrix3 "Eigen::Matrix3d":
Matrix3()
Matrix3(double*)
double operator()(int, int)
Quaternion euler2quat(const Vector3 &)
Vector3 quat2euler(const Quaternion &)
Matrix3 quat2rot(const Quaternion &)
Quaternion rot2quat(const Matrix3 &)
Vector3 rot2euler(const Matrix3 &)
Matrix3 euler2rot(const Vector3 &)
Matrix3 rot_matrix(double, double, double)
Vector3 ecef_euler_from_ned(const ECEF &, const Vector3 &)
Vector3 ned_euler_from_ecef(const ECEF &, const Vector3 &)
cdef extern from "coordinates.cc":
cdef struct ECEF:
double x
double y
double z
cdef struct NED:
double n
double e
double d
cdef struct Geodetic:
double lat
double lon
double alt
bool radians
ECEF geodetic2ecef(const Geodetic &)
Geodetic ecef2geodetic(const ECEF &)
cdef cppclass LocalCoord_c "LocalCoord":
Matrix3 ned2ecef_matrix
Matrix3 ecef2ned_matrix
LocalCoord_c(const Geodetic &, const ECEF &)
LocalCoord_c(const Geodetic &)
LocalCoord_c(const ECEF &)
NED ecef2ned(const ECEF &)
ECEF ned2ecef(const NED &)
NED geodetic2ned(const Geodetic &)
Geodetic ned2geodetic(const NED &)
cdef extern from "coordinates.hpp":
pass
+342
View File
@@ -0,0 +1,342 @@
import numpy as np
# Constants
a = 6378137.0
b = 6356752.3142
esq = 6.69437999014e-3
e1sq = 6.73949674228e-3
def geodetic2ecef_single(g):
"""
Convert geodetic coordinates (latitude, longitude, altitude) to ECEF.
"""
try:
if len(g) != 3:
raise ValueError("Geodetic must be size 3")
except TypeError:
raise ValueError("Geodetic must be a sequence of length 3") from None
lat, lon, alt = g
lat = np.radians(lat)
lon = np.radians(lon)
xi = np.sqrt(1.0 - esq * np.sin(lat)**2)
x = (a / xi + alt) * np.cos(lat) * np.cos(lon)
y = (a / xi + alt) * np.cos(lat) * np.sin(lon)
z = (a / xi * (1.0 - esq) + alt) * np.sin(lat)
return np.array([x, y, z])
def ecef2geodetic_single(e):
"""
Convert ECEF to geodetic coordinates using Ferrari's solution.
"""
x, y, z = e
r = np.sqrt(x**2 + y**2)
Esq = a**2 - b**2
F = 54 * b**2 * z**2
G = r**2 + (1 - esq) * z**2 - esq * Esq
C = (esq**2 * F * r**2) / (G**3)
S = np.cbrt(1 + C + np.sqrt(C**2 + 2 * C))
P = F / (3 * (S + 1 / S + 1)**2 * G**2)
Q = np.sqrt(1 + 2 * esq**2 * P)
r_0 = -(P * esq * r) / (1 + Q) + np.sqrt(0.5 * a**2 * (1 + 1.0 / Q) - P * (1 - esq) * z**2 / (Q * (1 + Q)) - 0.5 * P * r**2)
U = np.sqrt((r - esq * r_0)**2 + z**2)
V = np.sqrt((r - esq * r_0)**2 + (1 - esq) * z**2)
Z_0 = b**2 * z / (a * V)
h = U * (1 - b**2 / (a * V))
lat = np.arctan((z + e1sq * Z_0) / r)
lon = np.arctan2(y, x)
return np.array([np.degrees(lat), np.degrees(lon), h])
def euler2quat_single(euler):
"""
Convert Euler angles (roll, pitch, yaw) to a quaternion.
Rotation order: Z-Y-X (yaw, pitch, roll).
"""
phi, theta, psi = euler
c_phi, s_phi = np.cos(phi / 2), np.sin(phi / 2)
c_theta, s_theta = np.cos(theta / 2), np.sin(theta / 2)
c_psi, s_psi = np.cos(psi / 2), np.sin(psi / 2)
w = c_phi * c_theta * c_psi + s_phi * s_theta * s_psi
x = s_phi * c_theta * c_psi - c_phi * s_theta * s_psi
y = c_phi * s_theta * c_psi + s_phi * c_theta * s_psi
z = c_phi * c_theta * s_psi - s_phi * s_theta * c_psi
if w < 0:
return np.array([-w, -x, -y, -z])
return np.array([w, x, y, z])
def quat2euler_single(q):
"""
Convert a quaternion to Euler angles (roll, pitch, yaw).
"""
w, x, y, z = q
gamma = np.arctan2(2 * (w * x + y * z), 1 - 2 * (x**2 + y**2))
sin_arg = 2 * (w * y - z * x)
sin_arg = np.clip(sin_arg, -1.0, 1.0)
theta = np.arcsin(sin_arg)
psi = np.arctan2(2 * (w * z + x * y), 1 - 2 * (y**2 + z**2))
return np.array([gamma, theta, psi])
def quat2rot_single(q):
"""
Convert a quaternion to a 3x3 rotation matrix.
"""
w, x, y, z = q
xx, yy, zz = x * x, y * y, z * z
xy, xz, yz = x * y, x * z, y * z
wx, wy, wz = w * x, w * y, w * z
mat = np.array([
[1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy)],
[2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx)],
[2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy)]
])
return mat
def rot2quat_single(rot):
"""
Convert a 3x3 rotation matrix to a quaternion.
"""
trace = np.trace(rot)
if trace > 0:
s = 0.5 / np.sqrt(trace + 1.0)
w = 0.25 / s
x = (rot[2, 1] - rot[1, 2]) * s
y = (rot[0, 2] - rot[2, 0]) * s
z = (rot[1, 0] - rot[0, 1]) * s
else:
if rot[0, 0] > rot[1, 1] and rot[0, 0] > rot[2, 2]:
s = 2.0 * np.sqrt(1.0 + rot[0, 0] - rot[1, 1] - rot[2, 2])
w = (rot[2, 1] - rot[1, 2]) / s
x = 0.25 * s
y = (rot[0, 1] + rot[1, 0]) / s
z = (rot[0, 2] + rot[2, 0]) / s
elif rot[1, 1] > rot[2, 2]:
s = 2.0 * np.sqrt(1.0 + rot[1, 1] - rot[0, 0] - rot[2, 2])
w = (rot[0, 2] - rot[2, 0]) / s
x = (rot[0, 1] + rot[1, 0]) / s
y = 0.25 * s
z = (rot[1, 2] + rot[2, 1]) / s
else:
s = 2.0 * np.sqrt(1.0 + rot[2, 2] - rot[0, 0] - rot[1, 1])
w = (rot[1, 0] - rot[0, 1]) / s
x = (rot[0, 2] + rot[2, 0]) / s
y = (rot[1, 2] + rot[2, 1]) / s
z = 0.25 * s
if w < 0:
return np.array([-w, -x, -y, -z])
return np.array([w, x, y, z])
def euler2rot_single(euler):
"""
Convert Euler angles (roll, pitch, yaw) to a 3x3 rotation matrix.
Rotation order: Z-Y-X (yaw, pitch, roll).
"""
phi, theta, psi = euler
cx, sx = np.cos(phi), np.sin(phi)
cy, sy = np.cos(theta), np.sin(theta)
cz, sz = np.cos(psi), np.sin(psi)
Rx = np.array([[1, 0, 0], [0, cx, -sx], [0, sx, cx]])
Ry = np.array([[cy, 0, sy], [0, 1, 0], [-sy, 0, cy]])
Rz = np.array([[cz, -sz, 0], [sz, cz, 0], [0, 0, 1]])
return Rz @ Ry @ Rx
def rot2euler_single(rot):
"""
Convert a 3x3 rotation matrix to Euler angles (roll, pitch, yaw).
"""
return quat2euler_single(rot2quat_single(rot))
def rot_matrix(roll, pitch, yaw):
"""
Create a 3x3 rotation matrix from roll, pitch, and yaw angles.
"""
return euler2rot_single([roll, pitch, yaw])
def axis_angle_to_rot(axis, angle):
"""
Convert an axis-angle representation to a 3x3 rotation matrix.
"""
c = np.cos(angle / 2)
s = np.sin(angle / 2)
q = np.array([c, s*axis[0], s*axis[1], s*axis[2]])
return quat2rot_single(q)
class LocalCoord:
"""
A class to handle conversions between ECEF and local NED coordinates.
"""
def __init__(self, geodetic=None, ecef=None):
"""
Initialize LocalCoord with either geodetic or ECEF coordinates.
"""
if geodetic is not None:
self.init_ecef = geodetic2ecef_single(geodetic)
lat, lon, _ = geodetic
elif ecef is not None:
self.init_ecef = np.array(ecef)
lat, lon, _ = ecef2geodetic_single(ecef)
else:
raise ValueError("Must provide geodetic or ecef")
lat = np.radians(lat)
lon = np.radians(lon)
self.ned2ecef_matrix = np.array([
[-np.sin(lat) * np.cos(lon), -np.sin(lon), -np.cos(lat) * np.cos(lon)],
[-np.sin(lat) * np.sin(lon), np.cos(lon), -np.cos(lat) * np.sin(lon)],
[np.cos(lat), 0, -np.sin(lat)]
])
self.ecef2ned_matrix = self.ned2ecef_matrix.T
@classmethod
def from_geodetic(cls, geodetic):
"""
Create a LocalCoord instance from geodetic coordinates.
"""
return cls(geodetic=geodetic)
@classmethod
def from_ecef(cls, ecef):
"""
Create a LocalCoord instance from ECEF coordinates.
"""
return cls(ecef=ecef)
def ecef2ned_single(self, ecef):
"""
Convert a single ECEF point to NED coordinates relative to the origin.
"""
return self.ecef2ned_matrix @ (ecef - self.init_ecef)
def ned2ecef_single(self, ned):
"""
Convert a single NED point to ECEF coordinates.
"""
return self.ned2ecef_matrix @ ned + self.init_ecef
def geodetic2ned_single(self, geodetic):
"""
Convert a single geodetic point to NED coordinates.
"""
ecef = geodetic2ecef_single(geodetic)
return self.ecef2ned_single(ecef)
def ned2geodetic_single(self, ned):
"""
Convert a single NED point to geodetic coordinates.
"""
ecef = self.ned2ecef_single(ned)
return ecef2geodetic_single(ecef)
@property
def ned_from_ecef_matrix(self):
"""
Returns the rotation matrix from ECEF to NED coordinates.
"""
return self.ecef2ned_matrix
@property
def ecef_from_ned_matrix(self):
"""
Returns the rotation matrix from NED to ECEF coordinates.
"""
return self.ned2ecef_matrix
def ecef_euler_from_ned_single(ecef_init, ned_pose):
"""
Convert NED Euler angles (roll, pitch, yaw) at a given ECEF origin
to equivalent ECEF Euler angles.
"""
converter = LocalCoord(ecef=ecef_init)
zero = np.array(ecef_init)
x0 = converter.ned2ecef_single([1, 0, 0]) - zero
y0 = converter.ned2ecef_single([0, 1, 0]) - zero
z0 = converter.ned2ecef_single([0, 0, 1]) - zero
phi, theta, psi = ned_pose
x1 = axis_angle_to_rot(z0, psi) @ x0
y1 = axis_angle_to_rot(z0, psi) @ y0
z1 = axis_angle_to_rot(z0, psi) @ z0
x2 = axis_angle_to_rot(y1, theta) @ x1
y2 = axis_angle_to_rot(y1, theta) @ y1
z2 = axis_angle_to_rot(y1, theta) @ z1
x3 = axis_angle_to_rot(x2, phi) @ x2
y3 = axis_angle_to_rot(x2, phi) @ y2
x0 = np.array([1.0, 0, 0])
y0 = np.array([0, 1.0, 0])
z0 = np.array([0, 0, 1.0])
psi_out = np.arctan2(np.dot(x3, y0), np.dot(x3, x0))
theta_out = np.arctan2(-np.dot(x3, z0), np.sqrt(np.dot(x3, x0)**2 + np.dot(x3, y0)**2))
y2 = axis_angle_to_rot(z0, psi_out) @ y0
z2 = axis_angle_to_rot(y2, theta_out) @ z0
phi_out = np.arctan2(np.dot(y3, z2), np.dot(y3, y2))
return np.array([phi_out, theta_out, psi_out])
def ned_euler_from_ecef_single(ecef_init, ecef_pose):
"""
Convert ECEF Euler angles (roll, pitch, yaw) at a given ECEF origin
to equivalent NED Euler angles.
"""
converter = LocalCoord(ecef=ecef_init)
x0 = np.array([1.0, 0, 0])
y0 = np.array([0, 1.0, 0])
z0 = np.array([0, 0, 1.0])
phi, theta, psi = ecef_pose
x1 = axis_angle_to_rot(z0, psi) @ x0
y1 = axis_angle_to_rot(z0, psi) @ y0
z1 = axis_angle_to_rot(z0, psi) @ z0
x2 = axis_angle_to_rot(y1, theta) @ x1
y2 = axis_angle_to_rot(y1, theta) @ y1
z2 = axis_angle_to_rot(y1, theta) @ z1
x3 = axis_angle_to_rot(x2, phi) @ x2
y3 = axis_angle_to_rot(x2, phi) @ y2
zero = np.array(ecef_init)
x0 = converter.ned2ecef_single([1, 0, 0]) - zero
y0 = converter.ned2ecef_single([0, 1, 0]) - zero
z0 = converter.ned2ecef_single([0, 0, 1]) - zero
psi_out = np.arctan2(np.dot(x3, y0), np.dot(x3, x0))
theta_out = np.arctan2(-np.dot(x3, z0), np.sqrt(np.dot(x3, x0)**2 + np.dot(x3, y0)**2))
y2 = axis_angle_to_rot(z0, psi_out) @ y0
z2 = axis_angle_to_rot(y2, theta_out) @ z0
phi_out = np.arctan2(np.dot(y3, z2), np.dot(y3, y2))
return np.array([phi_out, theta_out, psi_out])
-173
View File
@@ -1,173 +0,0 @@
# distutils: language = c++
# cython: language_level = 3
from openpilot.common.transformations.transformations cimport Matrix3, Vector3, Quaternion
from openpilot.common.transformations.transformations cimport ECEF, NED, Geodetic
from openpilot.common.transformations.transformations cimport euler2quat as euler2quat_c
from openpilot.common.transformations.transformations cimport quat2euler as quat2euler_c
from openpilot.common.transformations.transformations cimport quat2rot as quat2rot_c
from openpilot.common.transformations.transformations cimport rot2quat as rot2quat_c
from openpilot.common.transformations.transformations cimport euler2rot as euler2rot_c
from openpilot.common.transformations.transformations cimport rot2euler as rot2euler_c
from openpilot.common.transformations.transformations cimport rot_matrix as rot_matrix_c
from openpilot.common.transformations.transformations cimport ecef_euler_from_ned as ecef_euler_from_ned_c
from openpilot.common.transformations.transformations cimport ned_euler_from_ecef as ned_euler_from_ecef_c
from openpilot.common.transformations.transformations cimport geodetic2ecef as geodetic2ecef_c
from openpilot.common.transformations.transformations cimport ecef2geodetic as ecef2geodetic_c
from openpilot.common.transformations.transformations cimport LocalCoord_c
import numpy as np
cimport numpy as np
cdef np.ndarray[double, ndim=2] matrix2numpy(Matrix3 m):
return np.array([
[m(0, 0), m(0, 1), m(0, 2)],
[m(1, 0), m(1, 1), m(1, 2)],
[m(2, 0), m(2, 1), m(2, 2)],
])
cdef Matrix3 numpy2matrix(np.ndarray[double, ndim=2, mode="fortran"] m):
assert m.shape[0] == 3
assert m.shape[1] == 3
return Matrix3(<double*>m.data)
cdef ECEF list2ecef(ecef):
cdef ECEF e
e.x = ecef[0]
e.y = ecef[1]
e.z = ecef[2]
return e
cdef NED list2ned(ned):
cdef NED n
n.n = ned[0]
n.e = ned[1]
n.d = ned[2]
return n
cdef Geodetic list2geodetic(geodetic):
cdef Geodetic g
g.lat = geodetic[0]
g.lon = geodetic[1]
g.alt = geodetic[2]
return g
def euler2quat_single(euler):
cdef Vector3 e = Vector3(euler[0], euler[1], euler[2])
cdef Quaternion q = euler2quat_c(e)
return [q.w(), q.x(), q.y(), q.z()]
def quat2euler_single(quat):
cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3])
cdef Vector3 e = quat2euler_c(q)
return [e(0), e(1), e(2)]
def quat2rot_single(quat):
cdef Quaternion q = Quaternion(quat[0], quat[1], quat[2], quat[3])
cdef Matrix3 r = quat2rot_c(q)
return matrix2numpy(r)
def rot2quat_single(rot):
cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double))
cdef Quaternion q = rot2quat_c(r)
return [q.w(), q.x(), q.y(), q.z()]
def euler2rot_single(euler):
cdef Vector3 e = Vector3(euler[0], euler[1], euler[2])
cdef Matrix3 r = euler2rot_c(e)
return matrix2numpy(r)
def rot2euler_single(rot):
cdef Matrix3 r = numpy2matrix(np.asfortranarray(rot, dtype=np.double))
cdef Vector3 e = rot2euler_c(r)
return [e(0), e(1), e(2)]
def rot_matrix(roll, pitch, yaw):
return matrix2numpy(rot_matrix_c(roll, pitch, yaw))
def ecef_euler_from_ned_single(ecef_init, ned_pose):
cdef ECEF init = list2ecef(ecef_init)
cdef Vector3 pose = Vector3(ned_pose[0], ned_pose[1], ned_pose[2])
cdef Vector3 e = ecef_euler_from_ned_c(init, pose)
return [e(0), e(1), e(2)]
def ned_euler_from_ecef_single(ecef_init, ecef_pose):
cdef ECEF init = list2ecef(ecef_init)
cdef Vector3 pose = Vector3(ecef_pose[0], ecef_pose[1], ecef_pose[2])
cdef Vector3 e = ned_euler_from_ecef_c(init, pose)
return [e(0), e(1), e(2)]
def geodetic2ecef_single(geodetic):
cdef Geodetic g = list2geodetic(geodetic)
cdef ECEF e = geodetic2ecef_c(g)
return [e.x, e.y, e.z]
def ecef2geodetic_single(ecef):
cdef ECEF e = list2ecef(ecef)
cdef Geodetic g = ecef2geodetic_c(e)
return [g.lat, g.lon, g.alt]
cdef class LocalCoord:
cdef LocalCoord_c * lc
def __init__(self, geodetic=None, ecef=None):
assert (geodetic is not None) or (ecef is not None)
if geodetic is not None:
self.lc = new LocalCoord_c(list2geodetic(geodetic))
elif ecef is not None:
self.lc = new LocalCoord_c(list2ecef(ecef))
@property
def ned2ecef_matrix(self):
return matrix2numpy(self.lc.ned2ecef_matrix)
@property
def ecef2ned_matrix(self):
return matrix2numpy(self.lc.ecef2ned_matrix)
@property
def ned_from_ecef_matrix(self):
return self.ecef2ned_matrix
@property
def ecef_from_ned_matrix(self):
return self.ned2ecef_matrix
@classmethod
def from_geodetic(cls, geodetic):
return cls(geodetic=geodetic)
@classmethod
def from_ecef(cls, ecef):
return cls(ecef=ecef)
def ecef2ned_single(self, ecef):
assert self.lc
cdef ECEF e = list2ecef(ecef)
cdef NED n = self.lc.ecef2ned(e)
return [n.n, n.e, n.d]
def ned2ecef_single(self, ned):
assert self.lc
cdef NED n = list2ned(ned)
cdef ECEF e = self.lc.ned2ecef(n)
return [e.x, e.y, e.z]
def geodetic2ned_single(self, geodetic):
assert self.lc
cdef Geodetic g = list2geodetic(geodetic)
cdef NED n = self.lc.geodetic2ned(g)
return [n.n, n.e, n.d]
def ned2geodetic_single(self, ned):
assert self.lc
cdef NED n = list2ned(ned)
cdef Geodetic g = self.lc.ned2geodetic(n)
return [g.lat, g.lon, g.alt]
def __dealloc__(self):
del self.lc
-46
View File
@@ -1,46 +0,0 @@
import os
import subprocess
def sudo_write(val: str, path: str) -> None:
try:
with open(path, 'w') as f:
f.write(str(val))
except PermissionError:
os.system(f"sudo chmod a+w {path}")
try:
with open(path, 'w') as f:
f.write(str(val))
except PermissionError:
# fallback for debugfs files
os.system(f"sudo su -c 'echo {val} > {path}'")
def sudo_read(path: str) -> str:
try:
return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8').strip()
except Exception:
return ""
class MovingAverage:
def __init__(self, window_size: int):
self.window_size: int = window_size
self.buffer: list[float] = [0.0] * window_size
self.index: int = 0
self.count: int = 0
self.sum: float = 0.0
def add_value(self, new_value: float):
# Update the sum: subtract the value being replaced and add the new value
self.sum -= self.buffer[self.index]
self.buffer[self.index] = new_value
self.sum += new_value
# Update the index in a circular manner
self.index = (self.index + 1) % self.window_size
# Track the number of added values (for partial windows)
self.count = min(self.count + 1, self.window_size)
def get_average(self) -> float:
if self.count == 0:
return float('nan')
return self.sum / self.count
+159 -5
View File
@@ -7,14 +7,82 @@ import time
import functools
from subprocess import Popen, PIPE, TimeoutExpired
import zstandard as zstd
from openpilot.common.swaglog import cloudlog
LOG_COMPRESSION_LEVEL = 10 # little benefit up to level 15. level ~17 is a small step change
class Timer:
"""Simple lap timer for profiling sequential operations."""
def __init__(self):
self._start = self._lap = time.monotonic()
self._sections = {}
def lap(self, name):
now = time.monotonic()
self._sections[name] = now - self._lap
self._lap = now
@property
def total(self):
return time.monotonic() - self._start
def fmt(self, duration):
parts = ", ".join(f"{k}={v:.2f}s" + (f" ({duration/v:.0f}x)" if k == 'render' and v > 0 else "") for k, v in self._sections.items())
total = self.total
realtime = f"{duration/total:.1f}x realtime" if total > 0 else "N/A"
return f"{duration}s in {total:.1f}s ({realtime}) | {parts}"
def sudo_write(val: str, path: str) -> None:
try:
with open(path, 'w') as f:
f.write(str(val))
except PermissionError:
os.system(f"sudo chmod a+w {path}")
try:
with open(path, 'w') as f:
f.write(str(val))
except PermissionError:
# fallback for debugfs files
os.system(f"sudo su -c 'echo {val} > {path}'")
def sudo_read(path: str) -> str:
try:
return subprocess.check_output(f"sudo cat {path}", shell=True, encoding='utf8').strip()
except Exception:
return ""
class MovingAverage:
def __init__(self, window_size: int):
self.window_size: int = window_size
self.buffer: list[float] = [0.0] * window_size
self.index: int = 0
self.count: int = 0
self.sum: float = 0.0
def add_value(self, new_value: float):
# Update the sum: subtract the value being replaced and add the new value
self.sum -= self.buffer[self.index]
self.buffer[self.index] = new_value
self.sum += new_value
# Update the index in a circular manner
self.index = (self.index + 1) % self.window_size
# Track the number of added values (for partial windows)
self.count = min(self.count + 1, self.window_size)
def get_average(self) -> float:
if self.count == 0:
return float('nan')
return self.sum / self.count
class CallbackReader:
"""Wraps a file, but overrides the read method to also
call a callback function with the number of bytes read so far."""
def __init__(self, f, callback, *args):
self.f = f
self.callback = callback
@@ -32,8 +100,8 @@ class CallbackReader:
@contextlib.contextmanager
def atomic_write_in_dir(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None,
overwrite: bool = False):
def atomic_write(path: str, mode: str = 'w', buffering: int = -1, encoding: str | None = None, newline: str | None = None,
overwrite: bool = False):
"""Write to a file atomically using a temporary file in the same directory as the destination file."""
dir_name = os.path.dirname(path)
@@ -99,6 +167,92 @@ def managed_proc(cmd: list[str], env: dict[str, str]):
proc.kill()
def tabulate(tabular_data, headers=(), tablefmt="simple", floatfmt="g", stralign="left", numalign=None):
rows = [list(row) for row in tabular_data]
def fmt(val):
if isinstance(val, str):
return val
if isinstance(val, (bool, int)):
return str(val)
try:
return format(val, floatfmt)
except (TypeError, ValueError):
return str(val)
formatted = [[fmt(c) for c in row] for row in rows]
hdrs = [str(h) for h in headers] if headers else None
ncols = max((len(r) for r in formatted), default=0)
if hdrs:
ncols = max(ncols, len(hdrs))
if ncols == 0:
return ""
for r in formatted:
r.extend([""] * (ncols - len(r)))
if hdrs:
hdrs.extend([""] * (ncols - len(hdrs)))
widths = [0] * ncols
if hdrs:
for i in range(ncols):
widths[i] = len(hdrs[i])
for row in formatted:
for i in range(ncols):
widths[i] = max(widths[i], max(len(ln) for ln in row[i].split('\n')))
def _align(s, w):
if stralign == "center":
return s.center(w)
return s.ljust(w)
if tablefmt == "html":
parts = ["<table>"]
if hdrs:
parts.append("<thead>")
parts.append("<tr>" + "".join(f"<th>{h}</th>" for h in hdrs) + "</tr>")
parts.append("</thead>")
parts.append("<tbody>")
for row in formatted:
parts.append("<tr>" + "".join(f"<td>{c}</td>" for c in row) + "</tr>")
parts.append("</tbody>")
parts.append("</table>")
return "\n".join(parts)
if tablefmt == "simple_grid":
def _sep(left, mid, right):
return left + mid.join("\u2500" * (w + 2) for w in widths) + right
top, mid_sep, bot = _sep("\u250c", "\u252c", "\u2510"), _sep("\u251c", "\u253c", "\u2524"), _sep("\u2514", "\u2534", "\u2518")
def _fmt_row(cells):
split = [c.split('\n') for c in cells]
nlines = max(len(s) for s in split)
for s in split:
s.extend([""] * (nlines - len(s)))
return ["\u2502" + "\u2502".join(f" {_align(split[i][li], widths[i])} " for i in range(ncols)) + "\u2502" for li in range(nlines)]
lines = [top]
if hdrs:
lines.extend(_fmt_row(hdrs))
lines.append(mid_sep)
for ri, row in enumerate(formatted):
lines.extend(_fmt_row(row))
lines.append(mid_sep if ri < len(formatted) - 1 else bot)
return "\n".join(lines)
# simple
gap = " "
lines = []
if hdrs:
lines.append(gap.join(h.ljust(w) for h, w in zip(hdrs, widths, strict=True)))
lines.append(gap.join("-" * w for w in widths))
for row in formatted:
lines.append(gap.join(_align(row[i], widths[i]) for i in range(ncols)))
return "\n".join(lines)
def retry(attempts=3, delay=1.0, ignore_failure=False):
def decorator(func):
@functools.wraps(func)
@@ -107,11 +261,11 @@ def retry(attempts=3, delay=1.0, ignore_failure=False):
try:
return func(*args, **kwargs)
except Exception:
cloudlog.exception(f"{func.__name__} failed, trying again")
print(f"{func.__name__} failed, trying again")
time.sleep(delay)
if ignore_failure:
cloudlog.error(f"{func.__name__} failed after retry")
print(f"{func.__name__} failed after retry")
else:
raise Exception(f"{func.__name__} failed after retry")
return wrapper
+1 -1
View File
@@ -1 +1 @@
#define COMMA_VERSION "0.10.2"
#define COMMA_VERSION "0.10.4"
+142 -149
View File
@@ -4,28 +4,26 @@
A supported vehicle is one that just works when you install a comma device. All supported cars provide a better experience than any stock system. Supported vehicles reference the US market unless otherwise specified.
# 341 Supported Cars
# 335 Supported Cars
|Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|<a href="##"><img width=2000></a>Hardware Needed<br>&nbsp;|Video|Setup Video|
|---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:|:---:|
|Acura|ILX 2016-18|Technology Plus Package or AcuraWatch Plus|openpilot|26 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2016-18">Buy Here</a></sub></details>|||
|Acura|ILX 2019|All|openpilot|26 mph|25 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura ILX 2019">Buy Here</a></sub></details>|||
|Acura|MDX 2025|All except Type S|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2025">Buy Here</a></sub></details>|||
|Acura|MDX 2025-26|All except Type S|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura MDX 2025-26">Buy Here</a></sub></details>|||
|Acura|RDX 2016-18|AcuraWatch Plus or Advance Package|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2016-18">Buy Here</a></sub></details>|||
|Acura|RDX 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura RDX 2019-21">Buy Here</a></sub></details>|||
|Acura|TLX 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2021">Buy Here</a></sub></details>|||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 2014-19">Buy Here</a></sub></details>|||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>|||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q2 2018">Buy Here</a></sub></details>|||
|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q3 2019-24">Buy Here</a></sub></details>|||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi RS3 2018">Buy Here</a></sub></details>|||
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi S3 2015-17">Buy Here</a></sub></details>|||
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EUV 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/xvwzGMUA210" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Acura|TLX 2025|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Acura TLX 2025">Buy Here</a></sub></details>|||
|Audi|A3 2014-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 2014-19">Buy Here</a></sub></details>|||
|Audi|A3 Sportback e-tron 2017-18|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi A3 Sportback e-tron 2017-18">Buy Here</a></sub></details>|||
|Audi|Q2 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q2 2018">Buy Here</a></sub></details>|||
|Audi|Q3 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi Q3 2019-24">Buy Here</a></sub></details>|||
|Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi RS3 2018">Buy Here</a></sub></details>|||
|Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Audi S3 2015-17">Buy Here</a></sub></details>|||
|Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim, without Super Cruise Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EUV 2022-23">Buy Here</a></sub></details>|<a href="https://youtu.be/xvwzGMUA210" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EV 2022-23">Buy Here</a></sub></details>|||
|Chevrolet|Bolt EV Non-ACC 2017|Adaptive Cruise Control (ACC)|Stock|24 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EV Non-ACC 2017">Buy Here</a></sub></details>|||
|Chevrolet|Bolt EV Non-ACC 2018-21|Adaptive Cruise Control (ACC)|Stock|24 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Bolt EV Non-ACC 2018-21">Buy Here</a></sub></details>|||
|Chevrolet|Equinox 2019-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Equinox 2019-22">Buy Here</a></sub></details>|||
|Chevrolet|Malibu Non-ACC 2016-23|Adaptive Cruise Control (ACC)|Stock|24 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Malibu Non-ACC 2016-23">Buy Here</a></sub></details>|||
|Chevrolet|Silverado 1500 2020-21|Safety Package II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Silverado 1500 2020-21">Buy Here</a></sub></details>|||
|Chevrolet|Trailblazer 2021-22|Adaptive Cruise Control (ACC)|openpilot available[<sup>1</sup>](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Trailblazer 2021-22">Buy Here</a></sub></details>|||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2017-18">Buy Here</a></sub></details>|||
@@ -34,33 +32,33 @@ A supported vehicle is one that just works when you install a comma device. All
|Chrysler|Pacifica Hybrid 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2017-18">Buy Here</a></sub></details>|||
|Chrysler|Pacifica Hybrid 2019-25|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica Hybrid 2019-25">Buy Here</a></sub></details>|||
|comma|body|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|None|<a href="https://youtu.be/VT-i3yRsX2s?t=2736" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=CUPRA Ateca 2018-23">Buy Here</a></sub></details>|||
|CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=CUPRA Ateca 2018-23">Buy Here</a></sub></details>|||
|Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Dodge Durango 2020-21">Buy Here</a></sub></details>|||
|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Bronco Sport 2021-24">Buy Here</a></sub></details>|||
|Ford|Escape 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2020-22">Buy Here</a></sub></details>|||
|Ford|Escape 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Escape 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2020-22">Buy Here</a></sub></details>|||
|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Escape Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2020-22">Buy Here</a></sub></details>|||
|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Expedition 2022-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Escape Plug-in Hybrid 2023-24|Co-Pilot360 Assist+|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Escape Plug-in Hybrid 2023-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Expedition 2022-24|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Expedition 2022-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Explorer 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer 2020-24">Buy Here</a></sub></details>|||
|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Explorer Hybrid 2020-24">Buy Here</a></sub></details>|||
|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 Hybrid 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Focus 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus 2018">Buy Here</a></sub></details>|||
|Ford|Focus Hybrid 2018[<sup>3</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus Hybrid 2018">Buy Here</a></sub></details>|||
|Ford|F-150 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|F-150 Hybrid 2021-23|Co-Pilot360 Assist 2.0|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford F-150 Hybrid 2021-23">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=MewJc9LYp9M" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Focus 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus 2018">Buy Here</a></sub></details>|||
|Ford|Focus Hybrid 2018[<sup>2</sup>](#footnotes)|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Focus Hybrid 2018">Buy Here</a></sub></details>|||
|Ford|Kuga 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga 2020-23">Buy Here</a></sub></details>|||
|Ford|Kuga Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2020-23">Buy Here</a></sub></details>|||
|Ford|Kuga Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Kuga Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Kuga Plug-in Hybrid 2020-23|Adaptive Cruise Control with Lane Centering|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2020-23">Buy Here</a></sub></details>|||
|Ford|Kuga Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Kuga Plug-in Hybrid 2024|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Kuga Plug-in Hybrid 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Maverick 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2022">Buy Here</a></sub></details>|||
|Ford|Maverick 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick 2023-24">Buy Here</a></sub></details>|||
|Ford|Maverick Hybrid 2022|LARIAT Luxury|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2022">Buy Here</a></sub></details>|||
|Ford|Maverick Hybrid 2023-24|Co-Pilot360 Assist|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Maverick Hybrid 2023-24">Buy Here</a></sub></details>|||
|Ford|Mustang Mach-E 2021-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Mustang Mach-E 2021-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Ranger 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Mustang Mach-E 2021-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Mustang Mach-E 2021-24">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Ford|Ranger 2024|Adaptive Cruise Control with Lane Centering|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q4 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ford Ranger 2024">Buy Here</a></sub></details>||<a href="https://www.youtube.com/watch?v=uUGkH6C_EQU" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Genesis|G70 2018|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2018">Buy Here</a></sub></details>|||
|Genesis|G70 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai F connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2019-21">Buy Here</a></sub></details>|||
|Genesis|G70 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Genesis G70 2022-23">Buy Here</a></sub></details>|||
@@ -82,7 +80,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Honda|Accord Hybrid 2023-25|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Accord Hybrid 2023-25">Buy Here</a></sub></details>|||
|Honda|City (Brazil only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|14 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda City (Brazil only) 2023">Buy Here</a></sub></details>|||
|Honda|Civic 2016-18|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2016-18">Buy Here</a></sub></details>|<a href="https://youtu.be/-IkImTe1NYE" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>5</sup>](#footnotes)|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=4Iz1Mz5LGF8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Honda|Civic 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|2 mph[<sup>4</sup>](#footnotes)|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=4Iz1Mz5LGF8" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Honda|Civic 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic 2022-24">Buy Here</a></sub></details>|<a href="https://youtu.be/ytiOT5lcp6Q" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Honda|Civic Hatchback 2017-18|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2017-18">Buy Here</a></sub></details>|||
|Honda|Civic Hatchback 2019-21|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback 2019-21">Buy Here</a></sub></details>|||
@@ -90,12 +88,11 @@ A supported vehicle is one that just works when you install a comma device. All
|Honda|Civic Hatchback Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid 2025-26">Buy Here</a></sub></details>|||
|Honda|Civic Hatchback Hybrid (Europe only) 2023|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hatchback Hybrid (Europe only) 2023">Buy Here</a></sub></details>|||
|Honda|Civic Hybrid 2025-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Civic Hybrid 2025-26">Buy Here</a></sub></details>|||
|Honda|Clarity 2018-21|Honda Sensing|openpilot|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector + Honda Clarity Proxy Board<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://shop.retropilot.org/product/honda-clarity-proxy-board-kit">Buy Here</a></sub></details>|||
|Honda|CR-V 2015-16|Touring Trim|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2015-16">Buy Here</a></sub></details>|||
|Honda|CR-V 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|15 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2017-22">Buy Here</a></sub></details>|||
|Honda|CR-V 2023-26|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V 2023-26">Buy Here</a></sub></details>|||
|Honda|CR-V Hybrid 2017-22|Honda Sensing|openpilot available[<sup>1</sup>](#footnotes)|0 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V Hybrid 2017-22">Buy Here</a></sub></details>|||
|Honda|CR-V Hybrid 2023-25|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V Hybrid 2023-25">Buy Here</a></sub></details>|||
|Honda|CR-V Hybrid 2023-26|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda CR-V Hybrid 2023-26">Buy Here</a></sub></details>|||
|Honda|e 2020|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|3 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda e 2020">Buy Here</a></sub></details>|||
|Honda|Fit 2018-20|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Fit 2018-20">Buy Here</a></sub></details>|||
|Honda|Freed 2020|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Freed 2020">Buy Here</a></sub></details>|||
@@ -106,6 +103,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Honda|N-Box 2018|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|11 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda N-Box 2018">Buy Here</a></sub></details>|||
|Honda|Odyssey 2018-20|Honda Sensing|openpilot|26 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2018-20">Buy Here</a></sub></details>|||
|Honda|Odyssey 2021-26|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|43 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey 2021-26">Buy Here</a></sub></details>|||
|Honda|Odyssey (Taiwan) 2018-19|Honda Sensing|openpilot|19 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Odyssey (Taiwan) 2018-19">Buy Here</a></sub></details>|||
|Honda|Passport 2019-25|All|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2019-25">Buy Here</a></sub></details>|||
|Honda|Passport 2026|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Bosch C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Passport 2026">Buy Here</a></sub></details>|||
|Honda|Pilot 2016-22|Honda Sensing|openpilot|26 mph|12 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Honda Nidec connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Honda Pilot 2016-22">Buy Here</a></sub></details>|||
@@ -120,7 +118,6 @@ A supported vehicle is one that just works when you install a comma device. All
|Hyundai|Elantra 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Hyundai|Elantra GT 2017-20|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra GT 2017-20">Buy Here</a></sub></details>|||
|Hyundai|Elantra Hybrid 2021-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Hybrid 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/_EdYQtV52-c" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Hyundai|Elantra Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Elantra Non-SCC 2022">Buy Here</a></sub></details>|||
|Hyundai|Genesis 2015-16|Smart Cruise Control (SCC)|Stock|19 mph|37 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai J connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Genesis 2015-16">Buy Here</a></sub></details>|||
|Hyundai|i30 2017-19|Smart Cruise Control (SCC)|Stock|0 mph|32 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai i30 2017-19">Buy Here</a></sub></details>|||
|Hyundai|Ioniq 5 (Southeast Asia and Europe only) 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Ioniq 5 (Southeast Asia and Europe only) 2022-24">Buy Here</a></sub></details>|||
@@ -138,9 +135,7 @@ A supported vehicle is one that just works when you install a comma device. All
|Hyundai|Kona Electric 2018-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2018-21">Buy Here</a></sub></details>|||
|Hyundai|Kona Electric 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai O connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric 2022-23">Buy Here</a></sub></details>|||
|Hyundai|Kona Electric (with HDA II, Korea only) 2023|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai R connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric (with HDA II, Korea only) 2023">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=U2fOCmcQ8hw" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Hyundai|Kona Electric Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Electric Non-SCC 2019">Buy Here</a></sub></details>|||
|Hyundai|Kona Hybrid 2020|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Hybrid 2020">Buy Here</a></sub></details>|||
|Hyundai|Kona Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Kona Non-SCC 2019">Buy Here</a></sub></details>|||
|Hyundai|Nexo 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Nexo 2021">Buy Here</a></sub></details>|||
|Hyundai|Palisade 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Palisade 2020-22">Buy Here</a></sub></details>|<a href="https://youtu.be/TAnDqjF4fDY?t=456" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Hyundai|Santa Cruz 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai N connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Hyundai Santa Cruz 2022-24">Buy Here</a></sub></details>|||
@@ -164,13 +159,11 @@ A supported vehicle is one that just works when you install a comma device. All
|Kia|Carnival 2022-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival 2022-24">Buy Here</a></sub></details>|||
|Kia|Carnival (China only) 2023|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Carnival (China only) 2023">Buy Here</a></sub></details>|||
|Kia|Ceed 2019-21|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed 2019-21">Buy Here</a></sub></details>|||
|Kia|Ceed Plug-in Hybrid Non-SCC 2022|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai I connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Ceed Plug-in Hybrid Non-SCC 2022">Buy Here</a></sub></details>|||
|Kia|EV6 (Southeast Asia only) 2022-24|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (Southeast Asia only) 2022-24">Buy Here</a></sub></details>|||
|Kia|EV6 (with HDA II) 2022-24|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai P connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (with HDA II) 2022-24">Buy Here</a></sub></details>|||
|Kia|EV6 (without HDA II) 2022-24|Highway Driving Assist|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai L connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia EV6 (without HDA II) 2022-24">Buy Here</a></sub></details>|||
|Kia|Forte 2019-21|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|6 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Forte 2019-21">Buy Here</a></sub></details>|||
|Kia|Forte 2022-23|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai E connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Forte 2022-23">Buy Here</a></sub></details>|||
|Kia|Forte Non-SCC 2019|No Smart Cruise Control (Non-SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai G connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Forte Non-SCC 2019">Buy Here</a></sub></details>|||
|Kia|K5 2021-24|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K5 2021-24">Buy Here</a></sub></details>|||
|Kia|K5 Hybrid 2020-22|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K5 Hybrid 2020-22">Buy Here</a></sub></details>|||
|Kia|K8 Hybrid (with HDA II) 2023|Highway Driving Assist II|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai Q connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia K8 Hybrid (with HDA II) 2023">Buy Here</a></sub></details>|||
@@ -202,171 +195,171 @@ A supported vehicle is one that just works when you install a comma device. All
|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai C connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=MJ94qoofYw0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Kia|Stinger 2022-23|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai K connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Stinger 2022-23">Buy Here</a></sub></details>|||
|Kia|Telluride 2020-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Hyundai H connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Kia Telluride 2020-22">Buy Here</a></sub></details>|||
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus CT Hybrid 2017-18">Buy Here</a></sub></details>|||
|Lexus|ES 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2017-18">Buy Here</a></sub></details>|||
|Lexus|CT Hybrid 2017-18|Lexus Safety System+|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus CT Hybrid 2017-18">Buy Here</a></sub></details>|||
|Lexus|ES 2017-18|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2017-18">Buy Here</a></sub></details>|||
|Lexus|ES 2019-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES 2019-25">Buy Here</a></sub></details>|||
|Lexus|ES Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2017-18">Buy Here</a></sub></details>|||
|Lexus|ES Hybrid 2017-18|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2017-18">Buy Here</a></sub></details>|||
|Lexus|ES Hybrid 2019-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus ES Hybrid 2019-25">Buy Here</a></sub></details>|<a href="https://youtu.be/BZ29osRVJeg?t=12" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Lexus|GS F 2016|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus GS F 2016">Buy Here</a></sub></details>|||
|Lexus|IS 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2017-19">Buy Here</a></sub></details>|||
|Lexus|IS 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus IS 2022-24">Buy Here</a></sub></details>|||
|Lexus|LC 2024-25|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus LC 2024-25">Buy Here</a></sub></details>|||
|Lexus|NX 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX 2018-19">Buy Here</a></sub></details>|||
|Lexus|LS 2018|All except Lexus Safety System+ A|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus LS 2018">Buy Here</a></sub></details>|||
|Lexus|NX 2018-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX 2018-19">Buy Here</a></sub></details>|||
|Lexus|NX 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX 2020-21">Buy Here</a></sub></details>|||
|Lexus|NX Hybrid 2018-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX Hybrid 2018-19">Buy Here</a></sub></details>|||
|Lexus|NX Hybrid 2018-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX Hybrid 2018-19">Buy Here</a></sub></details>|||
|Lexus|NX Hybrid 2020-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus NX Hybrid 2020-21">Buy Here</a></sub></details>|||
|Lexus|RC 2018-20|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RC 2018-20">Buy Here</a></sub></details>|||
|Lexus|RC 2023|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RC 2023">Buy Here</a></sub></details>|||
|Lexus|RX 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX 2016">Buy Here</a></sub></details>|||
|Lexus|RX 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX 2017-19">Buy Here</a></sub></details>|||
|Lexus|RX 2016|Lexus Safety System+|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX 2016">Buy Here</a></sub></details>|||
|Lexus|RX 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX 2017-19">Buy Here</a></sub></details>|||
|Lexus|RX 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX 2020-22">Buy Here</a></sub></details>|||
|Lexus|RX Hybrid 2016|Lexus Safety System+|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX Hybrid 2016">Buy Here</a></sub></details>|||
|Lexus|RX Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX Hybrid 2017-19">Buy Here</a></sub></details>|||
|Lexus|RX Hybrid 2016|Lexus Safety System+|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX Hybrid 2016">Buy Here</a></sub></details>|||
|Lexus|RX Hybrid 2017-19|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX Hybrid 2017-19">Buy Here</a></sub></details>|||
|Lexus|RX Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus RX Hybrid 2020-22">Buy Here</a></sub></details>|||
|Lexus|UX Hybrid 2019-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lexus UX Hybrid 2019-24">Buy Here</a></sub></details>|||
|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator 2020-24">Buy Here</a></sub></details>|||
|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Ford Q3 connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Lincoln Aviator Plug-in Hybrid 2020-24">Buy Here</a></sub></details>|||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN eTGE 2020-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=MAN TGE 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Mazda|CX-5 2022-25|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-5 2022-25">Buy Here</a></sub></details>|||
|Mazda|CX-9 2021-23|All|Stock|0 mph|28 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 Mazda connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Mazda CX-9 2021-23">Buy Here</a></sub></details>|<a href="https://youtu.be/dA3duO4a0O4" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Nissan[<sup>6</sup>](#footnotes)|Altima 2019-20, 2024|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Altima 2019-20, 2024">Buy Here</a></sub></details>|||
|Nissan[<sup>6</sup>](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Nissan[<sup>6</sup>](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Rogue 2018-20">Buy Here</a></sub></details>|||
|Nissan[<sup>6</sup>](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan X-Trail 2017">Buy Here</a></sub></details>|||
|Nissan[<sup>5</sup>](#footnotes)|Altima 2019-20, 2024|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan B connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Altima 2019-20, 2024">Buy Here</a></sub></details>|||
|Nissan[<sup>5</sup>](#footnotes)|Leaf 2018-23|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Leaf 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/vaMbtAh_0cY" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Nissan[<sup>5</sup>](#footnotes)|Rogue 2018-20|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan Rogue 2018-20">Buy Here</a></sub></details>|||
|Nissan[<sup>5</sup>](#footnotes)|X-Trail 2017|ProPILOT Assist|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 Nissan A connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Nissan X-Trail 2017">Buy Here</a></sub></details>|||
|Ram|1500 2019-24|Adaptive Cruise Control (ACC)|Stock|32 mph|1 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 1500 2019-24">Buy Here</a></sub></details>|||
|Ram|2500 2020-24|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 2500 2020-24">Buy Here</a></sub></details>|||
|Ram|3500 2019-22|Adaptive Cruise Control (ACC)|Stock|0 mph|36 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Ram connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Ram 3500 2019-22">Buy Here</a></sub></details>|||
|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1S 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1T 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Ateca 2016-23">Buy Here</a></sub></details>|||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Leon 2014-20">Buy Here</a></sub></details>|||
|Subaru|Ascent 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Forester 2017-18|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2017-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Forester 2019-21|All[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Impreza 2017-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Impreza 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Legacy 2015-18|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Legacy 2015-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Legacy 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Legacy 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2015-17|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2015-17">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2020-22|All[<sup>7</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>7</sup>](#footnotes)|openpilot available[<sup>1,8</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Škoda|Fabia 2022-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Fabia 2022-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Škoda|Kamiq 2021-23[<sup>12,14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kamiq 2021-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Škoda|Karoq 2019-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Karoq 2019-23">Buy Here</a></sub></details>|||
|Škoda|Kodiaq 2017-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kodiaq 2017-23">Buy Here</a></sub></details>|||
|Škoda|Octavia 2015-19[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia 2015-19">Buy Here</a></sub></details>|||
|Škoda|Octavia RS 2016[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia RS 2016">Buy Here</a></sub></details>|||
|Škoda|Octavia Scout 2017-19[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia Scout 2017-19">Buy Here</a></sub></details>|||
|Škoda|Scala 2020-23[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Scala 2020-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Škoda|Superb 2015-22[<sup>14</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Superb 2015-22">Buy Here</a></sub></details>|||
|Tesla[<sup>10</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>9</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW3) 2019-23">Buy Here</a></sub></details>|||
|Tesla[<sup>10</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>9</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW4) 2024-25">Buy Here</a></sub></details>|||
|Tesla[<sup>10</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>9</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW3) 2020-23">Buy Here</a></sub></details>|||
|Tesla[<sup>10</sup>](#footnotes)|Model Y (with HW4) 2024-25[<sup>9</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW4) 2024-25">Buy Here</a></sub></details>|||
|Rivian|R1S 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1S 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|Rivian|R1T 2022-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Rivian A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Rivian R1T 2022-24">Buy Here</a></sub></details>||<a href="https://youtu.be/uaISd1j7Z4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>|
|SEAT|Ateca 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Ateca 2016-23">Buy Here</a></sub></details>|||
|SEAT|Leon 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=SEAT Leon 2014-20">Buy Here</a></sub></details>|||
|Subaru|Ascent 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Ascent 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Crosstrek 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Subaru|Crosstrek 2020-23|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Crosstrek 2020-23">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Forester 2017-18|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2017-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Forester 2019-21|All[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Forester 2019-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Impreza 2017-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Impreza 2017-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Impreza 2020-22|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Impreza 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Legacy 2015-18|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Legacy 2015-18">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Legacy 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Legacy 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2015-17|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2015-17">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|Outback 2020-22|All[<sup>6</sup>](#footnotes)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru B connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru Outback 2020-22">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Subaru|XV 2018-19|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-empty.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2018-19">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|<a href="https://youtu.be/Agww7oE1k-s?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Subaru|XV 2020-21|EyeSight Driver Assistance[<sup>6</sup>](#footnotes)|openpilot available[<sup>1,7</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Subaru A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Subaru XV 2020-21">Buy Here</a></sub></details><details><summary>Tools</summary><sub>- 1 Pry Tool<br>- 1 Socket Wrench 8mm or 5/16" (deep)</sub></details>|||
|Škoda|Fabia 2022-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Fabia 2022-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Škoda|Kamiq 2021-23[<sup>11,13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kamiq 2021-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Škoda|Karoq 2019-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Karoq 2019-23">Buy Here</a></sub></details>|||
|Škoda|Kodiaq 2017-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Kodiaq 2017-23">Buy Here</a></sub></details>|||
|Škoda|Octavia 2015-19[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia 2015-19">Buy Here</a></sub></details>|||
|Škoda|Octavia RS 2016[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia RS 2016">Buy Here</a></sub></details>|||
|Škoda|Octavia Scout 2017-19[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Octavia Scout 2017-19">Buy Here</a></sub></details>|||
|Škoda|Scala 2020-23[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Scala 2020-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Škoda|Superb 2015-22[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Škoda Superb 2015-22">Buy Here</a></sub></details>|||
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW3) 2019-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW3) 2019-23">Buy Here</a></sub></details>|||
|Tesla[<sup>9</sup>](#footnotes)|Model 3 (with HW4) 2024-25[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model 3 (with HW4) 2024-25">Buy Here</a></sub></details>|||
|Tesla[<sup>9</sup>](#footnotes)|Model Y (with HW3) 2020-23[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla A connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW3) 2020-23">Buy Here</a></sub></details>|||
|Tesla[<sup>9</sup>](#footnotes)|Model Y (with HW4) 2024-25[<sup>8</sup>](#footnotes)|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Tesla B connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Tesla Model Y (with HW4) 2024-25">Buy Here</a></sub></details>|||
|Toyota|Alphard 2019-20|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Alphard 2019-20">Buy Here</a></sub></details>|||
|Toyota|Alphard Hybrid 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Alphard Hybrid 2021">Buy Here</a></sub></details>|||
|Toyota|Avalon 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2016">Buy Here</a></sub></details>|||
|Toyota|Avalon 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2017-18">Buy Here</a></sub></details>|||
|Toyota|Avalon 2019-21|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2019-21">Buy Here</a></sub></details>|||
|Toyota|Avalon 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2016">Buy Here</a></sub></details>|||
|Toyota|Avalon 2017-18|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2017-18">Buy Here</a></sub></details>|||
|Toyota|Avalon 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2019-21">Buy Here</a></sub></details>|||
|Toyota|Avalon 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon 2022">Buy Here</a></sub></details>|||
|Toyota|Avalon Hybrid 2019-21|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon Hybrid 2019-21">Buy Here</a></sub></details>|||
|Toyota|Avalon Hybrid 2019-21|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon Hybrid 2019-21">Buy Here</a></sub></details>|||
|Toyota|Avalon Hybrid 2022|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Avalon Hybrid 2022">Buy Here</a></sub></details>|||
|Toyota|C-HR 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR 2017-20">Buy Here</a></sub></details>|||
|Toyota|C-HR 2021|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR 2021">Buy Here</a></sub></details>|||
|Toyota|C-HR Hybrid 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2017-20">Buy Here</a></sub></details>|||
|Toyota|C-HR Hybrid 2021-22|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota C-HR Hybrid 2021-22">Buy Here</a></sub></details>|||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>11</sup>](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>11</sup>](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2021-24">Buy Here</a></sub></details>|||
|Toyota|Camry 2018-20|All|Stock|0 mph[<sup>10</sup>](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=fkcjviZY9CM" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Camry 2021-24|All|openpilot|0 mph[<sup>10</sup>](#footnotes)|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry 2021-24">Buy Here</a></sub></details>|||
|Toyota|Camry Hybrid 2018-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=Q2DYY0AWKgk" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Camry Hybrid 2021-24|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Camry Hybrid 2021-24">Buy Here</a></sub></details>|||
|Toyota|Corolla 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2017-19">Buy Here</a></sub></details>|||
|Toyota|Corolla 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2017-19">Buy Here</a></sub></details>|||
|Toyota|Corolla 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla 2020-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Corolla Cross (Non-US only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross (Non-US only) 2020-23">Buy Here</a></sub></details>|||
|Toyota|Corolla Cross Hybrid (Non-US only) 2020-22|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Cross Hybrid (Non-US only) 2020-22">Buy Here</a></sub></details>|||
|Toyota|Corolla Hatchback 2019-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hatchback 2019-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=_66pXk0CBYA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Corolla Hybrid 2020-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid 2020-22">Buy Here</a></sub></details>|||
|Toyota|Corolla Hybrid (South America only) 2020-23|All|openpilot|17 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Corolla Hybrid (South America only) 2020-23">Buy Here</a></sub></details>|||
|Toyota|Highlander 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2017-19">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0wS0wXSLzoo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Highlander 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2017-19">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=0wS0wXSLzoo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Highlander 2020-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander 2020-23">Buy Here</a></sub></details>|||
|Toyota|Highlander Hybrid 2017-19|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2017-19">Buy Here</a></sub></details>|||
|Toyota|Highlander Hybrid 2017-19|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2017-19">Buy Here</a></sub></details>|||
|Toyota|Highlander Hybrid 2020-23|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Highlander Hybrid 2020-23">Buy Here</a></sub></details>|||
|Toyota|Mirai 2021|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Mirai 2021">Buy Here</a></sub></details>|||
|Toyota|Prius 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2016">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius 2017-20|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius 2016|Toyota Safety Sense P|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2016">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius Prime 2017-20|All|openpilot available[<sup>2</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius Prime 2017-20|All|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2017-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=8zopPJI8XQ0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius Prime 2021-22|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius Prime 2021-22">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=J58TvCpUd4U" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Prius v 2017|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius v 2017">Buy Here</a></sub></details>|||
|Toyota|RAV4 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2016">Buy Here</a></sub></details>|||
|Toyota|RAV4 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2017-18">Buy Here</a></sub></details>|||
|Toyota|Prius v 2017|Toyota Safety Sense P|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Prius v 2017">Buy Here</a></sub></details>|||
|Toyota|RAV4 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2016">Buy Here</a></sub></details>|||
|Toyota|RAV4 2017-18|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2017-18">Buy Here</a></sub></details>|||
|Toyota|RAV4 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2019-21">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=wJxjDd42gGA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2022">Buy Here</a></sub></details>|||
|Toyota|RAV4 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 2023-25">Buy Here</a></sub></details>|||
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2016">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 Hybrid 2017-18|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 Hybrid 2016|Toyota Safety Sense P|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2016">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 Hybrid 2017-18|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/LhT5VzJVfNI?t=26" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 Hybrid 2019-21|All|openpilot|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2019-21">Buy Here</a></sub></details>|||
|Toyota|RAV4 Hybrid 2022|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2022">Buy Here</a></sub></details>|<a href="https://youtu.be/U0nH9cnrFB0" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|RAV4 Hybrid 2023-25|All|openpilot available[<sup>1</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota RAV4 Hybrid 2023-25">Buy Here</a></sub></details>|<a href="https://youtu.be/4eIsEq4L4Ng" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Toyota|Sienna 2018-20|All|openpilot available[<sup>2</sup>](#footnotes)|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon Shooting Brake 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas 2018-23">Buy Here</a></sub></details>|||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas Cross Sport 2020-22">Buy Here</a></sub></details>|||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen California 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Caravelle 2020">Buy Here</a></sub></details>|||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Crafter 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Crafter 2018-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Golf 2014-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf Alltrack 2015-19">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTD 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTE 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTI 2015-21">Buy Here</a></sub></details>|||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf R 2015-19">Buy Here</a></sub></details>|||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf SportsVan 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Grand California 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Jetta 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta 2018-23">Buy Here</a></sub></details>|||
|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta GLI 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Passat 2015-22[<sup>13</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat Alltrack 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat GTE 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo 2018-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Cross 2021">Buy Here</a></sub></details>[<sup>16</sup>](#footnotes)|||
|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Roc 2018-23">Buy Here</a></sub></details>|||
|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Taos 2022-24">Buy Here</a></sub></details>|||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont 2018-22">Buy Here</a></sub></details>|||
|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont Cross Sport 2021-22">Buy Here</a></sub></details>|||
|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont X 2021-22">Buy Here</a></sub></details>|||
|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan 2018-24">Buy Here</a></sub></details>|||
|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan eHybrid 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,15</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Touran 2016-23">Buy Here</a></sub></details>|||
|Toyota|Sienna 2018-20|All|Stock|19 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 Toyota A connector<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Toyota Sienna 2018-20">Buy Here</a></sub></details>|<a href="https://www.youtube.com/watch?v=q1UPOo4Sh68" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon 2018-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon eHybrid 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon eHybrid 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon R 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon R 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Arteon Shooting Brake 2020-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Arteon Shooting Brake 2020-23">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Atlas 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas 2018-23">Buy Here</a></sub></details>|||
|Volkswagen|Atlas Cross Sport 2020-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Atlas Cross Sport 2020-22">Buy Here</a></sub></details>|||
|Volkswagen|California 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen California 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Caravelle 2020|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Caravelle 2020">Buy Here</a></sub></details>|||
|Volkswagen|CC 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen CC 2018-22">Buy Here</a></sub></details>|<a href="https://youtu.be/FAomFKPFlDA" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Crafter 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Crafter 2017-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|e-Crafter 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Crafter 2018-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|e-Golf 2014-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen e-Golf 2014-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf Alltrack 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf Alltrack 2015-19">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTD 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTD 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTE 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTE 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Golf GTI 2015-21|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf GTI 2015-21">Buy Here</a></sub></details>|||
|Volkswagen|Golf R 2015-19|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf R 2015-19">Buy Here</a></sub></details>|||
|Volkswagen|Golf SportsVan 2015-20|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Golf SportsVan 2015-20">Buy Here</a></sub></details>|||
|Volkswagen|Grand California 2019-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|31 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Grand California 2019-24">Buy Here</a></sub></details>|<a href="https://youtu.be/4100gLeabmo" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|Volkswagen|Jetta 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta 2019-23">Buy Here</a></sub></details>|||
|Volkswagen|Jetta GLI 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Jetta GLI 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Passat 2015-22[<sup>12</sup>](#footnotes)|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Passat Alltrack 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat Alltrack 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Passat GTE 2015-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Passat GTE 2015-22">Buy Here</a></sub></details>|||
|Volkswagen|Polo 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo 2018-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Volkswagen|Polo GTI 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Polo GTI 2018-23">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Volkswagen|T-Cross 2021|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Cross 2021">Buy Here</a></sub></details>[<sup>15</sup>](#footnotes)|||
|Volkswagen|T-Roc 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen T-Roc 2018-23">Buy Here</a></sub></details>|||
|Volkswagen|Taos 2022-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Taos 2022-24">Buy Here</a></sub></details>|||
|Volkswagen|Teramont 2018-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont 2018-22">Buy Here</a></sub></details>|||
|Volkswagen|Teramont Cross Sport 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont Cross Sport 2021-22">Buy Here</a></sub></details>|||
|Volkswagen|Teramont X 2021-22|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Teramont X 2021-22">Buy Here</a></sub></details>|||
|Volkswagen|Tiguan 2018-24|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan 2018-24">Buy Here</a></sub></details>|||
|Volkswagen|Tiguan eHybrid 2021-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Tiguan eHybrid 2021-23">Buy Here</a></sub></details>|||
|Volkswagen|Touran 2016-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[<sup>1,14</sup>](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|<details><summary>Parts</summary><sub>- 1 OBD-C cable (2 ft)<br>- 1 VW J533 connector<br>- 1 comma four<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Volkswagen Touran 2016-23">Buy Here</a></sub></details>|||
### Footnotes
<sup>1</sup>openpilot Longitudinal Control (Alpha) is available behind a toggle; the toggle is only available in non-release branches such as `devel` or `nightly-dev`. <br />
<sup>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>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/gm" target="_blank">GM</a>. <br />
<sup>5</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
<sup>6</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/nissan" target="_blank">Nissan</a>. <br />
<sup>7</sup>In the non-US market, openpilot requires the car to come equipped with EyeSight with Lane Keep Assistance. <br />
<sup>8</sup>Enabling longitudinal control (alpha) will disable all EyeSight functionality, including AEB, LDW, and RAB. <br />
<sup>9</sup>Some 2023 model years have HW4. To check which hardware type your vehicle has, look for <b>Autopilot computer</b> under <b>Software -> Additional Vehicle Information</b> on your vehicle's touchscreen. See <a href="https://www.notateslaapp.com/news/2173/how-to-check-if-your-tesla-has-hardware-4-ai4-or-hardware-3">this page</a> for more information. <br />
<sup>10</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
<sup>11</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
<sup>12</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
<sup>13</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
<sup>14</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma four functionality. <br />
<sup>15</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
<sup>16</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
<sup>2</sup>Refers only to the Focus Mk4 (C519) available in Europe/China/Taiwan/Australasia, not the Focus Mk3 (C346) in North and South America/Southeast Asia. <br />
<sup>3</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/gm" target="_blank">GM</a>. <br />
<sup>4</sup>2019 Honda Civic 1.6L Diesel Sedan does not have ALC below 12mph. <br />
<sup>5</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/nissan" target="_blank">Nissan</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>Some 2023 model years have HW4. To check which hardware type your vehicle has, look for <b>Autopilot computer</b> under <b>Software -> Additional Vehicle Information</b> on your vehicle's touchscreen. See <a href="https://www.notateslaapp.com/news/2173/how-to-check-if-your-tesla-has-hardware-4-ai4-or-hardware-3">this page</a> for more information. <br />
<sup>9</sup>See more setup details for <a href="https://github.com/commaai/openpilot/wiki/tesla" target="_blank">Tesla</a>. <br />
<sup>10</sup>openpilot operates above 28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
<sup>11</sup>Not including the China market Kamiq, which is based on the (currently) unsupported PQ34 platform. <br />
<sup>12</sup>Refers only to the MQB-based European B8 Passat, not the NMS Passat in the USA/China/Mideast markets. <br />
<sup>13</sup>Some Škoda vehicles are equipped with heated windshields, which are known to block GPS signal needed for some comma four functionality. <br />
<sup>14</sup>Only available for vehicles using a gateway (J533) harness. At this time, vehicles using a camera harness are limited to using stock ACC. <br />
<sup>15</sup>Model-years 2022 and beyond may have a combined CAN gateway and BCM, which is supported by openpilot in software, but doesn't yet have a harness available from the comma store. <br />
## 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/).
@@ -384,7 +377,7 @@ If your car has the following packages or features, then it's a good candidate f
| Make | Required Package/Features |
| ---- | ------------------------- |
| Acura | Any car with AcuraWatch Plus will work. AcuraWatch Plus comes standard on many newer models. |
| Acura | Any car with AcuraWatch will work. AcuraWatch comes standard on many newer models. |
| Ford | Any car with Lane Centering will likely work. |
| Honda | Any car with Honda Sensing will work. Honda Sensing comes standard on many newer models. |
| Subaru | Any car with EyeSight will work. EyeSight comes standard on many newer models. |
+17 -20
View File
@@ -31,7 +31,7 @@ We'll run the `replay` tool with the demo route to get data streaming for testin
tools/replay/replay --demo
# in terminal 2
selfdrive/ui/ui
./selfdrive/ui/ui.py
```
The openpilot UI should launch and show a replay of the demo route.
@@ -43,39 +43,36 @@ If you have your own comma device, you can replace `--demo` with one of your own
Now lets update the speed display color in the UI.
Search for the function responsible for rendering UI text:
Search for the function responsible for rendering the current speed:
```bash
git grep "drawText" selfdrive/ui/qt/onroad/hud.cc
git grep "_draw_current_speed" selfdrive/ui/onroad/hud_renderer.py
```
Youll find the relevant code inside `selfdrive/ui/qt/onroad/hud.cc`, in this function:
You'll find the relevant code inside `selfdrive/ui/onroad/hud_renderer.py`, in this function:
```cpp
void HudRenderer::drawText(QPainter &p, int x, int y, const QString &text, int alpha) {
QRect real_rect = p.fontMetrics().boundingRect(text);
real_rect.moveCenter({x, y - real_rect.height() / 2});
p.setPen(QColor(0xff, 0xff, 0xff, alpha)); // <- this sets the speed text color
p.drawText(real_rect.x(), real_rect.bottom(), text);
}
```python
def _draw_current_speed(self, rect: rl.Rectangle) -> None:
"""Draw the current vehicle speed and unit."""
speed_text = str(round(self.speed))
speed_text_size = measure_text_cached(self._font_bold, speed_text, FONT_SIZES.current_speed)
speed_pos = rl.Vector2(rect.x + rect.width / 2 - speed_text_size.x / 2, 180 - speed_text_size.y / 2)
rl.draw_text_ex(self._font_bold, speed_text, speed_pos, FONT_SIZES.current_speed, 0, COLORS.white) # <- this sets the speed text color
```
Change the `QColor(...)` line to make it **blue** instead of white. A nice soft blue is `#8080FF`, which translates to:
Change `COLORS.white` to make it **blue** instead of white. A nice soft blue is `#8080FF`, which you can change inline:
```diff
- p.setPen(QColor(0xff, 0xff, 0xff, alpha));
+ p.setPen(QColor(0x80, 0x80, 0xFF, alpha));
- rl.draw_text_ex(self._font_bold, speed_text, speed_pos, FONT_SIZES.current_speed, 0, COLORS.white)
+ rl.draw_text_ex(self._font_bold, speed_text, speed_pos, FONT_SIZES.current_speed, 0, rl.Color(0x80, 0x80, 0xFF, 255))
```
This change will tint all speed-related UI text to blue with the same transparency (`alpha`).
---
## 4. Rebuild the UI
## 4. Re-run the UI
After making changes, rebuild Openpilot so your new UI is compiled:
After making changes, re-run the UI to see your new UI:
```bash
scons -j$(nproc) && selfdrive/ui/ui
./selfdrive/ui/ui.py
```
![](https://blog.comma.ai/img/blue_speed_ui.png)
+1 -1
View File
@@ -16,7 +16,7 @@ export VECLIB_MAXIMUM_THREADS=1
export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="15.1"
export AGNOS_VERSION="16"
fi
export STAGING_ROOT="/data/safe_staging"
+1 -1
Submodule panda updated: dee9061b2a...a95e060e85
+54 -79
View File
@@ -1,11 +1,11 @@
[project]
name = "openpilot"
requires-python = ">= 3.11, < 3.13"
requires-python = ">= 3.12.3, < 3.13"
license = {text = "MIT License"}
version = "0.1.0"
description = "an open source driver assistance system"
authors = [
{name ="Vehicle Researcher", email="user@comma.ai"}
{name = "Vehicle Researcher", email="user@comma.ai"}
]
dependencies = [
@@ -14,12 +14,9 @@ dependencies = [
"pyserial", # pigeond + qcomgpsd
"requests", # many one-off uses
"sympy", # rednose + friends
"crcmod", # cars + qcomgpsd
"crcmod-plus", # cars + qcomgpsd
"tqdm", # cars (fw_versions.py) on start + many one-off uses
# hardwared
"smbus2", # configuring amp
# core
"cffi",
"scons",
@@ -36,9 +33,6 @@ dependencies = [
"pyopenssl < 24.3.0",
"pyaudio",
# ubloxd (TODO: just use struct)
"kaitaistruct",
# panda
"libusb1",
"spidev; platform_system == 'Linux'",
@@ -49,7 +43,7 @@ dependencies = [
# logging
"pyzmq",
"sentry-sdk",
"xattr", # used in place of 'os.getxattr' for macos compatibility
"xattr", # used in place of 'os.getxattr' for macOS compatibility
# athena
"PyJWT",
@@ -58,7 +52,6 @@ dependencies = [
# acados deps
"casadi >=3.6.6", # 3.12 fixed in 3.6.6
"future-fstrings",
# joystickd
"inputs",
@@ -72,31 +65,30 @@ dependencies = [
"zstandard",
# ui
"raylib < 5.5.0.3", # TODO: unpin when they fix https://github.com/electronstudio/raylib-python-cffi/issues/186
"raylib > 5.5.0.3",
"qrcode",
"mapbox-earcut",
"jeepney",
]
[project.optional-dependencies]
docs = [
"Jinja2",
"natsort",
"mkdocs",
]
testing = [
"coverage",
"hypothesis ==6.47.*",
"mypy",
"ty",
"pytest",
"pytest-cpp",
"pytest-subtests",
# https://github.com/pytest-dev/pytest-xdist/pull/1229
"pytest-xdist @ git+https://github.com/sshane/pytest-xdist@2b4372bd62699fb412c4fe2f95bf9f01bd2018da",
"pytest-timeout",
"pytest-randomly",
"pytest-asyncio",
"pytest-mock",
"pytest-repeat",
"ruff",
"codespell",
"pre-commit-hooks",
@@ -104,28 +96,17 @@ testing = [
dev = [
"av",
"azure-identity",
"azure-storage-blob",
"dbus-next", # TODO: remove once we moved everything to jeepney
"dictdiffer",
"jeepney",
"matplotlib",
"opencv-python-headless",
"parameterized >=0.8, <0.9",
"pyautogui",
"pygame",
"pyopencl; platform_machine != 'aarch64'", # broken on arm64
"pytools < 2024.1.11; platform_machine != 'aarch64'", # pyopencl use a broken version
"pywinctl",
"pyprof2calltree",
"tabulate",
"types-requests",
"types-tabulate",
]
tools = [
"metadrive-simulator @ https://github.com/commaai/metadrive/releases/download/MetaDrive-minimal-0.4.2.4/metadrive_simulator-0.4.2.4-py3-none-any.whl ; (platform_machine != 'aarch64')",
"dearpygui>=2.1.0",
"dearpygui>=2.1.0; (sys_platform != 'linux' or platform_machine != 'aarch64')", # not vended for linux aarch64
]
[project.urls]
@@ -157,19 +138,9 @@ markers = [
testpaths = [
"common",
"selfdrive",
"system/manager",
"system/updated",
"system/athena",
"system/camerad",
"system/hardware",
"system/loggerd",
"system/tests",
"system/ubloxd",
"system/webrtc",
"tools/lib/tests",
"tools/replay",
"tools/cabana",
"cereal/messaging/tests",
"system",
"tools",
"cereal",
"sunnypilot",
]
@@ -180,43 +151,7 @@ ignore-words-list = "bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,w
builtin = "clear,rare,informal,code,names,en-GB_to_en-US"
skip = "./third_party/*, ./tinygrad/*, ./tinygrad_repo/*, ./msgq/*, ./panda/*, ./opendbc/*, ./opendbc_repo/*, ./rednose/*, ./rednose_repo/*, ./teleoprtc/*, ./teleoprtc_repo/*, *.po, uv.lock, *.onnx, ./cereal/gen/*, */c_generated_code/*, docs/assets/*, tools/plotjuggler/layouts/*, selfdrive/assets/offroad/mici_fcc.html"
[tool.mypy]
python_version = "3.11"
exclude = [
"cereal/",
"msgq/",
"msgq_repo/",
"opendbc/",
"opendbc_repo/",
"panda/",
"rednose/",
"rednose_repo/",
"tinygrad/",
"tinygrad_repo/",
"teleoprtc/",
"teleoprtc_repo/",
"third_party/",
]
# third-party packages
ignore_missing_imports=true
# helpful warnings
warn_redundant_casts=true
warn_unreachable=true
warn_unused_ignores=true
# restrict dynamic typing
warn_return_any=true
# allow implicit optionals for default args
implicit_optional = true
local_partial_types=true
explicit_package_bases=true
disable_error_code = "annotation-unchecked"
# https://beta.ruff.rs/docs/configuration/#using-pyprojecttoml
# https://docs.astral.sh/ruff/configuration/#using-pyprojecttoml
[tool.ruff]
indent-width = 2
lint.select = [
@@ -226,7 +161,7 @@ lint.select = [
"TRY203", "TRY400", "TRY401", # try/excepts
"RUF008", "RUF100",
"TID251",
"PLR1704",
"PLE", "PLR1704",
]
lint.ignore = [
"E741",
@@ -274,3 +209,43 @@ lint.flake8-implicit-str-concat.allow-multiline = false
[tool.ruff.format]
quote-style = "preserve"
[tool.ty.src]
exclude = [
"cereal/",
"msgq/",
"msgq_repo/",
"opendbc/",
"opendbc_repo/",
"panda/",
"rednose/",
"rednose_repo/",
"tinygrad/",
"tinygrad_repo/",
"teleoprtc/",
"teleoprtc_repo/",
"third_party/",
]
[tool.ty.rules]
# Ignore unresolved imports for Cython-compiled modules (.pyx)
unresolved-import = "ignore"
# Ignore unresolved attributes - many from capnp and Cython modules
unresolved-attribute = "ignore"
# Ignore invalid method overrides - signature variance issues
invalid-method-override = "ignore"
# Ignore possibly-missing-attribute - too many false positives
possibly-missing-attribute = "ignore"
# Ignore invalid assignment - often intentional monkey-patching
invalid-assignment = "ignore"
# Ignore no-matching-overload - numpy/ctypes overload matching issues
no-matching-overload = "ignore"
# Ignore invalid-argument-type - many false positives from raylib, ctypes, numpy
invalid-argument-type = "ignore"
# Ignore call-non-callable - false positives from dynamic types
call-non-callable = "ignore"
# Ignore unsupported-operator - false positives from dynamic types
unsupported-operator = "ignore"
# Ignore not-subscriptable - false positives from dynamic types
not-subscriptable = "ignore"
# not-iterable errors are now fixed
+8 -9
View File
@@ -4,18 +4,17 @@
## release checklist
### Go to staging
- [ ] make a GitHub issue to track release
- [ ] make a GitHub issue to track release with this checklist
- [ ] create release master branch
- [ ] update RELEASES.md
- [ ] create a branch from upstream master named `zerotentwo` for release `v0.10.2`
- [ ] revert risky commits (double check with autonomy team)
- [ ] push the new branch
- [ ] push to staging:
- [ ] make sure you are on the newly created release master branch (`zerotentwo`)
- [ ] run `BRANCH=devel-staging release/build_stripped.sh`. Jenkins will then automatically build staging on device, run `test_onroad` and update the staging branch
- [ ] bump version on master: `common/version.h` and `RELEASES.md`
- [ ] build new userdata partition from `release3-staging`
- [ ] post on Discord, tag `@release crew`
Updating staging:
1. either rebase on master or cherry-pick changes
2. run this to update: `BRANCH=devel-staging release/build_devel.sh`
3. build new userdata partition from `release3-staging`
### Go to release
- [ ] before going to release, test the following:
- [ ] update from previous release -> new release
@@ -26,7 +25,7 @@ Updating staging:
- [ ] check sentry, MTBF, etc.
- [ ] stress test passes in production
- [ ] publish the blog post
- [ ] `git reset --hard origin/release3-staging`
- [ ] `git reset --hard origin/release-mici-staging`
- [ ] tag the release: `git tag v0.X.X <commit-hash> && git push origin v0.X.X`
- [ ] create GitHub release
- [ ] final test install on `openpilot.comma.ai`
+3 -1
View File
@@ -68,8 +68,10 @@ def generate_metadata(model_path: Path, output_dir: Path, short_name: str):
metadata_file = metadata_file.rename(output_path / f"{base}_{short_name.lower()}_metadata.pkl")
# Build the metadata structure
model_type = "offPolicy" if "off_policy" in base else base.split("_")[-1]
model_metadata = {
"type": base.split("_")[-1] if "dmonitoring" not in base else "dmonitoring",
"type": model_type,
"artifact": {
"file_name": tinygrad_file.name,
"download_uri": {
+212
View File
@@ -0,0 +1,212 @@
#!/usr/bin/env python3
"""Fetch CI results from GitHub Actions and Jenkins."""
import argparse
import json
import subprocess
import time
import urllib.error
import urllib.request
from datetime import datetime
JENKINS_URL = "https://jenkins.comma.life"
DEFAULT_TIMEOUT = 1800 # 30 minutes
POLL_INTERVAL = 30 # seconds
LOG_TAIL_LINES = 10 # lines of log to include for failed jobs
def get_git_info():
branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"], text=True).strip()
commit = subprocess.check_output(["git", "rev-parse", "HEAD"], text=True).strip()
return branch, commit
def get_github_actions_status(commit_sha):
result = subprocess.run(
["gh", "run", "list", "--commit", commit_sha, "--workflow", "tests.yaml", "--json", "databaseId,status,conclusion"],
capture_output=True, text=True, check=True
)
runs = json.loads(result.stdout)
if not runs:
return None, None
run_id = runs[0]["databaseId"]
result = subprocess.run(
["gh", "run", "view", str(run_id), "--json", "jobs"],
capture_output=True, text=True, check=True
)
data = json.loads(result.stdout)
jobs = {job["name"]: {"status": job["status"], "conclusion": job["conclusion"],
"duration": format_duration(job) if job["conclusion"] not in ("skipped", None) and job.get("startedAt") else "",
"id": job["databaseId"]}
for job in data.get("jobs", [])}
return jobs, run_id
def get_github_job_log(run_id, job_id):
result = subprocess.run(
["gh", "run", "view", str(run_id), "--job", str(job_id), "--log-failed"],
capture_output=True, text=True
)
lines = result.stdout.strip().split('\n')
return '\n'.join(lines[-LOG_TAIL_LINES:]) if len(lines) > LOG_TAIL_LINES else result.stdout.strip()
def format_duration(job):
start = datetime.fromisoformat(job["startedAt"].replace("Z", "+00:00"))
end = datetime.fromisoformat(job["completedAt"].replace("Z", "+00:00"))
secs = int((end - start).total_seconds())
return f"{secs // 60}m {secs % 60}s"
def get_jenkins_status(branch, commit_sha):
base_url = f"{JENKINS_URL}/job/openpilot/job/{branch}"
try:
# Get list of recent builds
with urllib.request.urlopen(f"{base_url}/api/json?tree=builds[number,url]", timeout=10) as resp:
builds = json.loads(resp.read().decode()).get("builds", [])
# Find build matching commit
for build in builds[:20]: # check last 20 builds
with urllib.request.urlopen(f"{build['url']}api/json", timeout=10) as resp:
data = json.loads(resp.read().decode())
for action in data.get("actions", []):
if action.get("_class") == "hudson.plugins.git.util.BuildData":
build_sha = action.get("lastBuiltRevision", {}).get("SHA1", "")
if build_sha.startswith(commit_sha) or commit_sha.startswith(build_sha):
# Get stages info
stages = []
try:
with urllib.request.urlopen(f"{build['url']}wfapi/describe", timeout=10) as resp2:
wf_data = json.loads(resp2.read().decode())
stages = [{"name": s["name"], "status": s["status"]} for s in wf_data.get("stages", [])]
except urllib.error.HTTPError:
pass
return {
"number": data["number"],
"in_progress": data.get("inProgress", False),
"result": data.get("result"),
"url": data.get("url", ""),
"stages": stages,
}
return None # no build found for this commit
except urllib.error.HTTPError:
return None # branch doesn't exist on Jenkins
def get_jenkins_log(build_url):
url = f"{build_url}consoleText"
with urllib.request.urlopen(url, timeout=30) as resp:
text = resp.read().decode(errors='replace')
lines = text.strip().split('\n')
return '\n'.join(lines[-LOG_TAIL_LINES:]) if len(lines) > LOG_TAIL_LINES else text.strip()
def is_complete(gh_status, jenkins_status):
gh_done = gh_status is None or all(j["status"] == "completed" for j in gh_status.values())
jenkins_done = jenkins_status is None or not jenkins_status.get("in_progress", True)
return gh_done and jenkins_done
def status_icon(status, conclusion=None):
if status == "completed":
return ":white_check_mark:" if conclusion == "success" else ":x:"
return ":hourglass:" if status == "in_progress" else ":grey_question:"
def format_markdown(gh_status, gh_run_id, jenkins_status, commit_sha, branch):
lines = ["# CI Results", "",
f"**Branch**: {branch}",
f"**Commit**: {commit_sha[:7]}",
f"**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", ""]
lines.extend(["## GitHub Actions", "", "| Job | Status | Duration |", "|-----|--------|----------|"])
failed_gh_jobs = []
if gh_status:
for job_name, job in gh_status.items():
icon = status_icon(job["status"], job.get("conclusion"))
conclusion = job.get("conclusion") or job["status"]
lines.append(f"| {job_name} | {icon} {conclusion} | {job.get('duration', '')} |")
if job.get("conclusion") == "failure":
failed_gh_jobs.append((job_name, job.get("id")))
else:
lines.append("| - | No workflow runs found | |")
lines.extend(["", "## Jenkins", "", "| Stage | Status |", "|-------|--------|"])
failed_jenkins_stages = []
if jenkins_status:
stages = jenkins_status.get("stages", [])
if stages:
for stage in stages:
icon = ":white_check_mark:" if stage["status"] == "SUCCESS" else (
":x:" if stage["status"] == "FAILED" else ":hourglass:")
lines.append(f"| {stage['name']} | {icon} {stage['status'].lower()} |")
if stage["status"] == "FAILED":
failed_jenkins_stages.append(stage["name"])
# Show overall build status if still in progress
if jenkins_status["in_progress"]:
lines.append("| (build in progress) | :hourglass: in_progress |")
else:
icon = ":hourglass:" if jenkins_status["in_progress"] else (
":white_check_mark:" if jenkins_status["result"] == "SUCCESS" else ":x:")
status = "in progress" if jenkins_status["in_progress"] else (jenkins_status["result"] or "unknown")
lines.append(f"| #{jenkins_status['number']} | {icon} {status.lower()} |")
if jenkins_status.get("url"):
lines.append(f"\n[View build]({jenkins_status['url']})")
else:
lines.append("| - | No builds found for branch |")
if failed_gh_jobs or failed_jenkins_stages:
lines.extend(["", "## Failure Logs", ""])
for job_name, job_id in failed_gh_jobs:
lines.append(f"### GitHub Actions: {job_name}")
log = get_github_job_log(gh_run_id, job_id)
lines.extend(["", "```", log, "```", ""])
for stage_name in failed_jenkins_stages:
lines.append(f"### Jenkins: {stage_name}")
log = get_jenkins_log(jenkins_status["url"])
lines.extend(["", "```", log, "```", ""])
return "\n".join(lines) + "\n"
def main():
parser = argparse.ArgumentParser(description="Fetch CI results from GitHub Actions and Jenkins")
parser.add_argument("--wait", action="store_true", help="Wait for CI to complete")
parser.add_argument("--timeout", type=int, default=DEFAULT_TIMEOUT, help="Timeout in seconds (default: 1800)")
parser.add_argument("-o", "--output", default="ci_results.md", help="Output file (default: ci_results.md)")
parser.add_argument("--branch", help="Branch to check (default: current branch)")
parser.add_argument("--commit", help="Commit SHA to check (default: HEAD)")
args = parser.parse_args()
branch, commit = get_git_info()
branch = args.branch or branch
commit = args.commit or commit
print(f"Fetching CI results for {branch} @ {commit[:7]}")
start_time = time.monotonic()
while True:
gh_status, gh_run_id = get_github_actions_status(commit)
jenkins_status = get_jenkins_status(branch, commit) if branch != "HEAD" else None
if not args.wait or is_complete(gh_status, jenkins_status):
break
elapsed = time.monotonic() - start_time
if elapsed >= args.timeout:
print(f"Timeout after {int(elapsed)}s")
break
print(f"CI still running, waiting {POLL_INTERVAL}s... ({int(elapsed)}s elapsed)")
time.sleep(POLL_INTERVAL)
content = format_markdown(gh_status, gh_run_id, jenkins_status, commit, branch)
with open(args.output, "w") as f:
f.write(content)
print(f"Results written to {args.output}")
if __name__ == "__main__":
main()
+6 -6
View File
@@ -55,7 +55,7 @@ function run_tests() {
run "check_nomerge_comments" $DIR/check_nomerge_comments.sh $ALL_FILES
if [[ -z "$FAST" ]]; then
run "mypy" mypy $PYTHON_FILES
run "ty" ty check
run "codespell" codespell $ALL_FILES --ignore-words=$ROOT/.codespellignore
fi
@@ -69,7 +69,7 @@ function help() {
echo ""
echo -e "${BOLD}${UNDERLINE}Tests:${NC}"
echo -e " ${BOLD}ruff${NC}"
echo -e " ${BOLD}mypy${NC}"
echo -e " ${BOLD}ty${NC}"
echo -e " ${BOLD}codespell${NC}"
echo -e " ${BOLD}check_added_large_files${NC}"
echo -e " ${BOLD}check_shebang_scripts_are_executable${NC}"
@@ -81,11 +81,11 @@ function help() {
echo " Specify tests to skip separated by spaces"
echo ""
echo -e "${BOLD}${UNDERLINE}Examples:${NC}"
echo " op lint mypy ruff"
echo " Only run the mypy and ruff tests"
echo " op lint ty ruff"
echo " Only run the ty and ruff tests"
echo ""
echo " op lint --skip mypy ruff"
echo " Skip the mypy and ruff tests"
echo " op lint --skip ty ruff"
echo " Skip the ty and ruff tests"
echo ""
echo " op lint"
echo " Run all the tests"
+26
View File
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
set -e
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
cd $DIR/../../tinygrad_repo
GREEN='\033[0;32m'
NC='\033[0m'
#export DEBUG=2
export PYTHONPATH=.
export AM_RESET=1
export AMD=1
export AMD_IFACE=USB
export AMD_LLVM=1
python3 -m unittest -q --buffer test.test_tiny.TestTiny.test_plus \
> /tmp/test_tiny.log 2>&1 || (cat /tmp/test_tiny.log; exit 1)
printf "${GREEN}Booted in ${SECONDS}s${NC}\n"
printf "${GREEN}=============${NC}\n"
printf "\n\n"
printf "${GREEN}Transfer speeds:${NC}\n"
printf "${GREEN}================${NC}\n"
python3 test/external/external_test_usb_asm24.py TestDevCopySpeeds
+1 -1
View File
@@ -11,7 +11,7 @@ LANGUAGES_FILE = TRANSLATIONS_DIR / "languages.json"
GLYPH_PADDING = 6
EXTRA_CHARS = "–‑✓×°§•X⚙✕◀▶✔⌫⇧␣○●↳çêüñ–‑✓×°§•€£¥"
UNIFONT_LANGUAGES = {"ar", "th", "zh-CHT", "zh-CHS", "ko", "ja"}
UNIFONT_LANGUAGES = {"th", "zh-CHT", "zh-CHS", "ko", "ja"}
def _languages():
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:263598da73c577c01cebd31ae78f45969ef8b335be1a5f55d54a696bb2982c0a
size 2062
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9df44871e9f5fa910622b0b92205b92a54d137dbdc3827b92e8622d85ff2e08e
size 5189
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:013b368b38b17d9b2ef6aaf0f498f672deed95888084b7287f42bdfba617cbb6
size 10142
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8fd563eec78d5ce4a8204c2f596789e1090cb3e26a35b4ffeacee4ab61968538
size 8303
@@ -1,3 +0,0 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0be8d5eddcd9f87acbf1daccf446be6218522120f64aee1ee0a3c0b31560f076
size 15761
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:613af9ed79bb26c60fbd19c094214f0881736c0e293f6d000b530cde0478a273
size 2470
oid sha256:89ac033d879beeb0a7fa1919838e0ec64b1a625a4aafc14f7b990c607a79b676
size 2220
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:b77579c099c688d1a27f356197fba9c2c8efcf4d391af580b4b29f0e70587919
size 2086
oid sha256:254b7f753b70c964847b686f0f71af751f2f49beea6ede4aeb333fe06062a257
size 2289
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:eb42b8d6259238beb26f286dc28fb2dc8d91b00fec1f7a7655296b5769439a15
size 15690
oid sha256:01841b602632c66ab14a8e52b874a1623f09641dc2ef0620f4e2d00bb4a913f3
size 16243
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:17b6fe530598cbad34bcf31d4f21f929b792aacedef51b3ffef1941c86017811
size 7331
oid sha256:744dbaa68ee74e300cd46439bad79449c860e1c5c027304b0f382bd5383fba77
size 6817
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:05f3626e790622a4ad90e982c4aacb612d0785a752339352a3187addf763e2e9
size 13288
oid sha256:3b11ee84d48972a2499cb29f01594d77a1a39692f6424a315a3f83262bc16087
size 13481
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a877882a8dccb884bd35918f9f9b427a724a59e90a638e54f6fd5d0680ad173c
size 12137
oid sha256:d548405a65ba4d4590c55866612dc6aa0e78d9278fc864ef60fe3e463edf4a68
size 12169
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:ba944b208abed9b8b9752adb8017bd29cd2e98c89fb07ee5d0a595185c7564a5
size 11898
oid sha256:b6fc63326d34fbe72f6daf104d101ce19e547dbfe134427c067c957a7179df74
size 12124
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a23743d21bc8160e013625210654a55634e4ed58e60057b70e08761bac1c3680
size 40406
oid sha256:77b20a8c478d982412d556afb3a035b80b4aa9fe7a86aea761af4a42147d9435
size 45297
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:acbfa3e38f0b9f422f5c1335ce20013852df2892b813db176a51918adc83ad58
size 40979
oid sha256:584cea202afff6dd20d67ae1a9cd6d2b8cc07598bccb91a8d1bac0142567308e
size 45489
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e0d00d743b01c49c2b739127e9916a229caf8c48346d6d168863b080ddcaa409
size 11124
oid sha256:fd91685bf656e828648acf035a4737acb2c4709e8514cf0aa0a10fa470a9bb60
size 11580
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f3f57346a1cf9a66f9fd746f87bcebb23b7a403e9d6e4fd7701b126abcdd47ea
size 18476
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:f27352a18194a1c819e9eaea89cfc11d2964402df0a28efa3ba60ae2d972fe67
size 13108
oid sha256:cb89d9f11cf44992f92142aa5ad84e1ac700a2601aff2abab373e2a822af149e
size 11678
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:25d66e42a28a3367eb40724d28652889089aa762438b475645269e0319c46009
size 1431
oid sha256:e2772c6a9fe9c57099d347ad49f0cb7c906593f1fdf0e6dde96d104baf0200b0
size 1365
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:51af75afbaf30abeaae1c99c7ad3e25cf5d5c90a2d6c799aad353b3302384b0a
size 4829
oid sha256:07310879d093108435c0011846ae1184966db86443bc6e7ca036a6fa6123700b
size 4983
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:88b2ecf3a9834d2b156bb632ec2090d7dc112e8ab61711ba645c03489d1c457f
size 29157
oid sha256:7be447e56d649e0362ef650494b484e140a01ead31799ce43b266f5781c918d2
size 36473
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:28c95c8970648d40b35b94724936a9ab7a6f4cbca367a40f01b86f9abedc70e5
size 1587
oid sha256:56de402482b5987ed9a0ff3f793a1c89f857304b34fbb8a3deb5b5d4a332be1c
size 3688
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d2a2cb4db429467783d7f721ffbed7838551e4aabf32771e73759c87b4a67bca
size 28880
oid sha256:2aa6d04ba038f15a92868de6e6c7b04f624b4fe89d03bc3e9c4cd44cb729b24e
size 38317
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:0e845a211cf5d03f781efdd6eec4f8106e8dd85799ea59b51834a9099b479141
size 30348
oid sha256:f9f7d0554c0c79ab605c1119ffdef0a4f55196e53b75a65b6ac5218911e24a02
size 45701
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:009005539f14acc29a4f5510b4e9531d2ba3667133644f6e0069c12b08ba0fd9
size 35370
oid sha256:7fae4872ab3c24d5e4c2be6150127a844f89bbdcadfccdff2dfed180e125d577
size 45699
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:38a52171bdc6feb3ddfd2d9f9e59db3dabd09fa0aafbc9f81137c59bd03b7c26
size 2321
oid sha256:14b457d2dc19d8658f525cc6989c9cfcf0edaf695b18767514242acbdbe2a6dd
size 2198
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:10f469a6f5d25d9e2b0b1aae51b4fbd06d2c7b8417613bb321c2a30bb7298dab
size 1392
oid sha256:7ad4ee47ec6470f788a026f95ed86bf344f64f9cf3186c9c78927233d2694a1d
size 1388
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:c655994336b7da4ca986c6f27494bcab66e77f016ec9db8df271de53ed93e517
size 1328
oid sha256:b26133bee089627202d5e89a4e939ad23aaceb5d8e26d7381b1aea3ef892f2ee
size 2620
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a1f058c5640bd763d2f6927432a1daff1587770ea0d06f2e351a28462e9d8335
size 1743
oid sha256:ebb4f7ad9fd2f9fb3c69a38fbc00cbe690809b0ff202ffd4768ae5b699acc035
size 1759
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:77a1281979f0b50f0e109ead56a88a33b81ef5901dd1a4537eb3fa048e0d90de
size 1345
oid sha256:5f47e636025e044977f278a35546e0fc971f48fd53c2eeafd3508e95c35f378f
size 3117
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2649d36259700d32a0edef878647e76492b1bec2fe34ac8ea806d4e7e4c57855
size 2668
oid sha256:66858a5d3302333485fa391f7a9bb3a9b1ab4ae881e7fb47b04c3a4507011c94
size 2613
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4b982ac1b78b45487490d1dbbffed1f68735f6a35def502e882f706c30683aff
size 3664
oid sha256:f646263b26de46f79cac836ef6865b0f25ddc91e386b99311723b68bd06693c9
size 3304

Some files were not shown because too many files have changed in this diff Show More