Compare commits

...

140 Commits

Author SHA1 Message Date
royjr 77d09a7a16 close 2026-07-25 05:12:48 -04:00
royjr f57f1bd19d lag 2026-07-25 05:12:48 -04:00
royjr 2f1d422990 stats 2026-07-25 05:12:48 -04:00
royjr 28fa87d547 pepper 2026-07-25 05:12:48 -04:00
royjr 2430eed759 salt 2026-07-25 05:12:48 -04:00
royjr b8fa2c7535 almost 2026-07-25 05:12:47 -04:00
royjr a39aee2c24 again 2026-07-25 05:12:47 -04:00
royjr cff8b7c1f0 things 2026-07-25 05:12:47 -04:00
royjr c6991ead50 the 2026-07-25 05:12:47 -04:00
royjr 3e950b95ca all 2026-07-25 05:12:47 -04:00
royjr a5fd13ec4d break 2026-07-25 05:12:47 -04:00
royjr 6e99dc3482 icon 2026-07-25 05:12:47 -04:00
royjr 791d63cd81 Update host.py 2026-07-25 03:03:28 -04:00
royjr f166bfcdc5 Update process_config.py 2026-07-25 02:53:13 -04:00
royjr 418c8154be wgpu 2026-07-25 02:41:08 -04:00
Jason Wen 7801bdf0cc Reapply "mapd: ignore in plannerd health check (#1880)"
This reverts commit 9163d1cb74.
2026-07-25 01:36:05 -04:00
Jason Wen 0265ae5f76 Revert "plannerd: check all services for validity (#38341)"
This reverts commit a9ffebe96e.
2026-07-25 01:27:25 -04:00
Jason Wen 9163d1cb74 Revert "mapd: ignore in plannerd health check (#1880)"
This reverts commit 2c334ede44.
2026-07-25 01:27:11 -04:00
Jason Wen a0cc313fdc version: bump to 2026.003.000 2026-07-24 11:36:33 -04:00
Jason Wen 93bb596a2e Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1883) 2026-07-24 11:18:35 -04:00
Jason Wen 41b14fa595 Merge commaai/openpilot fdd1df79 into sync-20260721 2026-07-24 11:07:06 -04:00
Adeeb Shihadeh fdd1df79fb longitudinal: remove per-car stopping tunes (#38394)
* remove per-car longitudinal stopping tunes

* bump opendbc

* lil more

* lil more

* lil more

* lil more

* revert modeld for now
2026-07-20 19:52:23 -07:00
Adeeb Shihadeh 031b1ad0a3 longcontrol: remove starting state (#38340) 2026-07-20 16:30:42 -07:00
Daniel Koepping b1f2e638de fix branch cleanup burning GH API requests (#38392)
* ci: stop branch cleanup from burning API rate limit

* simpler
2026-07-20 16:00:20 -07:00
Daniel Koepping c20263d985 speedup chunk reading (#38389)
read chunk directly into caller buffer
2026-07-20 14:46:33 -07:00
Daniel Koepping 5472e69e35 New sounds (#38154)
* new sounds

* soundd: fix sound cutoff

* update sounds

* add max warning_immediate variant

* mici: play sounds button in developer settings

* rename sounds

* add complete sound

* update sounds

* raise soundfloor by 5%

* update sounds

* play unused sounds

* update sounds

* bump opendbc

* Revert "play unused sounds"

This reverts commit 47e538da2200e700804714576baa5f8c0f28cdb3.

* Revert "mici: play sounds button in developer settings"

This reverts commit 149141bb8a21bec7a04dc8f231d0b6b9120cc7c2.

* remove unused sounds

* raise soundfloor by 5%

* opendbc

* add space
2026-07-20 14:31:55 -07:00
Jason Wen 2c334ede44 mapd: ignore in plannerd health check (#1880)
* mapd: ignore in plannerd health check

* more
2026-07-20 15:05:19 -04:00
Daniel Koepping 78909dac73 soundd: add complete sound (#38390) 2026-07-20 10:50:18 -07:00
Daniel Koepping 24a9b6dae5 profile usb gpu link stability (#38368)
* profile usb gpu link before using

* ci
2026-07-20 10:36:09 -07:00
Jason Wen bf1b93f757 Revert "agnos: split launch for c3 and c3x to support custom agnos" (#1879)
Revert "agnos: split launch for c3 and c3x to support custom agnos (#1186)"

This reverts commit 54174d1e
2026-07-20 09:25:49 -04:00
Jason Wen bae7e49626 Sync: commaai/openpilot:mastersunnypilot/sunnypilot:master (#1876) 2026-07-19 23:51:06 -04:00
royjr 560cde61ae sync: fix upstream conflicts
Co-authored-by: royjr <royjr96@gmail.com>
2026-07-19 23:18:43 -04:00
Adeeb Shihadeh d9596fa998 gc old athena and uploader migration code 2026-07-19 14:55:42 -07:00
Adeeb Shihadeh e124d6df9b more dead code gc 2026-07-19 14:52:04 -07:00
Adeeb Shihadeh 3dbf02f803 cereal: gc dead ZMQ branches in tests 2026-07-19 14:45:26 -07:00
Adeeb Shihadeh fef29ad225 start porting tests to unittest style (#38384) 2026-07-19 14:33:26 -07:00
Adeeb Shihadeh 157c7080ce bump opendbc (#38370) 2026-07-19 12:21:04 -07:00
Adeeb Shihadeh caa9e770cc manager: remove preimport stage (#38381) 2026-07-19 12:20:25 -07:00
Adeeb Shihadeh 24893ebadb rm pre-commit-hooks (#38382)
* rm pre-commit-hooks

* rm test for the tests

* lil more
2026-07-19 12:10:48 -07:00
Adeeb Shihadeh 39e12c8bb1 rm cffi, it's a raylib transitive dep 2026-07-19 11:14:40 -07:00
Adeeb Shihadeh f0d93eb32d more ty, part 2 (#38379) 2026-07-19 11:02:00 -07:00
Adeeb Shihadeh 19ecc37de8 more ty (#38378)
* enable no matching overload

* enable call non callable

* enable unsupported-operator

* enable not subscriptable

* refactor pass
2026-07-19 09:45:46 -07:00
Adeeb Shihadeh ecac2d386b these go in tools 2026-07-19 09:02:02 -07:00
Adeeb Shihadeh e475d10adc more ruff (#38377)
* lil more ruff

* no exclusions!

* rm nb exception

* and generated

* not used

* c408

* random

* all

* unittest is fine
2026-07-19 08:51:16 -07:00
Adeeb Shihadeh 7d74c3c99b rm setuptools (#38376)
* rm setuptools

* lock
2026-07-19 08:25:31 -07:00
Adeeb Shihadeh cefcf10ec3 rm jinja2 2026-07-19 08:15:01 -07:00
Adeeb Shihadeh 1c07e00759 rm xattr (#38373)
* rm xattr

* doesn't add new coverage
2026-07-18 13:55:47 -07:00
Adeeb Shihadeh f0841b827a remove av (#38366) 2026-07-18 09:04:41 -07:00
Adeeb Shihadeh 3f49e2d33c jp: add thumbnail source (#38363) 2026-07-18 09:02:08 -07:00
Adeeb Shihadeh 3f93b00120 webrtc: remove av (#38369) 2026-07-18 08:52:02 -07:00
stef c21b0821da fix(ui): label alignment and text with icon (#38365)
fix align bottom and text positioning with icon
2026-07-17 16:23:44 -07:00
Adeeb Shihadeh b9f25f8a43 webrtcd: move to libdatachannel (#38228)
* try libdatachannel

* fix uv lock

* fix uv lock

* remove datachannel abstraction and just use libdatachannel

* clean

* fix livestream bitrate controller

* fix sample

* fix import breaking ci

* clean up and add catches

* bump tele

* move to teleop master

* fix linter

* .

* remove libdatachannel explicit reference from pyproject.toml

* add PyJWT crypto and catch in registration

* spelling

* add crypto back to lock

---------

Co-authored-by: stefpi <19478336+stefpi@users.noreply.github.com>
2026-07-17 15:28:39 -07:00
ZwX1616 c8786d930d DM: reasonable lockout ramp up (#38358) 2026-07-17 15:27:20 -07:00
Adeeb Shihadeh 3a55f31dc5 agnos 18.5 (#38302) 2026-07-17 15:24:34 -07:00
Adeeb Shihadeh a04c045cd7 cabana: de-Qt, part 3 (#38360) 2026-07-17 09:31:16 -07:00
rkdune 9aa5c3d2c6 expose submodule dependencies as an extra 2026-07-16 18:16:08 -07:00
Adeeb Shihadeh 5d23a78c77 cabana: de-Qt, part 2 (#38359) 2026-07-16 14:35:45 -07:00
Adeeb Shihadeh 06a73f538e cabana: de-Qt, part 1 (#38357)
* cabana: de-Qt, part 1

* lil more
2026-07-16 13:45:57 -07:00
Shane Smiskol 60716edc37 Fix thumbnail creation (#38354)
it's not a stream
2026-07-15 22:51:41 -07:00
Jason Wen 14318d2f09 Merge commit '91b067cca0913d0cc9f8b5dab68e3302e278efdc' into sync-20260716
# Conflicts:
#	.github/labeler.yaml
#	.github/workflows/auto_pr_review.yaml
#	.github/workflows/docs.yaml
#	.github/workflows/release.yaml
#	.github/workflows/repo-maintenance.yaml
#	.github/workflows/tests.yaml
#	.github/workflows/ui_preview.yaml
#	README.md
#	SConstruct
#	conftest.py
#	docs/CARS.md
#	msgq_repo
#	opendbc_repo
#	openpilot/cereal/messaging/tests/validate_sp_cereal_upstream.py
#	openpilot/common/api.py
#	openpilot/common/hardware/hw.py
#	openpilot/common/version.py
#	openpilot/selfdrive/assets/fonts/Audiowide-Regular.ttf
#	openpilot/selfdrive/assets/sounds/prompt_single_high.wav
#	openpilot/selfdrive/assets/sounds/prompt_single_low.wav
#	openpilot/selfdrive/car/card.py
#	openpilot/selfdrive/car/helpers.py
#	openpilot/selfdrive/car/tests/test_car_interfaces.py
#	openpilot/selfdrive/car/tests/test_cruise_speed.py
#	openpilot/selfdrive/controls/lib/desire_helper.py
#	openpilot/selfdrive/controls/lib/longcontrol.py
#	openpilot/selfdrive/controls/plannerd.py
#	openpilot/selfdrive/controls/radard.py
#	openpilot/selfdrive/controls/tests/test_longcontrol.py
#	openpilot/selfdrive/modeld/compile_warp.py
#	openpilot/selfdrive/modeld/modeld.py
#	openpilot/selfdrive/monitoring/policy.py
#	openpilot/selfdrive/monitoring/test_monitoring.py
#	openpilot/selfdrive/selfdrived/events.py
#	openpilot/selfdrive/selfdrived/selfdrived.py
#	openpilot/selfdrive/ui/layouts/onboarding.py
#	openpilot/selfdrive/ui/mici/layouts/onboarding.py
#	openpilot/selfdrive/ui/soundd.py
#	openpilot/selfdrive/ui/tests/diff/replay.py
#	openpilot/selfdrive/ui/translations/app.pot
#	openpilot/system/athena/athenad.py
#	openpilot/system/athena/manage_athenad.py
#	openpilot/system/hardware/hardwared.py
#	openpilot/system/loggerd/config.py
#	openpilot/system/manager/github_runner.sh
#	openpilot/system/manager/manager.py
#	openpilot/system/updated/updated.py
#	panda
#	pyproject.toml
#	scripts/lint/lint.sh
#	system/manager/process_config.py
#	system/statsd.py
#	tinygrad_repo
#	tools/release/build_release.sh
#	tools/release/build_stripped.sh
#	uv.lock
2026-07-16 00:58:32 -04:00
Adeeb Shihadeh 61608db786 jp: fix linking on macOS (#38353)
* jp: fix linking on macOS

* mv to root
2026-07-15 21:39:47 -07:00
Adeeb Shihadeh 91b067cca0 jenkins speedups (#38328)
* power draw first

* speedup encoder

* speed up hardware test suites

* refresh IRQ actions after hardware setup

* skip unused big model in device checkout

* move LFS pruning off device checkout path

* wtf is that for?

* reverts

* locality

* rm that
2026-07-15 18:43:48 -07:00
Adeeb Shihadeh 41886a90da rm redundant params tests 2026-07-15 18:40:08 -07:00
Daniel Koepping 680dd7cf3b bump opendbc (#38352) 2026-07-15 16:52:25 -07:00
Adeeb Shihadeh db99c8e5a6 op: add -u to scons command line (#38348) 2026-07-15 15:39:56 -07:00
Adeeb Shihadeh 2b1fd89064 annotate radar fields (#38347) 2026-07-15 12:01:46 -07:00
Adeeb Shihadeh ec72ee096d cleanup unused radar fields (#38346)
* cleanup unused radar fields

* bump opendbc

* this is nice for debugging

* bring that back too

* bring these back

* more revert
2026-07-15 11:52:31 -07:00
Harald Schäfer eee13472ce longitudinal: add e2e flag to tuning report (#38345) 2026-07-15 10:31:03 -07:00
Shane Smiskol d275c65f75 fix ui.py 2026-07-14 23:53:52 -07:00
Adeeb Shihadeh a9ffebe96e plannerd: check all services for validity (#38341)
* longitudinal planner: carControl must be valid

* plannerd: check all services for validity
2026-07-14 20:40:15 -07:00
Adeeb Shihadeh 45661ee8c0 tmp disable ui_report 2026-07-14 19:24:16 -07:00
Kacper Rączy c16039e0bc lagd: lower max lag (#38307)
* Max lag 0.6

* Fix tests

* 650ms
2026-07-15 02:17:30 +00:00
Adeeb Shihadeh d1e143ac98 longcontrol: simplify state machine (#38337) 2026-07-14 19:01:22 -07:00
Adeeb Shihadeh 45b53cf66a Rename LeadData.status to LeadData.present (#38339)
* rename LeadData.status to LeadData.present

* rename LeadData.status to LeadData.present

* resolve longitudinal MPC merge conflict
2026-07-14 18:54:07 -07:00
Daniel Koepping cf8371c2c5 add usb link err counter (#38338)
* add usb link err counter

* ci
2026-07-14 17:44:46 -07:00
Adeeb Shihadeh f42dbbb01c longitudinal planner: remove unused model trajectory parsing (#38336) 2026-07-14 16:01:45 -07:00
Adeeb Shihadeh 4fd4ddb438 long_mpc: remove unused solver state and timings (#38335) 2026-07-14 15:55:04 -07:00
Adeeb Shihadeh 503531ab38 replace psutil with simple /proc helper (#38326)
* replace psutil with simple /proc helper

* mv to common
2026-07-11 13:51:22 -07:00
Adeeb Shihadeh a52da0d3df bump msgq, no runtime deps 2026-07-11 13:08:39 -07:00
Adeeb Shihadeh a26254304f Move eigen dependency into rednose (#38321)
* Move eigen dependency into rednose

* Declare complete rednose package dependencies

* Update rednose submodule

* Update rednose submodule

* Update rednose submodule

* Fix rednose dependency integration

* bump rednose
2026-07-11 12:59:49 -07:00
stef c91731b13a athena: remove take snapshot (#38319)
remove snapshot
2026-07-09 19:15:23 -07:00
Adeeb Shihadeh 60924556f6 athena: minimal json-rpc implementation (#38318)
* athena: minimal json-rpc implementation

* lil more
2026-07-09 16:55:49 -07:00
Adeeb Shihadeh ee11c24cf4 ci: test op setup with empty submodules (#38316)
* ci: test op setup with empty submodules

* ci: init submodules via op setup instead of checkout

* ci: keep submodules for build release

* ci: drop explicit submodules: false

* ci: remove checkout comment
2026-07-09 12:26:56 -07:00
Adeeb Shihadeh 6392096de5 op setup: init submodules before uv sync (#38314) 2026-07-09 09:31:34 -07:00
Adeeb Shihadeh 39117a5879 remove submodule symlinks (#38312) 2026-07-08 21:30:17 -07:00
Adeeb Shihadeh 1478d0c476 Fix diff report artifact download (#38313) 2026-07-08 21:25:43 -07:00
Adeeb Shihadeh f283f6703c Revert "try removing submodule symlinks (#38310)"
This reverts commit b827c0f55e.
2026-07-08 21:12:12 -07:00
Adeeb Shihadeh b827c0f55e try removing submodule symlinks (#38310) 2026-07-08 21:11:39 -07:00
Adeeb Shihadeh bf5540c364 rm pyserial (#38311)
* rm pyserial

* lil more

* lil more
2026-07-08 21:06:53 -07:00
Adeeb Shihadeh 3b3f5967ec rm crcmod-plus (#38309)
* rm crcmod-plus

* cleanup
2026-07-08 20:43:12 -07:00
Adeeb Shihadeh 1e49eac4d1 rm libyuv (#38306)
* rm libyuv

* cleanup
2026-07-08 20:27:27 -07:00
Adeeb Shihadeh 9877f6ac0e ffmpeg: use shared libraries (#38308) 2026-07-08 20:20:24 -07:00
Adeeb Shihadeh 1ab1ed7453 Use PyPI comma-deps packages (#38295) 2026-07-08 19:35:39 -07:00
Adeeb Shihadeh cb82722dd5 remove libjpeg (#38305)
* remove libjpeg

* lil smaller

* happy linter
2026-07-08 12:21:22 -07:00
Adeeb Shihadeh 960c988355 Replace xvfb with headless raylib backend (#38298) 2026-07-08 11:53:47 -07:00
Shane Smiskol 05cf8023a9 fix cabana 2026-07-07 16:14:26 -07:00
Shane Smiskol 1b6e127e68 fix juggle.py 2026-07-07 15:40:56 -07:00
Adeeb Shihadeh c02cf706a6 fix cabana launch script 2026-07-07 14:09:32 -07:00
Adeeb Shihadeh 0d93f0e820 declare submodules as dependencies in pyproject (#38300)
* declare submodules as dependencies in pyproject

* spidev

* lock
2026-07-07 10:36:49 -07:00
stef 6de5d2c23a revert checkout@v7 to fix nightly release (#38294)
* revert back to checkout@v4

* add comment
2026-07-05 20:04:06 -07:00
Adeeb Shihadeh 92f3d24c8a Remove lateral MPC library (#38281) 2026-07-03 17:17:51 -07:00
Adeeb Shihadeh d606014ce2 ci: delete closed PR branches automatically (#38280) 2026-07-03 09:45:08 -07:00
commaci-public 2aa934e7c2 [bot] Update Python packages (#38263)
Update Python packages

Co-authored-by: Vehicle Researcher <user@comma.ai>
2026-07-02 19:04:06 -07:00
Adeeb Shihadeh 70a6efb8fc ci: update GitHub Actions to latest versions (#38278)
* ci: update GitHub Actions to latest versions

Bump all workflow actions to their latest releases, including major
updates for checkout (v7), upload-artifact (v7), github-script (v9),
action-download-artifact (v21), and thollander comment action (v3).

* ci: pin third-party actions to commit SHAs

Keep official GitHub actions on version tags, but pin community
actions to immutable commit hashes for supply-chain safety.
2026-07-02 19:00:35 -07:00
Adeeb Shihadeh 07ec389f4c bump ty (#38277)
* bump ty

* cleanup
2026-07-02 18:48:53 -07:00
Adeeb Shihadeh 9d03e737dd test_onroad: fix service timing threshold 2026-07-02 14:48:32 -07:00
YassineYousfi 4532320fb3 desire: enter preLaneChange if blinker before engaged (#38276) 2026-07-01 18:52:11 -07:00
YassineYousfi 4c5bef5840 rm modeld/models README 2026-07-01 18:50:52 -07:00
Jimmy 8e0ba7a91e modeld: use correct intrinsics for extra transform when wide camera disabled (#38239)
use correct intrinsics for extra transform when wide camera disabled
2026-07-01 17:17:25 -07:00
Armand du Parc Locmaria fa0c6876d3 lebowski model (#38268)
* Reapply "usbgpu: never materialize model weights in RAM" (#38271)

This reverts commit 8196b743af.

* release oob buffers as we load them

* don't leak fds

* lint

* bigger big

* don't roundtrip the features to qcom

* Revert "don't roundtrip the features to qcom"

This reverts commit 0d2ca73d7a71bd32c46beda425957339f1dbbcf8.

* tmp bump allowed lag

* faster

* Revert "tmp bump allowed lag"

This reverts commit b407702a0242074eb12abdff14e61789fc05109a.
2026-07-01 01:26:11 -07:00
Armand du Parc Locmaria a2c554805b Reapply "usbgpu: never materialize model weights in RAM" (#38273)
* Reapply "usbgpu: never materialize model weights in RAM" (#38271)

This reverts commit 8196b743af.

* release oob buffers as we load them

* don't leak fds

* lint

* 10s faster loading time for big model
2026-07-01 01:22:48 -07:00
Daniel Koepping e1e9efb965 add USB logging (#38186)
* usb logging

* fix test

* discover by PID

* hardwared, add counters

* edit msg

* add manufacturer

* reorder

* rm portli

* rm this
2026-06-30 16:17:26 -07:00
Armand du Parc Locmaria 8196b743af Revert "usbgpu: never materialize model weights in RAM" (#38271)
Revert "usbgpu: never materialize model weights in RAM (#38265)"

This reverts commit 724971afc3.
2026-06-30 13:13:23 -07:00
Armand du Parc Locmaria 724971afc3 usbgpu: never materialize model weights in RAM (#38265)
* bigger big

* don't load big model in ram

* patch tg to allow out of band buffers

* dump/load oob

* roundtrip pkl to disk

* streaming chunking

* to_disk

* fixup

* linter

* Revert "bigger big"

This reverts commit 7a8147dd7fab88db963d512ab4008de940714025.
2026-06-30 00:35:12 -07:00
Armand du Parc Locmaria 4fc5e308f3 Reapply "modeld: enqueue in policy" (#38267)
* Reapply "modeld: enqueue in policy" (#38266)

This reverts commit 8a3bbcdd4e.

* correct device for policy inputs
2026-06-30 00:31:54 -07:00
Armand du Parc Locmaria 8a3bbcdd4e Revert "modeld: enqueue in policy" (#38266)
Revert "modeld: enqueue in policy (#38264)"

This reverts commit 8c927d0fc2.
2026-06-30 00:15:50 -07:00
Armand du Parc Locmaria 8c927d0fc2 modeld: enqueue in policy (#38264)
* move enqueue to policy

* typo

* correct shape

* correct shape
2026-06-29 13:08:37 -07:00
Armand du Parc Locmaria 97215b17d7 modeld: remove prepare_only (#38252)
remove prepare_only
2026-06-29 11:53:27 -07:00
Toby Penner 61b6d52b01 Fix broken tools README link (#38260) 2026-06-28 10:40:05 -07:00
ZwX1616 e9e5548edc bump DM NoEntryAlert priority (#38253) 2026-06-26 18:23:01 -07:00
ZwX1616 f9c555a3fe DM: update escalation/lockout specs; softer sounds (#38244) 2026-06-26 14:57:19 -07:00
ZwX1616 069506aa36 sound: use log enum (#38246) 2026-06-26 13:55:30 -07:00
probablyanasian 5629b5a83d bump sensors test limits (#38245)
* bump sensors test limits

* loosen back to 60 c max due to device density

* 10 dps in 3d is 0.3 rad max
2026-06-25 18:06:42 -07:00
Adeeb Shihadeh addca46f68 move some tools back to root (#38235) 2026-06-24 19:21:19 -07:00
Harald Schäfer 7d325d6650 Simplify lane change logic (#38229)
* desire cleanups

* remove the finalize timeout

---------

Co-authored-by: Robbe Derks <robbe.derks@gmail.com>
2026-06-23 11:34:05 -07:00
commaci-public 288aa60bf4 [bot] Update Python packages (#38227)
* Update Python packages

* fix numpy reshape warning

* relock

---------

Co-authored-by: Vehicle Researcher <user@comma.ai>
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-06-22 15:28:11 -07:00
Adeeb Shihadeh cddb6103eb webrtc: replace aiohttp with stdlib http server (#38226)
* webrtc: replace aiohttp with stdlib http server

* lil more

* simplify

* remove aiohttp error response helper

---------

Co-authored-by: stefpi <19478336+stefpi@users.noreply.github.com>
2026-06-22 14:25:19 -07:00
Adeeb Shihadeh 1474d5474d move root include to the end to prevent using stale build products 2026-06-22 09:45:00 -07:00
Adeeb Shihadeh 2e9fa514bb simple pip install test (#38218)
* fails

* lil more

* try that
2026-06-21 19:39:21 -07:00
Adeeb Shihadeh 8a9ca15464 cleanup leftovers from the shuffling (#38224)
* cleanup leftovers

* rm

* one more
2026-06-21 19:17:01 -07:00
Adeeb Shihadeh 5edc0bd89d mv root dirs into nested openpilot (#38219) 2026-06-21 18:49:46 -07:00
Adeeb Shihadeh 20e0f21b58 prefix paths with openpilot (#38223)
* prefix paths with openpilot

* fix setup root detection

* fix split branch codespell skips
2026-06-21 18:28:35 -07:00
Adeeb Shihadeh 37eda06c95 move cereal/ into nested openpilot (#38220) 2026-06-21 17:55:17 -07:00
Adeeb Shihadeh df1663c58d the one true car.capnp (#38221)
* the one true car.capnp

* fix jotpluggler capnp import path

* bump to master
2026-06-21 17:32:19 -07:00
Adeeb Shihadeh bc168bb33a rm opencv-python-headless (#38214)
* rm opencv-python-headless

* and metadrive

* skip sim
2026-06-21 12:49:12 -07:00
Fang Li d79267fa22 modem: fall back when cellular DNS is missing (#38213)
* modem: fall back when cellular DNS is missing

* rm test

* comment

---------

Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
2026-06-21 12:37:56 -07:00
Adeeb Shihadeh cea5273f1f move version to common/ (#38210) 2026-06-21 09:43:53 -07:00
Adeeb Shihadeh d8bd6c784e rename androidLog -> operatingSystemLog (#38209)
not android
2026-06-21 09:11:04 -07:00
Adeeb Shihadeh ad5151b38b single IsOffroad param (#38205) 2026-06-20 16:55:48 -07:00
Adeeb Shihadeh fddb9fb31c remove statsd (#38204) 2026-06-20 16:35:28 -07:00
1522 changed files with 10177 additions and 7897 deletions
+2 -2
View File
@@ -10,5 +10,5 @@
*.otf filter=lfs diff=lfs merge=lfs -text *.otf filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text *.wav filter=lfs diff=lfs merge=lfs -text
selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text openpilot/selfdrive/car/tests/test_models_segs.txt filter=lfs diff=lfs merge=lfs -text
common/hardware/tici/updater filter=lfs diff=lfs merge=lfs -text openpilot/common/hardware/tici/updater filter=lfs diff=lfs merge=lfs -text
+6 -6
View File
@@ -8,24 +8,24 @@ chore:
car: car:
- changed-files: - changed-files:
- any-glob-to-all-files: '{selfdrive/car/**,opendbc_repo}' - any-glob-to-all-files: '{openpilot/selfdrive/car/**,opendbc_repo}'
simulation: simulation:
- changed-files: - changed-files:
- any-glob-to-all-files: 'tools/sim/**' - any-glob-to-all-files: 'openpilot/tools/sim/**'
ui: ui:
- changed-files: - changed-files:
- any-glob-to-all-files: '{selfdrive/assets/**,selfdrive/ui/**,system/ui/**}' - any-glob-to-all-files: '{openpilot/selfdrive/assets/**,openpilot/selfdrive/ui/**,openpilot/system/ui/**}'
tools: tools:
- changed-files: - changed-files:
- any-glob-to-all-files: 'tools/**' - any-glob-to-all-files: 'openpilot/tools/**'
multilanguage: multilanguage:
- changed-files: - changed-files:
- any-glob-to-all-files: 'selfdrive/ui/translations/**' - any-glob-to-all-files: 'openpilot/selfdrive/ui/translations/**'
autonomy: autonomy:
- changed-files: - changed-files:
- any-glob-to-all-files: "{selfdrive/modeld/models/**,selfdrive/test/process_replay/model_replay_ref_commit,sunnypilot/modeld*/models/**}" - any-glob-to-all-files: "{openpilot/selfdrive/modeld/models/**,openpilot/selfdrive/test/process_replay/model_replay_ref_commit,openpilot/sunnypilot/modeld*/models/**}"
+2 -2
View File
@@ -44,8 +44,8 @@ Explain how you tested this bug fix.
**Checklist** **Checklist**
- [ ] added entry to CAR in selfdrive/car/*/values.py and ran `selfdrive/car/docs.py` to generate new docs - [ ] added entry to CAR in openpilot/selfdrive/car/*/values.py and ran `openpilot/selfdrive/car/docs.py` to generate new docs
- [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/selfdrive/car/tests/routes.py) - [ ] test route added to [routes.py](https://github.com/commaai/openpilot/blob/master/openpilot/selfdrive/car/tests/routes.py)
- [ ] route with openpilot: - [ ] route with openpilot:
- [ ] route with stock system: - [ ] route with stock system:
- [ ] car harness used (if comma doesn't sell it, put N/A): - [ ] car harness used (if comma doesn't sell it, put N/A):
+2 -2
View File
@@ -12,7 +12,7 @@ jobs:
issues: write issues: write
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with: with:
submodules: false submodules: false
@@ -24,7 +24,7 @@ jobs:
# Check PR target branch # Check PR target branch
- name: check branch - name: check branch
uses: Vankka/pr-target-branch-action@def32ec9d93514138d6ac0132ee62e120a72aed5 uses: Vankka/pr-target-branch-action@5da68a42bcb7b43d39104295a876a6f3f8d7908b
if: github.repository == 'sunnypilot/sunnypilot' if: github.repository == 'sunnypilot/sunnypilot'
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
-35
View File
@@ -1,35 +0,0 @@
name: badges
on:
schedule:
- cron: '0 * * * *'
workflow_dispatch:
env:
PYTHONPATH: ${{ github.workspace }}
jobs:
badges:
name: create badges
runs-on: ubuntu-latest
if: github.repository == 'sunnypilot/sunnypilot'
permissions:
contents: write
steps:
- uses: actions/checkout@v6
with:
submodules: true
- run: ./tools/op.sh setup
- name: Push badges
run: |
python3 selfdrive/ui/translations/create_badges.py
rm .gitattributes
git checkout --orphan badges
git rm -rf --cached .
git config user.email "badge-researcher@sunnypilot.ai"
git config user.name "Badge Researcher"
git add translation_badge.svg
git commit -m "Add/Update badges"
git push -f origin HEAD
@@ -30,7 +30,7 @@ jobs:
run: | run: |
cd sunnypilot cd sunnypilot
export PYTHONPATH=$(pwd) export PYTHONPATH=$(pwd)
ref=$(python3 sunnypilot/models/tinygrad_ref.py) ref=$(python3 openpilot/sunnypilot/models/tinygrad_ref.py)
echo "tinygrad_ref=$ref" >> $GITHUB_OUTPUT echo "tinygrad_ref=$ref" >> $GITHUB_OUTPUT
echo "tinygrad_ref is $ref" echo "tinygrad_ref is $ref"
+24 -11
View File
@@ -6,7 +6,7 @@ on:
- master - master
pull_request: pull_request:
paths: paths:
- 'cereal/**' - 'openpilot/cereal/**'
workflow_dispatch: workflow_dispatch:
workflow_call: workflow_call:
inputs: inputs:
@@ -30,11 +30,25 @@ jobs:
- name: Checkout sunnypilot cereal - name: Checkout sunnypilot cereal
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
sparse-checkout: cereal sparse-checkout: |
openpilot/cereal
uv.lock
submodules: false
- name: Init sunnypilot opendbc submodule - name: Init sunnypilot opendbc submodule
run: git submodule update --init --depth 1 opendbc_repo run: git submodule update --init --depth 1 opendbc_repo
- name: Locate sunnypilot capnp import paths
id: locate-sp-capnp
run: |
SP_IMPORT_ARGS=""
SP_CAR_CAPNP=$(find opendbc_repo -maxdepth 4 -name car.capnp -path '*/opendbc/car/car.capnp' -printf '%h\n' -quit)
if [ -n "$SP_CAR_CAPNP" ]; then
SP_IMPORT_ARGS="-I $SP_CAR_CAPNP"
echo "Found sunnypilot car.capnp at: $SP_CAR_CAPNP"
fi
echo "import_args=$SP_IMPORT_ARGS" >> "$GITHUB_OUTPUT"
- name: Checkout upstream openpilot - name: Checkout upstream openpilot
uses: actions/checkout@v6 uses: actions/checkout@v6
with: with:
@@ -65,20 +79,19 @@ jobs:
fi fi
echo "import_args=$IMPORT_ARGS" >> "$GITHUB_OUTPUT" echo "import_args=$IMPORT_ARGS" >> "$GITHUB_OUTPUT"
- name: Install uv - name: Install pycapnp
run: pip install uv run: |
PYCAPNP_VER=$(python3 -c "import re; m=re.search(r'name = \"pycapnp\"\nversion = \"([^\"]+)\"', open('uv.lock').read()); print(m.group(1))")
pip install "pycapnp==${PYCAPNP_VER}"
- name: Generate sunnypilot schema - name: Generate sunnypilot schema
run: | run: |
PYCAPNP_VER=$(python3 -c "import re; m=re.search(r'name = \"pycapnp\"\nversion = \"([^\"]+)\"', open('uv.lock').read()); print(m.group(1))") python3 openpilot/cereal/messaging/tests/validate_sp_cereal_upstream.py \
uv run --isolated --with "pycapnp==${PYCAPNP_VER}" \ -g -f /tmp/sp_schema.json --cereal-dir openpilot/cereal \
python3 cereal/messaging/tests/validate_sp_cereal_upstream.py \ ${{ steps.locate-sp-capnp.outputs.import_args }}
-g -f /tmp/sp_schema.json --cereal-dir cereal
- name: Validate against upstream - name: Validate against upstream
run: | run: |
PYCAPNP_VER=$(python3 -c "import re; m=re.search(r'name = \"pycapnp\"\nversion = \"([^\"]+)\"', open('uv.lock').read()); print(m.group(1))") python3 openpilot/cereal/messaging/tests/validate_sp_cereal_upstream.py \
uv run --isolated --with "pycapnp==${PYCAPNP_VER}" \
python3 cereal/messaging/tests/validate_sp_cereal_upstream.py \
-r -f /tmp/sp_schema.json --cereal-dir ${{ steps.locate-capnp.outputs.cereal_dir }} \ -r -f /tmp/sp_schema.json --cereal-dir ${{ steps.locate-capnp.outputs.cereal_dir }} \
${{ steps.locate-capnp.outputs.import_args }} ${{ steps.locate-capnp.outputs.import_args }}
+24 -12
View File
@@ -17,29 +17,41 @@ jobs:
- name: Wait for process replay - name: Wait for process replay
id: wait id: wait
continue-on-error: true continue-on-error: true
uses: lewagon/wait-on-check-action@v1.3.4 uses: lewagon/wait-on-check-action@1d57e2c51a58d812d2765e036a028b6bdb5a6154
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
check-name: process replay check-name: process replay
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
allowed-conclusions: success,failure allowed-conclusions: success,failure
wait-interval: 20 wait-interval: 20
- name: Get tests run ID
if: steps.wait.outcome == 'success'
id: tests-run
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
run_id=$(gh api \
"repos/${{ github.repository }}/actions/workflows/tests.yaml/runs?event=pull_request&head_sha=${{ github.event.pull_request.head.sha }}&per_page=1" \
--jq '.workflow_runs[0].id // empty')
if [ -z "$run_id" ]; then
echo "No tests.yaml run found for ${{ github.event.pull_request.head.sha }}" >&2
exit 1
fi
echo "run-id=$run_id" >> "$GITHUB_OUTPUT"
- name: Download diff - name: Download diff
if: steps.wait.outcome == 'success' if: steps.wait.outcome == 'success'
uses: dawidd6/action-download-artifact@v6 uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
workflow: tests.yaml repository: ${{ github.repository }}
workflow_conclusion: '' run-id: ${{ steps.tests-run.outputs.run-id }}
pr: ${{ github.event.number }}
name: diff_report_${{ github.event.number }} name: diff_report_${{ github.event.number }}
path: . path: .
allow_forks: true
- name: Comment on PR - name: Comment on PR
if: steps.wait.outcome == 'success' if: steps.wait.outcome == 'success'
uses: thollander/actions-comment-pull-request@v2 uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b
with: with:
filePath: diff_report.txt file-path: diff_report.txt
comment_tag: diff_report comment-tag: diff_report
pr_number: ${{ github.event.number }} pr-number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
+3 -3
View File
@@ -22,7 +22,7 @@ jobs:
steps: steps:
- uses: commaai/timeout@v1 - uses: commaai/timeout@v1
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with: with:
submodules: true submodules: true
@@ -34,7 +34,7 @@ jobs:
python scripts/docs.py build python scripts/docs.py build
# Push to docs.comma.ai # Push to docs.comma.ai
- uses: actions/checkout@v6 - uses: actions/checkout@v7
if: github.ref == 'refs/heads/master' && github.repository == 'sunnypilot/sunnypilot' if: github.ref == 'refs/heads/master' && github.repository == 'sunnypilot/sunnypilot'
with: with:
path: openpilot-docs path: openpilot-docs
@@ -45,7 +45,7 @@ jobs:
run: | run: |
set -x set -x
source release/identity.sh source tools/release/identity.sh
cd openpilot-docs cd openpilot-docs
git checkout --orphan tmp git checkout --orphan tmp
+4 -4
View File
@@ -11,7 +11,7 @@ jobs:
contents: write contents: write
steps: steps:
- name: Delete stale Jenkins branches - name: Delete stale Jenkins branches
uses: actions/github-script@v8 uses: actions/github-script@v9
with: with:
script: | script: |
const cutoff = Date.now() - 24 * 60 * 60 * 1000; const cutoff = Date.now() - 24 * 60 * 60 * 1000;
@@ -52,7 +52,7 @@ jobs:
steps: steps:
- name: Check for trigger phrase - name: Check for trigger phrase
id: check_comment id: check_comment
uses: actions/github-script@v8 uses: actions/github-script@v9
with: with:
script: | script: |
const triggerPhrase = "trigger-jenkins"; const triggerPhrase = "trigger-jenkins";
@@ -72,7 +72,7 @@ jobs:
- name: Checkout repository - name: Checkout repository
if: steps.check_comment.outputs.result == 'true' if: steps.check_comment.outputs.result == 'true'
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
ref: refs/pull/${{ github.event.issue.number }}/head ref: refs/pull/${{ github.event.issue.number }}/head
@@ -86,7 +86,7 @@ jobs:
- name: Delete trigger comment - name: Delete trigger comment
if: steps.check_comment.outputs.result == 'true' && always() if: steps.check_comment.outputs.result == 'true' && always()
uses: actions/github-script@v8 uses: actions/github-script@v9
with: with:
script: | script: |
await github.rest.issues.deleteComment({ await github.rest.issues.deleteComment({
+14 -1
View File
@@ -65,8 +65,21 @@ jobs:
echo ' pushurl = ${{ env.LFS_PUSH_URL }}' >> .lfsconfig echo ' pushurl = ${{ env.LFS_PUSH_URL }}' >> .lfsconfig
echo ' locksverify = false' >> .lfsconfig echo ' locksverify = false' >> .lfsconfig
- name: Configure LFS transfer settings
run: |
git config lfs.activitytimeout 300
git config lfs.transfer.maxretries 5
git config lfs.concurrenttransfers 4
- name: Push LFS - name: Push LFS
id: sync-and-commit id: sync-and-commit
run: | run: |
git lfs ls-files -l git lfs ls-files -l
git lfs push --all origin for attempt in 1 2 3; do
echo "Push attempt $attempt..."
git lfs push --all origin && exit 0
echo "Attempt $attempt failed, retrying in 30s..."
sleep 30
done
echo "All push attempts failed"
exit 1
+4 -4
View File
@@ -4,7 +4,7 @@ on:
pull_request: pull_request:
types: [opened, reopened, synchronize] types: [opened, reopened, synchronize]
paths: paths:
- 'selfdrive/modeld/models/*.onnx' - 'openpilot/selfdrive/modeld/models/*.onnx'
workflow_dispatch: workflow_dispatch:
jobs: jobs:
@@ -16,11 +16,11 @@ jobs:
if: github.repository == 'commaai/openpilot' if: github.repository == 'commaai/openpilot'
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
submodules: true submodules: true
- name: Checkout master - name: Checkout master
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
ref: master ref: master
path: base path: base
@@ -36,7 +36,7 @@ jobs:
echo "EOF" >> $GITHUB_OUTPUT echo "EOF" >> $GITHUB_OUTPUT
- name: Post model report comment - name: Post model report comment
uses: marocchino/sticky-pull-request-comment@baa7203ed60924babbe5dcd0ac8eae3b66ec5e16 uses: marocchino/sticky-pull-request-comment@0ea0beb66eb9baf113663a64ec522f60e49231c0
with: with:
header: model-review header: model-review
message: ${{ steps.report.outputs.content }} message: ${{ steps.report.outputs.content }}
+3 -3
View File
@@ -15,17 +15,17 @@ jobs:
steps: steps:
- name: Wait for green check mark - name: Wait for green check mark
if: ${{ github.event_name == 'schedule' }} if: ${{ github.event_name == 'schedule' }}
uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc uses: lewagon/wait-on-check-action@1d57e2c51a58d812d2765e036a028b6bdb5a6154
with: with:
ref: master ref: master
wait-interval: 30 wait-interval: 30
running-workflow-name: 'build __nightly' running-workflow-name: 'build __nightly'
repo-token: ${{ secrets.GITHUB_TOKEN }} repo-token: ${{ secrets.GITHUB_TOKEN }}
check-regexp: ^((?!.*(build prebuilt|create badges).*).)*$ check-regexp: ^((?!.*(build prebuilt|create badges).*).)*$
- uses: actions/checkout@v4 - uses: actions/checkout@v4 # checkout version > v4 breaks nightly release script
with: with:
submodules: true submodules: true
fetch-depth: 0 fetch-depth: 0
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Push __nightly - name: Push __nightly
run: BRANCH=__nightly release/build_stripped.sh run: BRANCH=__nightly tools/release/build_stripped.sh
+56 -4
View File
@@ -3,6 +3,8 @@ name: repo maintenance
on: on:
schedule: schedule:
- cron: "0 14 * * 1" # every Monday at 2am UTC (6am PST) - cron: "0 14 * * 1" # every Monday at 2am UTC (6am PST)
pull_request:
types: [closed]
workflow_dispatch: workflow_dispatch:
env: env:
@@ -12,9 +14,11 @@ jobs:
package_updates: package_updates:
name: package_updates name: package_updates
runs-on: ubuntu-latest runs-on: ubuntu-latest
if: github.repository == 'sunnypilot/sunnypilot' if: >-
github.repository == 'sunnypilot/sunnypilot' &&
(github.event_name == 'schedule' || github.event_name == 'workflow_dispatch')
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with: with:
submodules: true submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
@@ -50,10 +54,10 @@ jobs:
git add . git add .
- name: update car docs - name: update car docs
run: | run: |
python selfdrive/car/docs.py python openpilot/selfdrive/car/docs.py
git add docs/CARS.md git add docs/CARS.md
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1
with: with:
author: github-actions[bot] <github-actions[bot]@users.noreply.github.com> author: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
token: ${{ github.repository == 'commaai/openpilot' && secrets.ACTIONS_CREATE_PR_PAT || secrets.GITHUB_TOKEN }} token: ${{ github.repository == 'commaai/openpilot' && secrets.ACTIONS_CREATE_PR_PAT || secrets.GITHUB_TOKEN }}
@@ -75,3 +79,51 @@ jobs:
${{ steps.pip_tree.outputs.PIP_TREE }} ${{ steps.pip_tree.outputs.PIP_TREE }}
``` ```
labels: bot labels: bot
cleanup_closed_branches:
if: github.repository == 'commaai/openpilot'
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: read
steps:
- uses: actions/github-script@v9
with:
script: |
const { owner, repo } = context.repo;
const upstream = `${owner}/${repo}`;
const closed = context.payload.pull_request;
if (closed) {
if (closed.head.repo?.full_name === upstream) {
await github.rest.git.deleteRef({ owner, repo, ref: `heads/${closed.head.ref}` }).catch(console.log);
}
return;
}
for await (const response of github.paginate.iterator(github.rest.pulls.list, {
owner,
repo,
state: 'closed',
per_page: 100,
})) {
for (const pr of response.data) {
if (pr.head.repo?.full_name !== upstream) continue;
const branch = pr.head.ref;
try {
await github.rest.git.deleteRef({
owner,
repo,
ref: `heads/${branch}`,
});
console.log(`Deleted branch ${branch} (PR #${pr.number})`);
} catch (error) {
if (error.status === 422 || error.status === 403) {
console.log(`Skipping branch ${branch} (PR #${pr.number}): ${error.message}`);
continue;
}
throw error;
}
}
}
+10 -5
View File
@@ -6,7 +6,7 @@ env:
SCONS_CACHE_DIR: ${{ github.workspace }}/release/ci/scons_cache SCONS_CACHE_DIR: ${{ github.workspace }}/release/ci/scons_cache
UPSTREAM_REPO: "commaai/openpilot" UPSTREAM_REPO: "commaai/openpilot"
TINYGRAD_PATH: ${{ github.workspace }}/tinygrad_repo TINYGRAD_PATH: ${{ github.workspace }}/tinygrad_repo
MODELS_DIR: ${{ github.workspace }}/selfdrive/modeld/models MODELS_DIR: ${{ github.workspace }}/openpilot/selfdrive/modeld/models
on: on:
workflow_call: workflow_call:
@@ -92,7 +92,7 @@ jobs:
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
with: with:
name: models-${{ env.REF }}${{ inputs.artifact_suffix }} name: models-${{ env.REF }}${{ inputs.artifact_suffix }}
path: ${{ github.workspace }}/openpilot/selfdrive/modeld/models/*.onnx path: ${{ github.workspace }}/openpilot/openpilot/selfdrive/modeld/models/*.onnx
build_model: build_model:
runs-on: [self-hosted, tici] runs-on: [self-hosted, tici]
@@ -128,7 +128,10 @@ jobs:
# Set up common environment # Set up common environment
source /etc/profile; source /etc/profile;
export UV_PROJECT_ENVIRONMENT=${HOME}/venv export UV_PROJECT_ENVIRONMENT=${HOME}/venv
export UV_PYTHON_PREFERENCE=managed
export UV_PYTHON_INSTALL_DIR=${HOME}/uv/python
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
uv sync
printenv >> $GITHUB_ENV printenv >> $GITHUB_ENV
if [[ "${{ runner.debug }}" == "1" ]]; then if [[ "${{ runner.debug }}" == "1" ]]; then
cat $GITHUB_OUTPUT cat $GITHUB_OUTPUT
@@ -148,6 +151,7 @@ jobs:
if [[ "${{ runner.debug }}" == "1" ]]; then if [[ "${{ runner.debug }}" == "1" ]]; then
printenv printenv
fi fi
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --disable PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --disable
rm -rf ${{ env.MODELS_DIR }}/*.onnx rm -rf ${{ env.MODELS_DIR }}/*.onnx
@@ -155,9 +159,9 @@ jobs:
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:
name: models-${{ env.REF }}${{ inputs.artifact_suffix }} name: models-${{ env.REF }}${{ inputs.artifact_suffix }}
path: ${{ github.workspace }}/selfdrive/modeld/models path: ${{ env.MODELS_DIR }}
- run: | - run: |
rm -f ${{ github.workspace }}/selfdrive/modeld/models/{dmonitoring_model,big_driving_policy,big_driving_vision}.onnx rm -f ${{ env.MODELS_DIR }}/{dmonitoring_model,big_driving_policy,big_driving_vision}.onnx
- name: Build Model - name: Build Model
run: | run: |
@@ -166,7 +170,7 @@ jobs:
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
export PYTHONPATH="${PYTHONPATH}:${{ env.TINYGRAD_PATH }}:${{ github.workspace }}" export PYTHONPATH="${PYTHONPATH}:${{ env.TINYGRAD_PATH }}:${{ github.workspace }}"
COMPILE_MODELD="${{ github.workspace }}/sunnypilot/modeld_v2/compile_modeld.py" COMPILE_MODELD="${{ github.workspace }}/openpilot/sunnypilot/modeld_v2/compile_modeld.py"
MODEL_SIZE=$(python3 -c "from openpilot.common.transformations.model import MEDMODEL_INPUT_SIZE as s; print(f'{s[0]}x{s[1]}')") MODEL_SIZE=$(python3 -c "from openpilot.common.transformations.model import MEDMODEL_INPUT_SIZE as s; print(f'{s[0]}x{s[1]}')")
CAMERA_RES=$(python3 -c "from openpilot.common.transformations.camera import _ar_ox_fisheye as a, _os_fisheye as o; print(f'{a.width}x{a.height} {o.width}x{o.height}')") CAMERA_RES=$(python3 -c "from openpilot.common.transformations.camera import _ar_ox_fisheye as a, _os_fisheye as o; print(f'{a.width}x{a.height} {o.width}x{o.height}')")
TG_FLAGS="DEV=QCOM IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1" TG_FLAGS="DEV=QCOM IMAGE=1 FLOAT16=1 NOLOCALS=1 JIT_BATCH_SIZE=0 OPENPILOT_HACKS=1"
@@ -264,4 +268,5 @@ jobs:
- name: Re-enable powersave - name: Re-enable powersave
if: always() if: always()
run: | run: |
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable
@@ -79,7 +79,7 @@ jobs:
is_stable_branch="$(echo "$CONFIG" | jq -r '.stable_branch // false')"; is_stable_branch="$(echo "$CONFIG" | jq -r '.stable_branch // false')";
echo "is_stable_branch=$is_stable_branch" >> $GITHUB_OUTPUT echo "is_stable_branch=$is_stable_branch" >> $GITHUB_OUTPUT
stable_version=$(cat sunnypilot/common/version.h | grep SUNNYPILOT_VERSION | sed -e 's/[^0-9|.]//g'); stable_version=$(cat openpilot/sunnypilot/common/version.h | grep SUNNYPILOT_VERSION | sed -e 's/[^0-9|.]//g');
echo "version=$([ "$is_stable_branch" = "true" ] && echo "$stable_version" || echo "$BUILD")" >> $GITHUB_OUTPUT echo "version=$([ "$is_stable_branch" = "true" ] && echo "$stable_version" || echo "$BUILD")" >> $GITHUB_OUTPUT
echo "extra_version_identifier=${environment}" >> $GITHUB_OUTPUT echo "extra_version_identifier=${environment}" >> $GITHUB_OUTPUT
fi fi
@@ -152,7 +152,10 @@ jobs:
# Set up common environment # Set up common environment
source /etc/profile; source /etc/profile;
export UV_PROJECT_ENVIRONMENT=${HOME}/venv export UV_PROJECT_ENVIRONMENT=${HOME}/venv
export UV_PYTHON_PREFERENCE=managed
export UV_PYTHON_INSTALL_DIR=${HOME}/uv/python
export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT export VIRTUAL_ENV=$UV_PROJECT_ENVIRONMENT
uv sync
printenv >> $GITHUB_ENV printenv >> $GITHUB_ENV
if [[ "${{ runner.debug }}" == "1" ]]; then if [[ "${{ runner.debug }}" == "1" ]]; then
cat $GITHUB_OUTPUT cat $GITHUB_OUTPUT
@@ -172,20 +175,26 @@ jobs:
if [[ "${{ runner.debug }}" == "1" ]]; then if [[ "${{ runner.debug }}" == "1" ]]; then
printenv printenv
fi fi
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --disable PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --disable
- name: Build Main Project - name: Build Main Project
run: | run: |
export PYTHONPATH="$BUILD_DIR" export PYTHONPATH="$BUILD_DIR"
./release/release_files.py | sort | uniq | rsync -rRl${RUNNER_DEBUG:+v} --files-from=- . $BUILD_DIR/ ./tools/release/release_files.py | sort | uniq | rsync -rRl${RUNNER_DEBUG:+v} --files-from=- . $BUILD_DIR/
cd $BUILD_DIR cd $BUILD_DIR
ln -sfn msgq_repo/msgq msgq
ln -sfn opendbc_repo/opendbc opendbc
ln -sfn rednose_repo/rednose rednose
ln -sfn teleoprtc_repo/teleoprtc teleoprtc
ln -sfn tinygrad_repo/tinygrad tinygrad
sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py sed -i '/from .board.jungle import PandaJungle, PandaJungleDFU/s/^/#/' panda/__init__.py
echo "Building sunnypilot's modeld_v2..." echo "Building sunnypilot's modeld_v2..."
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal sunnypilot/modeld_v2 scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal openpilot/sunnypilot/modeld_v2
echo "Building sunnypilot's locationd..." echo "Building sunnypilot's locationd..."
scons -j2 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal sunnypilot/selfdrive/locationd scons -j2 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal openpilot/sunnypilot/selfdrive/locationd
echo "Building openpilot's locationd..." echo "Building openpilot's locationd..."
scons -j1 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal selfdrive/locationd scons -j1 cache_dir=${{env.SCONS_CACHE_DIR}} --minimal openpilot/selfdrive/locationd
echo "Building rest of sunnypilot" echo "Building rest of sunnypilot"
scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal scons -j$(nproc) cache_dir=${{env.SCONS_CACHE_DIR}} --minimal
touch ${BUILD_DIR}/prebuilt touch ${BUILD_DIR}/prebuilt
@@ -208,17 +217,17 @@ jobs:
--exclude='Jenkinsfile' \ --exclude='Jenkinsfile' \
--exclude='**/release/' \ --exclude='**/release/' \
--exclude='**/.github/' \ --exclude='**/.github/' \
--exclude='**/selfdrive/ui/replay/' \ --exclude='**/openpilot/selfdrive/ui/replay/' \
--exclude='**/__pycache__/' \ --exclude='**/__pycache__/' \
--exclude='${{env.SCONS_CACHE_DIR}}' \ --exclude='${{env.SCONS_CACHE_DIR}}' \
--exclude='**/.git/' \ --exclude='**/.git/' \
--exclude='**/SConstruct' \ --exclude='**/SConstruct' \
--exclude='**/SConscript' \ --exclude='**/SConscript' \
--exclude='**/.venv/' \ --exclude='**/.venv/' \
--exclude='selfdrive/modeld/models/*.onnx*' \ --exclude='openpilot/selfdrive/modeld/models/*.onnx*' \
--exclude='sunnypilot/modeld*/models/*.onnx*' \ --exclude='openpilot/sunnypilot/modeld*/models/*.onnx*' \
--exclude='third_party/*x86*' \ --exclude='openpilot/third_party/*x86*' \
--exclude='third_party/*Darwin*' \ --exclude='openpilot/third_party/*Darwin*' \
--delete-excluded \ --delete-excluded \
--chown=comma:comma \ --chown=comma:comma \
${BUILD_DIR}/ ${OUTPUT_DIR}/ ${BUILD_DIR}/ ${OUTPUT_DIR}/
@@ -237,6 +246,7 @@ jobs:
- name: Re-enable powersave - name: Re-enable powersave
if: always() if: always()
run: | run: |
source ${UV_PROJECT_ENVIRONMENT}/bin/activate
PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable PYTHONPATH=$PYTHONPATH:${{ github.workspace }}/ ${{ github.workspace }}/scripts/manage-powersave.py --enable
@@ -363,7 +373,7 @@ jobs:
owner: context.repo.owner, owner: context.repo.owner,
repo: context.repo.repo, repo: context.repo.repo,
issue_number: prNumber, issue_number: prNumber,
name: process.env.LABEL name: process.env.LABELf
}); });
console.log(`Removed '${process.env.LABEL}' label from PR #${prNumber}`); console.log(`Removed '${process.env.LABEL}' label from PR #${prNumber}`);
+42 -45
View File
@@ -35,27 +35,27 @@ jobs:
STRIPPED_DIR: /tmp/releasepilot STRIPPED_DIR: /tmp/releasepilot
PYTHONPATH: /tmp/releasepilot PYTHONPATH: /tmp/releasepilot
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with: with:
submodules: true submodules: true
- name: Getting LFS files - name: Getting LFS files
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60
with: with:
timeout_minutes: 2 timeout_minutes: 2
max_attempts: 3 max_attempts: 3
command: git lfs pull command: git lfs pull
- name: Build devel - name: Build devel
timeout-minutes: 1 timeout-minutes: 3
run: TARGET_DIR=$STRIPPED_DIR release/build_stripped.sh run: TARGET_DIR=$STRIPPED_DIR tools/release/build_stripped.sh
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Build openpilot and run checks - name: Build openpilot and run checks
timeout-minutes: 30 timeout-minutes: 30
working-directory: ${{ env.STRIPPED_DIR }} working-directory: ${{ env.STRIPPED_DIR }}
run: python3 system/manager/build.py run: python3 openpilot/system/manager/build.py
- name: Run tests - name: Run tests
timeout-minutes: 1 timeout-minutes: 1
working-directory: ${{ env.STRIPPED_DIR }} working-directory: ${{ env.STRIPPED_DIR }}
run: release/check-dirty.sh run: tools/release/check-dirty.sh
- name: Check submodules - name: Check submodules
if: github.repository == 'sunnypilot/sunnypilot' if: github.repository == 'sunnypilot/sunnypilot'
timeout-minutes: 3 timeout-minutes: 3
@@ -75,15 +75,13 @@ jobs:
export CHECK_PR_REFS=true export CHECK_PR_REFS=true
fi fi
fi fi
release/check-submodules.sh tools/release/check-submodules.sh
build_mac: build_mac:
name: build macOS name: build macOS
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' }} 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: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- name: Remove Homebrew from environment - name: Remove Homebrew from environment
run: | run: |
FILTERED=$(echo "$PATH" | tr ':' '\n' | grep -v '/opt/homebrew' | tr '\n' ':') FILTERED=$(echo "$PATH" | tr ':' '\n' | grep -v '/opt/homebrew' | tr '\n' ':')
@@ -101,9 +99,7 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16"]') && fromJSON('["namespace-profile-amd64-8x16"]')
|| fromJSON('["ubuntu-24.04"]') }} || fromJSON('["ubuntu-24.04"]') }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Static analysis - name: Static analysis
timeout-minutes: 1 timeout-minutes: 1
@@ -118,16 +114,18 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16"]') && fromJSON('["namespace-profile-amd64-8x16"]')
|| fromJSON('["ubuntu-24.04"]') }} || fromJSON('["ubuntu-24.04"]') }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Install raylib headless dependencies
if: ${{ !contains(runner.name, 'nsc') }}
run: sudo apt-get install -y --no-install-recommends libgles2 libegl1
- name: Build openpilot - name: Build openpilot
run: scons run: scons
- name: Run unit tests - name: Run unit tests
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 999 }} timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 999 }}
env:
RAYLIB_BACKEND: headless
run: | run: |
source selfdrive/test/setup_xvfb.sh
# Pre-compile Python bytecode so each pytest worker doesn't need to # Pre-compile Python bytecode so each pytest worker doesn't need to
$PYTEST --collect-only -m 'not slow' -qq $PYTEST --collect-only -m 'not slow' -qq
MAX_EXAMPLES=1 $PYTEST -m 'not slow' MAX_EXAMPLES=1 $PYTEST -m 'not slow'
@@ -142,39 +140,37 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16"]') && fromJSON('["namespace-profile-amd64-8x16"]')
|| fromJSON('["ubuntu-24.04"]') }} || fromJSON('["ubuntu-24.04"]') }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Build openpilot - name: Build openpilot
run: scons run: scons
- name: Run replay - name: Run replay
timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 20 }} timeout-minutes: ${{ contains(runner.name, 'nsc') && 2 || 20 }}
continue-on-error: ${{ github.ref == 'refs/heads/master' }} continue-on-error: ${{ github.ref == 'refs/heads/master' }}
run: selfdrive/test/process_replay/test_processes.py -j$(nproc) run: openpilot/selfdrive/test/process_replay/test_processes.py -j$(nproc)
- name: Print diff - name: Print diff
id: print-diff id: print-diff
if: always() if: always()
run: cat selfdrive/test/process_replay/diff.txt run: cat openpilot/selfdrive/test/process_replay/diff.txt
- name: Print diff report - name: Print diff report
if: always() if: always()
run: cat selfdrive/test/process_replay/diff_report.txt run: cat openpilot/selfdrive/test/process_replay/diff_report.txt
- uses: actions/upload-artifact@v6 - uses: actions/upload-artifact@v7
if: always() if: always()
continue-on-error: true continue-on-error: true
with: with:
name: process_replay_diff.txt name: process_replay_diff.txt
path: selfdrive/test/process_replay/diff.txt path: openpilot/selfdrive/test/process_replay/diff.txt
- name: Upload diff report - name: Upload diff report
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
if: always() && github.event_name == 'pull_request' if: always() && github.event_name == 'pull_request'
continue-on-error: true continue-on-error: true
with: with:
name: diff_report_${{ github.event.number }} name: diff_report_${{ github.event.number }}
path: selfdrive/test/process_replay/diff_report.txt path: openpilot/selfdrive/test/process_replay/diff_report.txt
- name: Checkout ci-artifacts - name: Checkout ci-artifacts
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master' if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
uses: actions/checkout@v4 uses: actions/checkout@v7
with: with:
repository: commaai/ci-artifacts repository: commaai/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }} ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
@@ -187,13 +183,13 @@ jobs:
git config user.email "<>" git config user.email "<>"
git fetch origin process-replay || true git fetch origin process-replay || true
git checkout process-replay 2>/dev/null || git checkout --orphan process-replay git checkout process-replay 2>/dev/null || git checkout --orphan process-replay
cp ${{ github.workspace }}/selfdrive/test/process_replay/fakedata/*.zst . cp ${{ github.workspace }}/openpilot/selfdrive/test/process_replay/fakedata/*.zst .
echo "${{ github.sha }}" > ref_commit echo "${{ github.sha }}" > ref_commit
git add . git add .
git commit -m "process-replay refs for ${{ github.repository }}@${{ github.sha }}" || echo "No changes to commit" git commit -m "process-replay refs for ${{ github.repository }}@${{ github.sha }}" || echo "No changes to commit"
- name: Push refs - name: Push refs
if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master' if: github.repository == 'commaai/openpilot' && github.ref == 'refs/heads/master'
uses: nick-fields/retry@7152eba30c6575329ac0576536151aca5a72780e uses: nick-fields/retry@ad984534de44a9489a53aefd81eb77f87c70dc60
with: with:
timeout_minutes: 2 timeout_minutes: 2
max_attempts: 3 max_attempts: 3
@@ -203,7 +199,7 @@ jobs:
timeout-minutes: 4 timeout-minutes: 4
env: env:
ONNXCPU: 1 ONNXCPU: 1
run: $PYTEST selfdrive/test/process_replay/test_regen.py run: $PYTEST openpilot/selfdrive/test/process_replay/test_regen.py
simulator_driving: simulator_driving:
name: simulator driving name: simulator driving
@@ -215,17 +211,16 @@ jobs:
|| fromJSON('["ubuntu-24.04"]') }} || fromJSON('["ubuntu-24.04"]') }}
if: false # FIXME: Started to timeout recently if: false # FIXME: Started to timeout recently
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Build openpilot - name: Build openpilot
run: scons run: scons
- name: Driving test - name: Driving test
timeout-minutes: 2 timeout-minutes: 2
run: | env:
source selfdrive/test/setup_xvfb.sh # MetaDrive renders offscreen through panda3d's EGL pipe on llvmpipe
pytest -s tools/sim/tests/test_metadrive_bridge.py EGL_PLATFORM: surfaceless
run: pytest -s openpilot/tools/sim/tests/test_metadrive_bridge.py
create_ui_report: create_ui_report:
name: Create UI Report name: Create UI Report
@@ -236,19 +231,21 @@ jobs:
&& fromJSON('["namespace-profile-amd64-8x16"]') && fromJSON('["namespace-profile-amd64-8x16"]')
|| fromJSON('["ubuntu-24.04"]') }} || fromJSON('["ubuntu-24.04"]') }}
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with:
submodules: true
- run: ./tools/op.sh setup - run: ./tools/op.sh setup
- name: Install raylib headless dependencies
if: ${{ !contains(runner.name, 'nsc') }}
run: sudo apt-get install -y --no-install-recommends libgles2 libegl1
- name: Build openpilot - name: Build openpilot
run: scons run: scons
- name: Create UI Report - name: Create UI Report
env:
RAYLIB_BACKEND: headless
run: | run: |
source selfdrive/test/setup_xvfb.sh python3 openpilot/selfdrive/ui/tests/diff/replay.py
python3 selfdrive/ui/tests/diff/replay.py python3 openpilot/selfdrive/ui/tests/diff/replay.py --big
python3 selfdrive/ui/tests/diff/replay.py --big
- name: Upload UI Report - name: Upload UI Report
uses: actions/upload-artifact@v6 uses: actions/upload-artifact@v7
with: with:
name: ui-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }} name: ui-report-${{ inputs.run_number || '1' }}-${{ github.event_name == 'push' && github.ref == 'refs/heads/master' && 'master' || github.event.number }}
path: selfdrive/ui/tests/diff/report path: openpilot/selfdrive/ui/tests/diff/report
+17 -17
View File
@@ -8,9 +8,9 @@ on:
branches: branches:
- 'master' - 'master'
paths: paths:
- 'selfdrive/assets/**' - 'openpilot/selfdrive/assets/**'
- 'selfdrive/ui/**' - 'openpilot/selfdrive/ui/**'
- 'system/ui/**' - 'openpilot/system/ui/**'
workflow_dispatch: workflow_dispatch:
env: env:
@@ -34,12 +34,12 @@ jobs:
pull-requests: write pull-requests: write
actions: read actions: read
steps: steps:
- uses: actions/checkout@v6 - uses: actions/checkout@v7
with: with:
submodules: true submodules: true
- name: Waiting for ui generation to end - name: Waiting for ui generation to end
uses: lewagon/wait-on-check-action@v1.3.4 uses: lewagon/wait-on-check-action@1d57e2c51a58d812d2765e036a028b6bdb5a6154
with: with:
ref: ${{ env.SHA }} ref: ${{ env.SHA }}
check-name: ${{ env.UI_JOB_NAME }} check-name: ${{ env.UI_JOB_NAME }}
@@ -53,7 +53,7 @@ jobs:
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 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 - name: Getting proposed ui
uses: dawidd6/action-download-artifact@v6 uses: dawidd6/action-download-artifact@b6e2e70617bc3265edd6dab6c906732b2f1ae151
with: with:
github_token: ${{ secrets.GITHUB_TOKEN }} github_token: ${{ secrets.GITHUB_TOKEN }}
run_id: ${{ steps.get_run_id.outputs.run_id }} run_id: ${{ steps.get_run_id.outputs.run_id }}
@@ -62,7 +62,7 @@ jobs:
path: ${{ github.workspace }}/pr_ui path: ${{ github.workspace }}/pr_ui
- name: Getting mici master ui - name: Getting mici master ui
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
repository: sunnypilot/ci-artifacts repository: sunnypilot/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }} ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
@@ -70,7 +70,7 @@ jobs:
ref: openpilot_master_ui_mici_raylib ref: openpilot_master_ui_mici_raylib
- name: Getting big master ui - name: Getting big master ui
uses: actions/checkout@v6 uses: actions/checkout@v7
with: with:
repository: sunnypilot/ci-artifacts repository: sunnypilot/ci-artifacts
ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }} ssh-key: ${{ secrets.CI_ARTIFACTS_DEPLOY_KEY }}
@@ -97,7 +97,7 @@ jobs:
done done
- name: Setup FFmpeg - name: Setup FFmpeg
uses: AnimMouse/setup-ffmpeg@ae28d57dabbb148eff63170b6bf7f2b60062cbae uses: AnimMouse/setup-ffmpeg@178e0b4a408f06ce40d896c3cd79f50fa6f8b0c3
- name: Finding diffs - name: Finding diffs
if: github.event_name == 'pull_request_target' if: github.event_name == 'pull_request_target'
@@ -115,13 +115,13 @@ jobs:
cp "${{ github.workspace }}/master_${name}/${video}.mp4" "${{ github.workspace }}/pr_ui/${video}_master.mp4" cp "${{ github.workspace }}/master_${name}/${video}.mp4" "${{ github.workspace }}/pr_ui/${video}_master.mp4"
diff_exit_code=0 diff_exit_code=0
python3 ${{ github.workspace }}/selfdrive/ui/tests/diff/diff.py \ python3 ${{ github.workspace }}/openpilot/selfdrive/ui/tests/diff/diff.py \
"${{ github.workspace }}/pr_ui/${video}_master.mp4" \ "${{ github.workspace }}/pr_ui/${video}_master.mp4" \
"${{ github.workspace }}/pr_ui/${video}_proposed.mp4" \ "${{ github.workspace }}/pr_ui/${video}_proposed.mp4" \
"${diff_name}.html" --basedir "$baseurl" --no-open || diff_exit_code=$? "${diff_name}.html" --basedir "$baseurl" --no-open || diff_exit_code=$?
cp "${{ github.workspace }}/selfdrive/ui/tests/diff/report/${diff_name}.html" "${{ github.workspace }}/pr_ui/" cp "${{ github.workspace }}/openpilot/selfdrive/ui/tests/diff/report/${diff_name}.html" "${{ github.workspace }}/pr_ui/"
cp "${{ github.workspace }}/selfdrive/ui/tests/diff/report/${diff_name}.mp4" "${{ github.workspace }}/pr_ui/" cp "${{ github.workspace }}/openpilot/selfdrive/ui/tests/diff/report/${diff_name}.mp4" "${{ github.workspace }}/pr_ui/"
REPORT_URL="https://sunnypilot.github.io/ci-artifacts/${diff_name}_pr_${{ github.event.number }}.html" REPORT_URL="https://sunnypilot.github.io/ci-artifacts/${diff_name}_pr_${{ github.event.number }}.html"
if [ $diff_exit_code -eq 0 ]; then if [ $diff_exit_code -eq 0 ]; then
@@ -156,7 +156,7 @@ jobs:
for variant in $VARIANTS; do for variant in $VARIANTS; do
IFS=':' read -r name _ _ <<< "$variant" IFS=':' read -r name _ _ <<< "$variant"
diff_name="${name}_diff" diff_name="${name}_diff"
cp "${{ github.workspace }}/selfdrive/ui/tests/diff/report/${diff_name}.html" "${diff_name}_pr_${{ github.event.number }}.html" cp "${{ github.workspace }}/openpilot/selfdrive/ui/tests/diff/report/${diff_name}.html" "${diff_name}_pr_${{ github.event.number }}.html"
git add "${diff_name}_pr_${{ github.event.number }}.html" git add "${diff_name}_pr_${{ github.event.number }}.html"
done done
git commit -m "ui diff reports for PR #${{ github.event.number }}" || echo "No changes to commit" git commit -m "ui diff reports for PR #${{ github.event.number }}" || echo "No changes to commit"
@@ -164,12 +164,12 @@ jobs:
- name: Comment on PR - name: Comment on PR
if: github.event_name == 'pull_request_target' if: github.event_name == 'pull_request_target'
uses: thollander/actions-comment-pull-request@v2 uses: thollander/actions-comment-pull-request@24bffb9b452ba05a4f3f77933840a6a841d1b32b
with: with:
message: | message: |
<!-- _(run_id_ui_preview **${{ github.run_id }}**)_ --> <!-- _(run_id_ui_preview **${{ github.run_id }}**)_ -->
## UI Preview ## UI Preview
${{ steps.find_diff.outputs.COMMENT }} ${{ steps.find_diff.outputs.COMMENT }}
comment_tag: run_id_ui_preview comment-tag: run_id_ui_preview
pr_number: ${{ github.event.number }} pr-number: ${{ github.event.number }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} github-token: ${{ secrets.GITHUB_TOKEN }}
+16 -9
View File
@@ -15,6 +15,13 @@ a.out
.cache/ .cache/
bin/ bin/
# created at launch for TICI PYTHONPATH (PC uses editable installs via pyproject.toml)
/msgq
/opendbc
/rednose
/teleoprtc
/tinygrad
*.mp4 *.mp4
*.dylib *.dylib
*.DSYM *.DSYM
@@ -44,18 +51,18 @@ bin/
config.json config.json
compile_commands.json compile_commands.json
compare_runtime*.html compare_runtime*.html
selfdrive/modeld/models/tg_input_devices.json openpilot/selfdrive/modeld/models/tg_input_devices.json
# build artifacts # build artifacts
docs_site/ docs_site/
selfdrive/pandad/pandad openpilot/selfdrive/pandad/pandad
cereal/services.h openpilot/cereal/services.h
cereal/gen openpilot/cereal/gen
cereal/messaging/bridge openpilot/cereal/messaging/bridge
selfdrive/ui/translations/tmp openpilot/selfdrive/ui/translations/tmp
selfdrive/car/tests/cars_dump openpilot/selfdrive/car/tests/cars_dump
system/camerad/camerad openpilot/system/camerad/camerad
system/camerad/test/ae_gray_test openpilot/system/camerad/test/ae_gray_test
.coverage* .coverage*
coverage.xml coverage.xml
+1 -1
View File
@@ -17,5 +17,5 @@
path = tinygrad_repo path = tinygrad_repo
url = https://github.com/sunnypilot/tinygrad.git url = https://github.com/sunnypilot/tinygrad.git
[submodule "sunnypilot/neural_network_data"] [submodule "sunnypilot/neural_network_data"]
path = sunnypilot/neural_network_data path = openpilot/sunnypilot/neural_network_data
url = https://github.com/sunnypilot/neural-network-data.git url = https://github.com/sunnypilot/neural-network-data.git
+4 -4
View File
@@ -6,9 +6,9 @@
"type": "pickString", "type": "pickString",
"description": "Select the process to debug", "description": "Select the process to debug",
"options": [ "options": [
"selfdrive/controls/controlsd.py", "openpilot/selfdrive/controls/controlsd.py",
"system/timed/timed.py", "openpilot/system/timed/timed.py",
"tools/sim/run_bridge.py" "openpilot/tools/sim/run_bridge.py"
] ]
}, },
{ {
@@ -16,7 +16,7 @@
"type": "pickString", "type": "pickString",
"description": "Select the process to debug", "description": "Select the process to debug",
"options": [ "options": [
"selfdrive/ui/ui" "openpilot/selfdrive/ui/ui"
] ]
}, },
{ {
-5
View File
@@ -17,10 +17,5 @@
"**/.git", "**/.git",
"**/.venv", "**/.venv",
"**/__pycache__", "**/__pycache__",
// exclude directories that should be using the symlinked version
"common/**",
"selfdrive/**",
"system/**",
"tools/**",
] ]
} }
Vendored
+27 -25
View File
@@ -63,6 +63,8 @@ if [ -f /data/openpilot/launch_env.sh ]; then
source /data/openpilot/launch_env.sh source /data/openpilot/launch_env.sh
fi fi
export LD_LIBRARY_PATH="\$(python -c 'import ffmpeg; print(ffmpeg.LIB_DIR)'):/usr/local/lib:\${LD_LIBRARY_PATH:-}"
ln -snf ${env.TEST_DIR} /data/pythonpath ln -snf ${env.TEST_DIR} /data/pythonpath
cd ${env.TEST_DIR} || true cd ${env.TEST_DIR} || true
@@ -93,7 +95,7 @@ def deviceStage(String stageName, String deviceType, List extra_env, def steps)
retry (3) { retry (3) {
def date = sh(script: 'date', returnStdout: true).trim(); def date = sh(script: 'date', returnStdout: true).trim();
device(device_ip, "set time", "date -s '" + date + "'") device(device_ip, "set time", "date -s '" + date + "'")
device(device_ip, "git checkout", extra + "\n" + readFile("selfdrive/test/setup_device_ci.sh")) device(device_ip, "git checkout", extra + "\n" + readFile("openpilot/selfdrive/test/setup_device_ci.sh"))
} }
steps.each { item -> steps.each { item ->
def name = item[0] def name = item[0]
@@ -179,7 +181,7 @@ node {
try { try {
if (env.BRANCH_NAME == 'devel-staging') { if (env.BRANCH_NAME == 'devel-staging') {
deviceStage("build release-tizi-staging", "tizi-needs-can", [], [ deviceStage("build release-tizi-staging", "tizi-needs-can", [], [
step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging,release-mici-staging $SOURCE_DIR/release/build_release.sh"), step("build release-tizi-staging", "RELEASE_BRANCH=release-tizi-staging,release-mici-staging $SOURCE_DIR/tools/release/build_release.sh"),
]) ])
} }
@@ -187,12 +189,12 @@ node {
parallel ( parallel (
'nightly': { 'nightly': {
deviceStage("build nightly", "tizi-needs-can", [], [ deviceStage("build nightly", "tizi-needs-can", [], [
step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/release/build_release.sh"), step("build nightly", "RELEASE_BRANCH=nightly $SOURCE_DIR/tools/release/build_release.sh"),
]) ])
}, },
'nightly-dev': { 'nightly-dev': {
deviceStage("build nightly-dev", "tizi-needs-can", [], [ deviceStage("build nightly-dev", "tizi-needs-can", [], [
step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/release/build_release.sh"), step("build nightly-dev", "PANDA_DEBUG_BUILD=1 RELEASE_BRANCH=nightly-dev $SOURCE_DIR/tools/release/build_release.sh"),
]) ])
}, },
) )
@@ -202,51 +204,51 @@ node {
parallel ( parallel (
'onroad tests': { 'onroad tests': {
deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [ deviceStage("onroad", "tizi-needs-can", ["UNSAFE=1"], [
step("build openpilot", "cd system/manager && ./build.py"), step("build openpilot", "cd openpilot/system/manager && ./build.py"),
step("check dirty", "release/check-dirty.sh"), step("check dirty", "tools/release/check-dirty.sh"),
step("onroad tests", "pytest selfdrive/test/test_onroad.py -s", [timeout: 60]), step("onroad tests", "pytest openpilot/selfdrive/test/test_onroad.py -s", [timeout: 60]),
]) ])
}, },
'HW + Unit Tests': { 'HW + Unit Tests': {
deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [ deviceStage("tizi-hardware", "tizi-common", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py"), step("build", "cd openpilot/system/manager && ./build.py"),
step("test power draw", "pytest -s selfdrive/test//test_power_draw.py"), step("test power draw", "pytest -s openpilot/selfdrive/test//test_power_draw.py"),
step("test encoder", "LD_LIBRARY_PATH=/usr/local/lib pytest system/loggerd/tests/test_encoder.py", [diffPaths: ["system/loggerd/"]]), step("test encoder", "pytest openpilot/system/loggerd/tests/test_encoder.py", [diffPaths: ["openpilot/system/loggerd/"]]),
step("test manager", "pytest system/manager/test/test_manager.py"), step("test manager", "pytest openpilot/system/manager/test/test_manager.py"),
]) ])
}, },
'camerad OX03C10': { 'camerad OX03C10': {
deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [ deviceStage("OX03C10", "tizi-ox03c10", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py"), step("build", "cd openpilot/system/manager && ./build.py"),
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"), step("test pandad", "pytest openpilot/selfdrive/pandad/tests/test_pandad.py"),
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]), step("test camerad", "pytest openpilot/system/camerad/test/test_camerad.py", [timeout: 90]),
]) ])
}, },
'camerad OS04C10': { 'camerad OS04C10': {
deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [ deviceStage("OS04C10", "tici-os04c10", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py"), step("build", "cd openpilot/system/manager && ./build.py"),
step("test pandad", "pytest selfdrive/pandad/tests/test_pandad.py"), step("test pandad", "pytest openpilot/selfdrive/pandad/tests/test_pandad.py"),
step("test camerad", "pytest system/camerad/test/test_camerad.py", [timeout: 90]), step("test camerad", "pytest openpilot/system/camerad/test/test_camerad.py", [timeout: 90]),
]) ])
}, },
'sensord': { 'sensord': {
deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [ deviceStage("LSM + MMC", "tizi-lsmc", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py"), step("build", "cd openpilot/system/manager && ./build.py"),
step("test sensord", "pytest system/sensord/tests/test_sensord.py"), step("test sensord", "pytest openpilot/system/sensord/tests/test_sensord.py"),
]) ])
}, },
'replay': { 'replay': {
deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [ deviceStage("model-replay", "tizi-replay", ["UNSAFE=1"], [
step("build", "cd system/manager && ./build.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), step("build", "cd openpilot/system/manager && ./build.py", [diffPaths: ["openpilot/selfdrive/modeld/", "tinygrad_repo", "openpilot/selfdrive/test/process_replay/model_replay.py"]]),
step("model replay", "selfdrive/test/process_replay/model_replay.py", [diffPaths: ["selfdrive/modeld/", "tinygrad_repo", "selfdrive/test/process_replay/model_replay.py"]]), step("model replay", "openpilot/selfdrive/test/process_replay/model_replay.py", [diffPaths: ["openpilot/selfdrive/modeld/", "tinygrad_repo", "openpilot/selfdrive/test/process_replay/model_replay.py"]]),
]) ])
}, },
'tizi': { 'tizi': {
deviceStage("tizi", "tizi", ["UNSAFE=1"], [ deviceStage("tizi", "tizi", ["UNSAFE=1"], [
step("build openpilot", "cd system/manager && ./build.py"), step("build openpilot", "cd openpilot/system/manager && ./build.py"),
step("test pandad loopback", "pytest selfdrive/pandad/tests/test_pandad_loopback.py"), step("test pandad loopback", "pytest openpilot/selfdrive/pandad/tests/test_pandad_loopback.py"),
step("test pandad spi", "pytest selfdrive/pandad/tests/test_pandad_spi.py"), step("test pandad spi", "pytest openpilot/selfdrive/pandad/tests/test_pandad_spi.py"),
step("test amp", "pytest common/hardware/tici/tests/test_amplifier.py"), step("test amp", "pytest openpilot/common/hardware/tici/tests/test_amplifier.py"),
]) ])
}, },
+1 -1
View File
@@ -1104,7 +1104,7 @@ Version 0.2.1 (2016-12-14)
Version 0.2 (2016-12-12) Version 0.2 (2016-12-12)
========================= =========================
* Car/Radar abstraction layers have shipped, see cereal/car.capnp * Car/Radar abstraction layers have shipped, see openpilot/cereal/car.capnp
* controlsd has been refactored * controlsd has been refactored
* Shipped plant model and testing maneuvers * Shipped plant model and testing maneuvers
* visiond exits more gracefully now * visiond exits more gracefully now
+64 -25
View File
@@ -27,6 +27,21 @@ AddOption('--minimal',
default=(not TICI and not release), default=(not TICI and not release),
help='the minimum build to run openpilot. no tests, tools, etc.') help='the minimum build to run openpilot. no tests, tools, etc.')
submodule_python_paths = [
Dir("#").abspath,
Dir("#msgq_repo").abspath,
Dir("#opendbc_repo").abspath,
Dir("#rednose_repo").abspath,
Dir("#teleoprtc_repo").abspath,
Dir("#tinygrad_repo").abspath,
]
for p in reversed(submodule_python_paths):
if p not in sys.path:
sys.path.insert(0, p)
if external_pythonpath := os.environ.get("PYTHONPATH"):
submodule_python_paths += [p for p in external_pythonpath.split(os.pathsep) if p and p not in submodule_python_paths]
# Detect platform # Detect platform
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
if platform.system() == "Darwin": if platform.system() == "Darwin":
@@ -40,9 +55,24 @@ assert arch in [
"Darwin", # macOS arm64 (x86 not supported) "Darwin", # macOS arm64 (x86 not supported)
] ]
pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'libjpeg', 'libyuv', 'ncurses', 'zeromq', 'zstd'] pkg_names = ['acados', 'bzip2', 'capnproto', 'catch2', 'eigen', 'ffmpeg', 'json11', 'ncurses', 'zeromq', 'zstd']
pkgs = [importlib.import_module(name) for name in pkg_names] pkgs = [importlib.import_module(name) for name in pkg_names]
acados = pkgs[pkg_names.index('acados')] acados = pkgs[pkg_names.index('acados')]
ffmpeg = pkgs[pkg_names.index('ffmpeg')]
# Shared package ships .so/.dylib; older device venvs still have static .a only.
# Keep static link deps (x264/z/va/drm) when the installed package is static so
# TICI CI works without upgrading the device venv yet.
# TODO: drop the static fallback once device venvs have comma-deps-ffmpeg>=7.1.0.post94
_ffmpeg_lib_names = os.listdir(ffmpeg.LIB_DIR) if os.path.isdir(ffmpeg.LIB_DIR) else []
ffmpeg_shared = any(
n.startswith('libavcodec.so') or (n.startswith('libavcodec') and n.endswith('.dylib'))
for n in _ffmpeg_lib_names
)
ffmpeg_libs = ['avformat', 'avcodec', 'swresample', 'avutil']
if not ffmpeg_shared:
ffmpeg_libs += ['x264', 'z']
if arch != "Darwin":
ffmpeg_libs += ['va', 'va-drm', 'drm']
acados_include_dirs = [ acados_include_dirs = [
acados.INCLUDE_DIR, acados.INCLUDE_DIR,
os.path.join(acados.INCLUDE_DIR, "blasfeo", "include"), os.path.join(acados.INCLUDE_DIR, "blasfeo", "include"),
@@ -91,7 +121,7 @@ def _libflags(target, source, env, for_signature):
env = Environment( env = Environment(
ENV={ ENV={
"PATH": os.environ['PATH'], "PATH": os.environ['PATH'],
"PYTHONPATH": Dir("#").abspath, "PYTHONPATH": os.pathsep.join(submodule_python_paths),
"ACADOS_SOURCE_DIR": acados.DIR, "ACADOS_SOURCE_DIR": acados.DIR,
"ACADOS_PYTHON_INTERFACE_PATH": acados.TEMPLATE_DIR, "ACADOS_PYTHON_INTERFACE_PATH": acados.TEMPLATE_DIR,
"TERA_PATH": acados.TERA_PATH "TERA_PATH": acados.TERA_PATH
@@ -112,25 +142,35 @@ env = Environment(
CFLAGS=["-std=gnu11"], CFLAGS=["-std=gnu11"],
CXXFLAGS=["-std=c++1z"], CXXFLAGS=["-std=c++1z"],
CPPPATH=[ CPPPATH=[
"#", "#openpilot",
"#msgq", "#msgq_repo", # #include "msgq/..."
"#opendbc_repo", # #include "opendbc/..."
"#rednose_repo", # #include "rednose/..."
"#rednose_repo/rednose", # #include "logger/..." (rednose package root)
"#openpilot/cereal/gen/cpp",
acados_include_dirs, acados_include_dirs,
[x.INCLUDE_DIR for x in pkgs], [x.INCLUDE_DIR for x in pkgs],
"#",
], ],
LIBPATH=[ LIBPATH=[
"#common", "#openpilot/common",
"#msgq_repo", "#msgq_repo",
"#selfdrive/pandad", "#openpilot/selfdrive/pandad",
"#rednose/helpers", "#rednose_repo/rednose/helpers",
[x.LIB_DIR for x in pkgs], [x.LIB_DIR for x in pkgs],
], ],
RPATH=[], RPATH=[ffmpeg.LIB_DIR] if ffmpeg_shared else [],
CYTHONCFILESUFFIX=".cpp", CYTHONCFILESUFFIX=".cpp",
COMPILATIONDB_USE_ABSPATH=True, COMPILATIONDB_USE_ABSPATH=True,
REDNOSE_ROOT="#", REDNOSE_ROOT="#rednose_repo",
tools=["default", "cython", "compilation_db", "rednose_filter"], tools=["default", "cython", "compilation_db", "rednose_filter"],
toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"], toolpath=["#site_scons/site_tools", "#rednose_repo/site_scons/site_tools"],
) )
# SCons' Darwin linker tool doesn't define the variables used to expand RPATH.
if arch == "Darwin":
env["RPATHPREFIX"] = "-Wl,-rpath,"
env["RPATHSUFFIX"] = ""
env["_RPATH"] = "${_concat(RPATHPREFIX, RPATH, RPATHSUFFIX, __env__)}"
if arch != "larch64": if arch != "larch64":
env['_LIBFLAGS'] = _libflags env['_LIBFLAGS'] = _libflags
@@ -190,7 +230,7 @@ else:
np_version = SCons.Script.Value(np.__version__) np_version = SCons.Script.Value(np.__version__)
Export('envCython', 'np_version') Export('envCython', 'np_version')
Export('env', 'arch', 'acados', 'release') Export('env', 'arch', 'acados', 'release', 'ffmpeg_libs')
# Setup cache dir # Setup cache dir
default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache' default_cache_dir = '/data/scons_cache' if arch == "larch64" else '/tmp/scons_cache'
@@ -211,7 +251,7 @@ def prune_cache_dir(target=None, source=None, env=None):
# ********** start building stuff ********** # ********** start building stuff **********
# Build common module # Build common module
SConscript(['common/SConscript']) SConscript(['openpilot/common/SConscript'])
Import('_common') Import('_common')
common = [_common, 'json11', 'zmq'] common = [_common, 'json11', 'zmq']
Export('common') Export('common')
@@ -222,7 +262,7 @@ env_swaglog = env.Clone()
env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""') env_swaglog['CXXFLAGS'].append('-DSWAGLOG="\\"common/swaglog.h\\""')
SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog}) SConscript(['msgq_repo/SConscript'], exports={'env': env_swaglog})
SConscript(['cereal/SConscript']) SConscript(['openpilot/cereal/SConscript'])
Import('socketmaster', 'msgq') Import('socketmaster', 'msgq')
messaging = [socketmaster, msgq, 'capnp', 'kj',] messaging = [socketmaster, msgq, 'capnp', 'kj',]
@@ -233,34 +273,33 @@ Export('messaging')
SConscript(['panda/SConscript']) SConscript(['panda/SConscript'])
# Build rednose library # Build rednose library
SConscript(['rednose/SConscript']) SConscript(['rednose_repo/rednose/SConscript'])
# Build system services # Build system services
SConscript([ SConscript([
'system/loggerd/SConscript', 'openpilot/system/loggerd/SConscript',
]) ])
if arch == "larch64": if arch == "larch64":
SConscript(['system/camerad/SConscript']) SConscript(['openpilot/system/camerad/SConscript'])
# Build selfdrive # Build selfdrive
SConscript([ SConscript([
'selfdrive/pandad/SConscript', 'openpilot/selfdrive/pandad/SConscript',
'selfdrive/controls/lib/lateral_mpc_lib/SConscript', 'openpilot/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript',
'selfdrive/controls/lib/longitudinal_mpc_lib/SConscript', 'openpilot/selfdrive/locationd/SConscript',
'selfdrive/locationd/SConscript', 'openpilot/selfdrive/modeld/SConscript',
'selfdrive/modeld/SConscript', 'openpilot/selfdrive/ui/SConscript',
'selfdrive/ui/SConscript',
]) ])
SConscript(['sunnypilot/SConscript']) SConscript(['openpilot/sunnypilot/SConscript'])
# Build desktop-only tools # Build desktop-only tools
if GetOption('extras') and arch != "larch64": if GetOption('extras') and arch != "larch64":
SConscript([ SConscript([
'tools/replay/SConscript', 'openpilot/tools/replay/SConscript',
'tools/cabana/SConscript', 'openpilot/tools/cabana/SConscript',
'tools/jotpluggler/SConscript', 'openpilot/tools/jotpluggler/SConscript',
]) ])
-20
View File
@@ -1,20 +0,0 @@
Import('env', 'common', 'msgq')
cereal_dir = Dir('.')
gen_dir = Dir('gen')
# Build cereal
schema_files = ['log.capnp', 'car.capnp', 'deprecated.capnp', 'custom.capnp']
env.Command([f'gen/cpp/{s}.c++' for s in schema_files] + [f'gen/cpp/{s}.h' for s in schema_files],
schema_files,
f"capnpc --src-prefix={cereal_dir.path} $SOURCES -o c++:{gen_dir.path}/cpp/")
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', 'messaging/bridge_zmq.cc'], LIBS=[msgq, common, 'pthread'])
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
Export('cereal', 'socketmaster')
-11
View File
@@ -1,11 +0,0 @@
import os
import capnp
from importlib.resources import as_file, files
capnp.remove_import_hook()
with as_file(files("cereal")) as fspath:
CEREAL_PATH = fspath.as_posix()
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"))
car = capnp.load(os.path.join(CEREAL_PATH, "car.capnp"))
custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp"))
-1
View File
@@ -1 +0,0 @@
../opendbc_repo/opendbc/car/car.capnp
-27
View File
@@ -1,27 +0,0 @@
#include "catch2/catch.hpp"
#define private public
#include "common/params.h"
#include "common/util.h"
TEST_CASE("params_nonblocking_put") {
char tmp_path[] = "/tmp/asyncWriter_XXXXXX";
const std::string param_path = mkdtemp(tmp_path);
auto param_names = {"CarParams", "IsMetric"};
{
Params params(param_path);
for (const auto &name : param_names) {
params.putNonBlocking(name, "1");
// param is empty
REQUIRE(params.get(name).empty());
}
// check if thread is running
REQUIRE(params.future.valid());
REQUIRE(params.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::timeout);
}
// check results
Params p(param_path);
for (const auto &name : param_names) {
REQUIRE(p.get(name) == "1");
}
}
+6 -3
View File
@@ -9,11 +9,14 @@ from openpilot.common.hardware import TICI, HARDWARE
# these are heavy CI-only tests, invoked explicitly in .github/workflows/tests.yaml # these are heavy CI-only tests, invoked explicitly in .github/workflows/tests.yaml
collect_ignore = [ collect_ignore = [
"selfdrive/test/process_replay/test_processes.py", "openpilot/selfdrive/test/process_replay/test_processes.py",
"selfdrive/test/process_replay/test_regen.py", "openpilot/selfdrive/test/process_replay/test_regen.py",
"openpilot/tools/sim/",
# tinygrad JIT has process-global state. Other test files import modeld → tinygrad, # tinygrad JIT has process-global state. Other test files import modeld → tinygrad,
# which corrupts JIT captures for test_warp.py in the same process. Run separately in CI. # which corrupts JIT captures for test_warp.py in the same process. Run separately in CI.
"sunnypilot/modeld_v2/tests/test_warp.py", "openpilot/sunnypilot/modeld_v2/tests/test_warp.py",
] ]
+1 -1
View File
@@ -68,6 +68,6 @@ A good pull request has all of the following:
### A guide for forks ### A guide for forks
In order for your fork's data to be eligible for the training set: In order for your fork's data to be eligible for the training set:
* **Your cereal messaging structs must be [compatible](../cereal#custom-forks)** * **Your cereal messaging structs must be [compatible](../openpilot/cereal#custom-forks)**
* **The definitions of all the stock messaging structs must not change**: Do not change how any of the fields are set, including everything from `selfdriveState.enabled` to `carState.steeringAngleDeg`. Instead, create your own structs and set them however you'd like. * **The definitions of all the stock messaging structs must not change**: Do not change how any of the fields are set, including everything from `selfdriveState.enabled` to `carState.steeringAngleDeg`. Instead, create your own structs and set them however you'd like.
* **Do not include cars that are not supported in upstream platforms**: Instead, create new opendbc platforms for cars that you'd like to support outside of upstream, even if it's just a trim-level difference. * **Do not include cars that are not supported in upstream platforms**: Instead, create new opendbc platforms for cars that you'd like to support outside of upstream, even if it's just a trim-level difference.
+2 -2
View File
@@ -35,8 +35,8 @@ For additional safety implementation details, refer to [panda safety model](http
### Forks of openpilot ### Forks of openpilot
* Do not disable or nerf [driver monitoring](https://github.com/commaai/openpilot/tree/master/selfdrive/monitoring) * Do not disable or nerf [driver monitoring](https://github.com/commaai/openpilot/tree/master/openpilot/selfdrive/monitoring)
* Do not disable or nerf [excessive actuation checks](https://github.com/commaai/openpilot/tree/master/selfdrive/selfdrived/helpers.py) * Do not disable or nerf [excessive actuation checks](https://github.com/commaai/openpilot/tree/master/openpilot/selfdrive/selfdrived/helpers.py)
* If your fork modifies any of the code in `opendbc/safety/`: * If your fork modifies any of the code in `opendbc/safety/`:
* your fork cannot use the openpilot trademark * your fork cannot use the openpilot trademark
* your fork must preserve the full [safety test suite](https://github.com/commaai/opendbc/tree/master/opendbc/safety/tests) and all tests must pass, including any new coverage required by the fork's changes * your fork must preserve the full [safety test suite](https://github.com/commaai/opendbc/tree/master/opendbc/safety/tests) and all tests must pass, including any new coverage required by the fork's changes
+3 -3
View File
@@ -2,13 +2,13 @@
openpilot records routes in one minute chunks called segments. A route starts on the rising edge of ignition and ends on the falling edge. openpilot records routes in one minute chunks called segments. A route starts on the rising edge of ignition and ends on the falling edge.
Check out our [Python library](https://github.com/commaai/openpilot/blob/master/tools/lib/logreader.py) for reading openpilot logs. Also checkout our [tools](https://github.com/commaai/openpilot/tree/master/tools) to replay and view your data. These are the same tools we use to debug and develop openpilot. Check out our [Python library](https://github.com/commaai/openpilot/blob/master/openpilot/tools/lib/logreader.py) for reading openpilot logs. Also checkout our [tools](https://github.com/commaai/openpilot/tree/master/openpilot/tools) to replay and view your data. These are the same tools we use to debug and develop openpilot.
For each segment, openpilot records the following log types: For each segment, openpilot records the following log types:
## rlog.zst ## rlog.zst
rlogs contain all the messages passed amongst openpilot's processes. See [cereal/services.py](https://github.com/commaai/openpilot/blob/master/cereal/services.py) for a list of all the logged services. They're a zstd archive of the serialized [Capn Proto](https://capnproto.org/) messages. rlogs contain all the messages passed amongst openpilot's processes. See [openpilot/cereal/services.py](https://github.com/commaai/openpilot/blob/master/openpilot/cereal/services.py) for a list of all the logged services. They're a zstd archive of the serialized [Capn Proto](https://capnproto.org/) messages.
## {f,e,d}camera.hevc ## {f,e,d}camera.hevc
@@ -20,7 +20,7 @@ Each camera stream is H.265 encoded and written to its respective file.
## qlog.zst & qcamera.ts ## qlog.zst & qcamera.ts
qlogs are a decimated subset of the rlogs. Check out [cereal/services.py](https://github.com/commaai/cereal/blob/master/services.py) for the decimation. qlogs are a decimated subset of the rlogs. Check out [openpilot/cereal/services.py](https://github.com/commaai/openpilot/blob/master/openpilot/cereal/services.py) for the decimation.
qcameras are H.264 encoded, lower res versions of the fcamera.hevc. The video shown in [comma connect](https://connect.comma.ai/) is from the qcameras. qcameras are H.264 encoded, lower res versions of the fcamera.hevc. The video shown in [comma connect](https://connect.comma.ai/) is from the qcameras.
+1 -1
View File
@@ -30,7 +30,7 @@ Each car brand is supported by a standard interface structure in `opendbc/car/[b
For historical reasons, openpilot still contains a small amount of car-specific logic. This will eventually be migrated to opendbc or otherwise removed. For historical reasons, openpilot still contains a small amount of car-specific logic. This will eventually be migrated to opendbc or otherwise removed.
* `selfdrive/car/car_specific.py`: Brand-specific event logic * `openpilot/selfdrive/car/car_specific.py`: Brand-specific event logic
# How do I port car? # How do I port car?
+1 -1
View File
@@ -5,7 +5,7 @@ Replaying is a critical tool for openpilot development and debugging.
## Replaying a route ## Replaying a route
*Hardware required: none* *Hardware required: none*
Just run `tools/replay/replay --demo`. Just run `openpilot/tools/replay/replay --demo`.
## Replaying CAN data ## Replaying CAN data
*Hardware required: jungle and comma four* *Hardware required: jungle and comma four*
+5 -5
View File
@@ -28,10 +28,10 @@ scons
We'll run the `replay` tool with the demo route to get data streaming for testing our UI changes. We'll run the `replay` tool with the demo route to get data streaming for testing our UI changes.
```bash ```bash
# in terminal 1 # in terminal 1
tools/replay/replay --demo openpilot/tools/replay/replay --demo
# in terminal 2 # in terminal 2
./selfdrive/ui/ui.py ./openpilot/selfdrive/ui/ui.py
``` ```
The openpilot UI should launch and show a replay of the demo route. The openpilot UI should launch and show a replay of the demo route.
@@ -45,10 +45,10 @@ Now lets update the speed display color in the UI.
Search for the function responsible for rendering the current speed: Search for the function responsible for rendering the current speed:
```bash ```bash
git grep "_draw_current_speed" selfdrive/ui/onroad/hud_renderer.py git grep "_draw_current_speed" openpilot/selfdrive/ui/onroad/hud_renderer.py
``` ```
You'll find the relevant code inside `selfdrive/ui/onroad/hud_renderer.py`, in this function: You'll find the relevant code inside `openpilot/selfdrive/ui/onroad/hud_renderer.py`, in this function:
```python ```python
def _draw_current_speed(self, rect: rl.Rectangle) -> None: def _draw_current_speed(self, rect: rl.Rectangle) -> None:
@@ -72,7 +72,7 @@ Change `COLORS.white` to make it **blue** instead of white. A nice soft blue is
After making changes, re-run the UI to see your new UI: After making changes, re-run the UI to see your new UI:
```bash ```bash
./selfdrive/ui/ui.py ./openpilot/selfdrive/ui/ui.py
``` ```
![](https://blog.comma.ai/img/blue_speed_ui.png) ![](https://blog.comma.ai/img/blue_speed_ui.png)
+12 -4
View File
@@ -19,12 +19,12 @@ function agnos_init {
# Check if AGNOS update is required # Check if AGNOS update is required
if [ $(< /VERSION) != "$AGNOS_VERSION" ]; then if [ $(< /VERSION) != "$AGNOS_VERSION" ]; then
AGNOS_PY="$DIR/common/hardware/tici/agnos.py" AGNOS_PY="$DIR/openpilot/common/hardware/tici/agnos.py"
MANIFEST="$DIR/system/hardware/tici/agnos.json" MANIFEST="$DIR/openpilot/system/hardware/tici/agnos.json"
if $AGNOS_PY --verify $MANIFEST; then if $AGNOS_PY --verify $MANIFEST; then
sudo reboot sudo reboot
fi fi
$DIR/common/hardware/tici/updater $AGNOS_PY $MANIFEST $DIR/openpilot/common/hardware/tici/updater $AGNOS_PY $MANIFEST
fi fi
} }
@@ -70,6 +70,14 @@ function launch {
ln -sfn $(pwd) /data/pythonpath ln -sfn $(pwd) /data/pythonpath
export PYTHONPATH="$PWD" export PYTHONPATH="$PWD"
# submodule package symlinks for PYTHONPATH imports on device.
# on PC these come from editable installs via pyproject.toml / uv.
ln -sfn msgq_repo/msgq msgq
ln -sfn opendbc_repo/opendbc opendbc
ln -sfn rednose_repo/rednose rednose
ln -sfn teleoprtc_repo/teleoprtc teleoprtc
ln -sfn tinygrad_repo/tinygrad tinygrad
# hardware specific init # hardware specific init
if [ -f /AGNOS ]; then if [ -f /AGNOS ]; then
agnos_init agnos_init
@@ -79,7 +87,7 @@ function launch {
tmux capture-pane -pq -S-1000 > /tmp/launch_log tmux capture-pane -pq -S-1000 > /tmp/launch_log
# start manager # start manager
cd system/manager cd openpilot/system/manager
if [ ! -f $DIR/prebuilt ]; then if [ ! -f $DIR/prebuilt ]; then
./build.py ./build.py
fi fi
+1 -1
View File
@@ -16,7 +16,7 @@ export VECLIB_MAXIMUM_THREADS=1
export QCOM_PRIORITY=12 export QCOM_PRIORITY=12
if [ -z "$AGNOS_VERSION" ]; then if [ -z "$AGNOS_VERSION" ]; then
export AGNOS_VERSION="18.4" export AGNOS_VERSION="18.5"
fi fi
export STAGING_ROOT="/data/safe_staging" export STAGING_ROOT="/data/safe_staging"
-17
View File
@@ -1,20 +1,3 @@
#!/usr/bin/env bash #!/usr/bin/env bash
set -euo pipefail
IFS=$'\n\t'
# On any failure, run the fallback launcher
trap 'exec ./launch_chffrplus.sh' ERR
C3_LAUNCH_SH="./sunnypilot/system/hardware/c3/launch_chffrplus.sh"
MODEL="$(tr -d '\0' < "/sys/firmware/devicetree/base/model")"
export MODEL
if [ "$MODEL" = "comma tici" ]; then
# Force a failure if the launcher doesn't exist
[ -x "$C3_LAUNCH_SH" ] || false
# If it exists, run it
exec "$C3_LAUNCH_SH"
fi
exec ./launch_chffrplus.sh exec ./launch_chffrplus.sh
-1
View File
@@ -1 +0,0 @@
msgq_repo/msgq
-1
View File
@@ -1 +0,0 @@
opendbc_repo/opendbc
@@ -24,17 +24,17 @@ things are not. Read more details [here](https://capnproto.org/language.html).
### Custom forks ### Custom forks
Forks of [openpilot](https://github.com/commaai/openpilot) might want to add things to the messaging Forks of [openpilot](https://github.com/commaai/openpilot) might want to add things to the messaging
spec, however this could conflict with future changes made in mainline cereal/openpilot. Rebasing against mainline openpilot spec, however this could conflict with future changes made in mainline openpilot's cereal spec. Rebasing against mainline openpilot
then means breaking backwards-compatibility with all old logs of your fork. So we added reserved events in then means breaking backwards-compatibility with all old logs of your fork. So we added reserved events in
[custom.capnp](custom.capnp) that we will leave empty in mainline cereal/openpilot. **If you only modify those, you can ensure your [custom.capnp](custom.capnp) that we will leave empty in mainline openpilot's cereal spec. **If you only modify those, you can ensure your
fork will remain backwards-compatible with all versions of mainline openpilot and your fork.** fork will remain backwards-compatible with all versions of mainline openpilot and your fork.**
An example of compatible changes: An example of compatible changes:
```diff ```diff
diff --git a/cereal/custom.capnp b/cereal/custom.capnp diff --git a/openpilot/cereal/custom.capnp b/openpilot/cereal/custom.capnp
index 3348e859e..3365c7b98 100644 index 3348e859e..3365c7b98 100644
--- a/cereal/custom.capnp --- a/openpilot/cereal/custom.capnp
+++ b/cereal/custom.capnp +++ b/openpilot/cereal/custom.capnp
@@ -10,7 +10,11 @@ $Cxx.namespace("cereal"); @@ -10,7 +10,11 @@ $Cxx.namespace("cereal");
# DO rename the structs # DO rename the structs
# DON'T change the identifier (e.g. @0x81c2f05a394cf4af) # DON'T change the identifier (e.g. @0x81c2f05a394cf4af)
@@ -48,10 +48,10 @@ index 3348e859e..3365c7b98 100644
} }
struct CustomReserved1 @0xaedffd8f31e7b55d { struct CustomReserved1 @0xaedffd8f31e7b55d {
diff --git a/cereal/log.capnp b/cereal/log.capnp diff --git a/openpilot/cereal/log.capnp b/openpilot/cereal/log.capnp
index 1209f3fd9..b189f58b6 100644 index 1209f3fd9..b189f58b6 100644
--- a/cereal/log.capnp --- a/openpilot/cereal/log.capnp
+++ b/cereal/log.capnp +++ b/openpilot/cereal/log.capnp
@@ -2558,14 +2558,14 @@ struct Event { @@ -2558,14 +2558,14 @@ struct Event {
# DO change the name of the field # DO change the name of the field
@@ -76,7 +76,7 @@ index 1209f3fd9..b189f58b6 100644
Example Example
--- ---
```python ```python
import cereal.messaging as messaging import openpilot.cereal.messaging as messaging
# in subscriber # in subscriber
sm = messaging.SubMaster(['sensorEvents']) sm = messaging.SubMaster(['sensorEvents'])
+22
View File
@@ -0,0 +1,22 @@
Import('env', 'common', 'msgq')
cereal_dir = Dir('.')
gen_dir = Dir('gen')
# Build cereal
schema_files = ['log.capnp', 'deprecated.capnp', 'custom.capnp']
car_capnp = '#opendbc_repo/opendbc/car/car.capnp'
all_output = schema_files + ['car.capnp']
env.Command([f'gen/cpp/{s}.c++' for s in all_output] + [f'gen/cpp/{s}.h' for s in all_output],
schema_files + [car_capnp],
f"capnpc --src-prefix={cereal_dir.path} --src-prefix=opendbc_repo/opendbc/car --import-path=opendbc_repo/opendbc/car $SOURCES -o c++:{gen_dir.path}/cpp/")
cereal = env.Library('cereal', [f'gen/cpp/{s}.c++' for s in all_output])
# 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', 'messaging/bridge_zmq.cc'], LIBS=[msgq, common, 'pthread'])
socketmaster = env.Library('socketmaster', ['messaging/socketmaster.cc'])
Export('cereal', 'socketmaster')
+11
View File
@@ -0,0 +1,11 @@
import os
import capnp
from importlib.resources import as_file, files
capnp.remove_import_hook()
with as_file(files("openpilot.cereal")) as fspath, as_file(files("opendbc")) as opendbc_path:
CEREAL_PATH = fspath.as_posix()
opendbc_import_path = os.path.join(os.path.realpath(opendbc_path.as_posix()), 'car')
log = capnp.load(os.path.join(CEREAL_PATH, "log.capnp"), imports=[opendbc_import_path])
custom = capnp.load(os.path.join(CEREAL_PATH, "custom.capnp"), imports=[opendbc_import_path])
@@ -1,4 +1,4 @@
using Cxx = import "./include/c++.capnp"; using Cxx = import "/include/c++.capnp";
$Cxx.namespace("cereal"); $Cxx.namespace("cereal");
@0xb526ba661d550a59; @0xb526ba661d550a59;
@@ -1,4 +1,4 @@
using Cxx = import "./include/c++.capnp"; using Cxx = import "/include/c++.capnp";
$Cxx.namespace("cereal"); $Cxx.namespace("cereal");
@0x80ef1ec4889c2a63; @0x80ef1ec4889c2a63;
+78 -30
View File
@@ -1,7 +1,7 @@
using Cxx = import "./include/c++.capnp"; using Cxx = import "/include/c++.capnp";
$Cxx.namespace("cereal"); $Cxx.namespace("cereal");
using Car = import "car.capnp"; using Car = import "/car.capnp";
using Deprecated = import "deprecated.capnp"; using Deprecated = import "deprecated.capnp";
using Custom = import "custom.capnp"; using Custom = import "custom.capnp";
@@ -132,7 +132,6 @@ struct OnroadEvent @0xc4fa6047f024e718 {
userBookmark @95; userBookmark @95;
excessiveActuation @96; excessiveActuation @96;
audioFeedback @97; audioFeedback @97;
soundsUnavailableDEPRECATED @47; soundsUnavailableDEPRECATED @47;
} }
} }
@@ -414,6 +413,10 @@ struct CanData {
struct DeviceState @0xa4d8b5af2aa492eb { struct DeviceState @0xa4d8b5af2aa492eb {
deviceType @45 :InitData.DeviceType; deviceType @45 :InitData.DeviceType;
# usb
chestnutPresent @51 :Bool;
usbState @52 :UsbState;
networkType @22 :NetworkType; networkType @22 :NetworkType;
networkInfo @31 :NetworkInfo; networkInfo @31 :NetworkInfo;
networkStrength @24 :NetworkStrength; networkStrength @24 :NetworkStrength;
@@ -684,33 +687,47 @@ struct PeripheralState {
} }
} }
struct UsbState {
devices @0 :List(Device);
struct Device {
busnum @0 :UInt8;
devnum @1 :UInt8;
vendorId @2 :UInt16;
productId @3 :UInt16;
speedMbps @4 :UInt16;
manufacturer @6 :Text;
product @5 :Text;
linkErrorCount @7 :UInt16;
}
}
struct RadarState @0x9a185389d6fdd05f { struct RadarState @0x9a185389d6fdd05f {
mdMonoTime @6 :UInt64; mdMonoTime @6 :UInt64; # for debugging
carStateMonoTime @11 :UInt64;
radarErrors @13 :Car.RadarData.Error; radarErrors @13 :Car.RadarData.Error;
leadOne @3 :LeadData; leadOne @3 :LeadData;
leadTwo @4 :LeadData; leadTwo @4 :LeadData;
struct LeadData { struct LeadData {
dRel @0 :Float32; dRel @0 :Float32; # m from the front bumper of the car
yRel @1 :Float32; yRel @1 :Float32; # m in car frame, left positive
vRel @2 :Float32; vRel @2 :Float32; # m/s relative longitudinal speed
aRel @3 :Float32; vLead @4 :Float32; # m/s absolute lead speed
vLead @4 :Float32; vLeadK @8 :Float32; # kalman-filtered lead speed
dPath @6 :Float32; aLeadK @9 :Float32; # kalman-filtered lead accel
vLat @7 :Float32; present @11 :Bool; # true if a lead is present
vLeadK @8 :Float32; aLeadTau @12 :Float32; # lead accel time constant
aLeadK @9 :Float32; modelProb @13 :Float32; # vision model lead probability
fcw @10 :Bool; radar @14 :Bool; # true if lead is radar-matched (vs vision-only)
status @11 :Bool; radarTrackId @15 :Int32 = -1; # for debugging
aLeadTau @12 :Float32;
modelProb @13 :Float32;
radar @14 :Bool;
radarTrackId @15 :Int32 = -1;
deprecated :group { deprecated :group {
aRel @3 :Float32;
aLead @5 :Float32; aLead @5 :Float32;
dPath @6 :Float32;
vLat @7 :Float32;
fcw @10 :Bool;
} }
} }
@@ -723,6 +740,7 @@ struct RadarState @0x9a185389d6fdd05f {
calPerc @9 :Int8; calPerc @9 :Int8;
canMonoTimes @10 :List(UInt64); canMonoTimes @10 :List(UInt64);
cumLagMs @5 :Float32; cumLagMs @5 :Float32;
carStateMonoTime @11 :UInt64;
radarErrors @12 :List(Car.RadarData.ErrorDEPRECATED); radarErrors @12 :List(Car.RadarData.ErrorDEPRECATED);
} }
} }
@@ -771,13 +789,31 @@ struct SelfdriveState {
alertStatus @5 :AlertStatus; alertStatus @5 :AlertStatus;
alertSize @6 :AlertSize; alertSize @6 :AlertSize;
alertType @7 :Text; alertType @7 :Text;
alertSound @8 :Car.CarControl.HUDControl.AudibleAlert; alertSound @13 :AudibleAlert;
alertHudVisual @12 :Car.CarControl.HUDControl.VisualAlert; alertHudVisual @12 :Car.CarControl.HUDControl.VisualAlert;
# configurable driving settings # configurable driving settings
experimentalMode @10 :Bool; experimentalMode @10 :Bool;
personality @11 :LongitudinalPersonality; personality @11 :LongitudinalPersonality;
enum AudibleAlert {
none @0;
engage @1;
disengage @2;
refuse @3;
warningSoft @4;
warningImmediate @5;
prompt @6;
promptRepeat @7;
promptDistracted @8;
preAlert @9;
complete @10;
}
enum OpenpilotState @0xdbe58b96d2d1ac61 { enum OpenpilotState @0xdbe58b96d2d1ac61 {
disabled @0; disabled @0;
preEnabled @1; preEnabled @1;
@@ -798,6 +834,10 @@ struct SelfdriveState {
mid @2; mid @2;
full @3; full @3;
} }
deprecated :group {
alertSound @8 :Car.CarControl.HUDControl.AudibleAlert;
}
} }
struct ControlsState @0x97ff69c53601abf1 { struct ControlsState @0x97ff69c53601abf1 {
@@ -918,7 +958,7 @@ struct ControlsState @0x97ff69c53601abf1 {
alertStatus @38 :SelfdriveState.AlertStatus; alertStatus @38 :SelfdriveState.AlertStatus;
alertSize @39 :SelfdriveState.AlertSize; alertSize @39 :SelfdriveState.AlertSize;
alertType @44 :Text; alertType @44 :Text;
alertSound2 @56 :Car.CarControl.HUDControl.AudibleAlert; alertSound2 @56 :SelfdriveState.AudibleAlert;
engageable @41 :Bool; # can OP be engaged? engageable @41 :Bool; # can OP be engaged?
state @31 :SelfdriveState.OpenpilotState; state @31 :SelfdriveState.OpenpilotState;
enabled @19 :Bool; enabled @19 :Bool;
@@ -1001,7 +1041,6 @@ struct ModelDataV2 {
roadEdgeStds @14 :List(Float32); roadEdgeStds @14 :List(Float32);
# predicted lead cars # predicted lead cars
leads @11 :List(LeadDataV2);
leadsV3 @18 :List(LeadDataV3); leadsV3 @18 :List(LeadDataV3);
meta @12 :MetaData; meta @12 :MetaData;
@@ -1011,8 +1050,9 @@ struct ModelDataV2 {
action @26: Action; action @26: Action;
lateralPlannerSolutionDEPRECATED @25: Deprecated.LateralPlannerSolution; lateralPlannerSolutionDEPRECATED @25: Deprecated.LateralPlannerSolution;
leadsDEPRECATED @11 :List(LeadDataV2DEPRECATED);
struct LeadDataV2 { struct LeadDataV2DEPRECATED {
prob @0 :Float32; # probability that car is your lead at time t prob @0 :Float32; # probability that car is your lead at time t
t @1 :Float32; t @1 :Float32;
@@ -1132,7 +1172,7 @@ struct EncodeIndex {
} }
} }
struct AndroidLogEntry { struct OperatingSystemLogEntry {
id @0 :UInt8; id @0 :UInt8;
ts @1 :UInt64; ts @1 :UInt64;
priority @2 :UInt8; priority @2 :UInt8;
@@ -1270,7 +1310,7 @@ struct LateralPlan @0xe1e9318e2ae8b51e {
struct LiveLocationKalman { struct LiveLocationKalman {
# More info on reference frames: # More info on reference frames:
# https://github.com/commaai/openpilot/tree/master/common/transformations # https://github.com/commaai/openpilot/tree/master/openpilot/common/transformations
positionECEF @0 : Measurement; positionECEF @0 : Measurement;
positionGeodetic @1 : Measurement; positionGeodetic @1 : Measurement;
@@ -1327,7 +1367,7 @@ struct LiveLocationKalman {
struct LivePose { struct LivePose {
# More info on reference frames: # More info on reference frames:
# https://github.com/commaai/openpilot/tree/master/common/transformations # https://github.com/commaai/openpilot/tree/master/openpilot/common/transformations
orientationNED @0 :XYZMeasurement; orientationNED @0 :XYZMeasurement;
velocityDevice @1 :XYZMeasurement; velocityDevice @1 :XYZMeasurement;
accelerationDevice @2 :XYZMeasurement; accelerationDevice @2 :XYZMeasurement;
@@ -2120,8 +2160,11 @@ struct DriverMonitoringStateDEPRECATED @0xb83cda094a1da284 {
struct DriverMonitoringState { struct DriverMonitoringState {
lockout @0 :Bool; lockout @0 :Bool;
alertCountLockoutPercent @1 :Int8; lockoutCount @15 :Int8;
alertTimeLockoutPercent @2 :Int8; lockoutMinutesRemaining @11 :Int8;
alert3Count @12 :Int8;
noResponseCount @13 :Int8;
noResponseForceDecel @14 :Bool;
alwaysOn @3 :Bool; alwaysOn @3 :Bool;
alwaysOnLockout @4 :Bool; alwaysOnLockout @4 :Bool;
@@ -2185,6 +2228,11 @@ struct DriverMonitoringState {
calibratedPercent @0 :Int8; calibratedPercent @0 :Int8;
offset @1 :Float32; offset @1 :Float32;
} }
deprecated :group {
alertCountLockoutPercent @1 :Int8;
alertTimeLockoutPercent @2 :Int8;
}
} }
struct Boot { struct Boot {
@@ -2517,7 +2565,7 @@ struct Event {
rawAudioData @147 :AudioData; rawAudioData @147 :AudioData;
# systems stuff # systems stuff
androidLog @20 :AndroidLogEntry; operatingSystemLog @20 :OperatingSystemLogEntry;
managerState @78 :ManagerState; managerState @78 :ManagerState;
procLog @33 :ProcLog; procLog @33 :ProcLog;
clocks @35 :Clocks; clocks @35 :Clocks;
@@ -7,12 +7,43 @@ import os
import capnp import capnp
import time import time
from typing import Optional, List, Union, Dict from typing import Union
from cereal import log from openpilot.cereal import log
from cereal.services import SERVICE_LIST from openpilot.cereal.services import SERVICE_LIST
from openpilot.common.utils import MovingAverage from openpilot.common.utils import MovingAverage
__all__ = (
"NO_TRAVERSAL_LIMIT",
"Context",
"FrequencyTracker",
"IpcError",
"MultiplePublishersError",
"Poller",
"PubMaster",
"PubSocket",
"SocketEventHandle",
"SubMaster",
"SubSocket",
"delete_fake_prefix",
"drain_sock",
"drain_sock_raw",
"fake_event_handle",
"get_fake_prefix",
"log_from_bytes",
"new_message",
"pub_sock",
"recv_one",
"recv_one_or_none",
"recv_one_retry",
"recv_sock",
"reset_context",
"set_fake_prefix",
"sub_sock",
"toggle_fake_events",
"wait_for_one_event",
)
NO_TRAVERSAL_LIMIT = 2**64-1 NO_TRAVERSAL_LIMIT = 2**64-1
@@ -22,8 +53,8 @@ def pub_sock(endpoint: str) -> PubSocket:
return msgq.pub_sock(endpoint, segment_size) return msgq.pub_sock(endpoint, segment_size)
def sub_sock(endpoint: str, poller: Optional[Poller] = None, addr: str = "127.0.0.1", def sub_sock(endpoint: str, poller: Poller | None = None, addr: str = "127.0.0.1",
conflate: bool = False, timeout: Optional[int] = None) -> SubSocket: conflate: bool = False, timeout: int | None = None) -> SubSocket:
service = SERVICE_LIST.get(endpoint) service = SERVICE_LIST.get(endpoint)
segment_size = service.queue_size if service else 0 segment_size = service.queue_size if service else 0
return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate, return msgq.sub_sock(endpoint, poller=poller, addr=addr, conflate=conflate,
@@ -39,7 +70,7 @@ def log_from_bytes(dat: bytes, struct: capnp.lib.capnp._StructModule = log.Event
return msg return msg
def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder: def new_message(service: str | None, size: int | None = None, **kwargs) -> capnp.lib.capnp._DynamicStructBuilder:
args = { args = {
'valid': False, 'valid': False,
'logMonoTime': int(time.monotonic() * 1e9), 'logMonoTime': int(time.monotonic() * 1e9),
@@ -54,14 +85,14 @@ def new_message(service: Optional[str], size: Optional[int] = None, **kwargs) ->
return dat return dat
def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> List[capnp.lib.capnp._DynamicStructReader]: def drain_sock(sock: SubSocket, wait_for_one: bool = False) -> list[capnp.lib.capnp._DynamicStructReader]:
"""Receive all message currently available on the queue""" """Receive all message currently available on the queue"""
msgs = drain_sock_raw(sock, wait_for_one=wait_for_one) msgs = drain_sock_raw(sock, wait_for_one=wait_for_one)
return [log_from_bytes(m) for m in msgs] return [log_from_bytes(m) for m in msgs]
# TODO: print when we drop packets? # TODO: print when we drop packets?
def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._DynamicStructReader]: def recv_sock(sock: SubSocket, wait: bool = False) -> capnp.lib.capnp._DynamicStructReader | None:
"""Same as drain sock, but only returns latest message. Consider using conflate instead.""" """Same as drain sock, but only returns latest message. Consider using conflate instead."""
dat = None dat = None
@@ -82,14 +113,14 @@ def recv_sock(sock: SubSocket, wait: bool = False) -> Optional[capnp.lib.capnp._
return dat return dat
def recv_one(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: def recv_one(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive() dat = sock.receive()
if dat is not None: if dat is not None:
dat = log_from_bytes(dat) dat = log_from_bytes(dat)
return dat return dat
def recv_one_or_none(sock: SubSocket) -> Optional[capnp.lib.capnp._DynamicStructReader]: def recv_one_or_none(sock: SubSocket) -> capnp.lib.capnp._DynamicStructReader | None:
dat = sock.receive(non_blocking=True) dat = sock.receive(non_blocking=True)
if dat is not None: if dat is not None:
dat = log_from_bytes(dat) dat = log_from_bytes(dat)
@@ -148,27 +179,27 @@ class FrequencyTracker:
class SubMaster: class SubMaster:
def __init__(self, services: List[str], poll: Optional[str] = None, def __init__(self, services: list[str], poll: str | None = None,
ignore_alive: Optional[List[str]] = None, ignore_avg_freq: Optional[List[str]] = None, ignore_alive: list[str] | None = None, ignore_avg_freq: list[str] | None = None,
ignore_valid: Optional[List[str]] = None, addr: str = "127.0.0.1", frequency: Optional[float] = None): ignore_valid: list[str] | None = None, addr: str = "127.0.0.1", frequency: float | None = None):
self.frame = -1 self.frame = -1
self.services = services self.services = services
self.seen = {s: False for s in services} self.seen = dict.fromkeys(services, False)
self.updated = {s: False for s in services} self.updated = dict.fromkeys(services, False)
self.recv_time = {s: 0. for s in services} self.recv_time = dict.fromkeys(services, 0.0)
self.recv_frame = {s: 0 for s in services} self.recv_frame = dict.fromkeys(services, 0)
self.sock = {} self.sock = {}
self.data = {} self.data = {}
self.logMonoTime = {s: 0 for s in services} self.logMonoTime = dict.fromkeys(services, 0)
# zero-frequency / on-demand services are always alive and presumed valid; all others must pass checks # zero-frequency / on-demand services are always alive and presumed valid; all others must pass checks
on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in services} on_demand = {s: SERVICE_LIST[s].frequency <= 1e-5 for s in services}
self.static_freq_services = set(s for s in services if not on_demand[s]) self.static_freq_services = {s for s in services if not on_demand[s]}
self.alive = {s: on_demand[s] for s in services} self.alive = {s: on_demand[s] for s in services}
self.freq_ok = {s: on_demand[s] for s in services} self.freq_ok = {s: on_demand[s] for s in services}
self.valid = {s: on_demand[s] for s in services} self.valid = {s: on_demand[s] for s in services}
self.freq_tracker: Dict[str, FrequencyTracker] = {} self.freq_tracker: dict[str, FrequencyTracker] = {}
self.poller = Poller() self.poller = Poller()
polled_services = set([poll, ] if poll is not None else services) polled_services = set([poll, ] if poll is not None else services)
self.non_polled_services = set(services) - polled_services self.non_polled_services = set(services) - polled_services
@@ -211,7 +242,7 @@ class SubMaster:
msgs.append(recv_one_or_none(self.sock[s])) msgs.append(recv_one_or_none(self.sock[s]))
self.update_msgs(time.monotonic(), msgs) self.update_msgs(time.monotonic(), msgs)
def update_msgs(self, cur_time: float, msgs: List[capnp.lib.capnp._DynamicStructReader]) -> None: def update_msgs(self, cur_time: float, msgs: list[capnp.lib.capnp._DynamicStructReader]) -> None:
self.frame += 1 self.frame += 1
self.updated = dict.fromkeys(self.services, False) self.updated = dict.fromkeys(self.services, False)
for msg in msgs: for msg in msgs:
@@ -234,21 +265,21 @@ class SubMaster:
self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) or (self.seen[s] and self.simulation) self.alive[s] = (cur_time - self.recv_time[s]) < (10. / SERVICE_LIST[s].frequency) or (self.seen[s] and self.simulation)
self.freq_ok[s] = self.freq_tracker[s].valid or self.simulation self.freq_ok[s] = self.freq_tracker[s].valid or self.simulation
def all_alive(self, service_list: Optional[List[str]] = None) -> bool: def all_alive(self, service_list: list[str] | None = None) -> bool:
return all(self.alive[s] for s in (service_list or self.services) if s not in self.ignore_alive) return all(self.alive[s] for s in (service_list or self.services) if s not in self.ignore_alive)
def all_freq_ok(self, service_list: Optional[List[str]] = None) -> bool: def all_freq_ok(self, service_list: list[str] | None = None) -> bool:
return all(self.freq_ok[s] for s in (service_list or self.services) if self._check_avg_freq(s)) return all(self.freq_ok[s] for s in (service_list or self.services) if self._check_avg_freq(s))
def all_valid(self, service_list: Optional[List[str]] = None) -> bool: def all_valid(self, service_list: list[str] | None = None) -> bool:
return all(self.valid[s] for s in (service_list or self.services) if s not in self.ignore_valid) return all(self.valid[s] for s in (service_list or self.services) if s not in self.ignore_valid)
def all_checks(self, service_list: Optional[List[str]] = None) -> bool: def all_checks(self, service_list: list[str] | None = None) -> bool:
return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list) return self.all_alive(service_list) and self.all_freq_ok(service_list) and self.all_valid(service_list)
class PubMaster: class PubMaster:
def __init__(self, services: List[str]): def __init__(self, services: list[str]):
self.sock = {} self.sock = {}
for s in services: for s in services:
self.sock[s] = pub_sock(s) self.sock[s] = pub_sock(s)
@@ -1,7 +1,7 @@
#include <cassert> #include <cassert>
#include "cereal/messaging/msgq_to_zmq.h" #include "openpilot/cereal/messaging/msgq_to_zmq.h"
#include "cereal/services.h" #include "openpilot/cereal/services.h"
#include "common/util.h" #include "common/util.h"
ExitHandler do_exit; ExitHandler do_exit;
@@ -1,4 +1,4 @@
#include "cereal/messaging/bridge_zmq.h" #include "openpilot/cereal/messaging/bridge_zmq.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
@@ -8,7 +8,7 @@
#include <capnp/serialize.h> #include <capnp/serialize.h>
#include "cereal/gen/cpp/log.capnp.h" #include "openpilot/cereal/gen/cpp/log.capnp.h"
#include "common/timing.h" #include "common/timing.h"
#include "msgq/ipc.h" #include "msgq/ipc.h"
@@ -1,8 +1,8 @@
#include "cereal/messaging/msgq_to_zmq.h" #include "openpilot/cereal/messaging/msgq_to_zmq.h"
#include <cassert> #include <cassert>
#include "cereal/services.h" #include "openpilot/cereal/services.h"
#include "common/util.h" #include "common/util.h"
extern ExitHandler do_exit; extern ExitHandler do_exit;
@@ -8,7 +8,7 @@
#include <vector> #include <vector>
#include "msgq/impl_msgq.h" #include "msgq/impl_msgq.h"
#include "cereal/messaging/bridge_zmq.h" #include "openpilot/cereal/messaging/bridge_zmq.h"
class MsgqToZmq { class MsgqToZmq {
public: public:
@@ -3,8 +3,8 @@
#include <string> #include <string>
#include <mutex> #include <mutex>
#include "cereal/services.h" #include "openpilot/cereal/services.h"
#include "cereal/messaging/messaging.h" #include "openpilot/cereal/messaging/messaging.h"
const bool SIMULATION = (getenv("SIMULATION") != nullptr) && (std::string(getenv("SIMULATION")) == "1"); const bool SIMULATION = (getenv("SIMULATION") != nullptr) && (std::string(getenv("SIMULATION")) == "1");
@@ -1,4 +1,3 @@
import os
import capnp import capnp
import multiprocessing import multiprocessing
import numbers import numbers
@@ -6,11 +5,11 @@ import random
import threading import threading
import time import time
from openpilot.common.parameterized import parameterized from openpilot.common.parameterized import parameterized
import pytest
from cereal import log, car from openpilot.cereal import log
import cereal.messaging as messaging from opendbc.car.structs import car
from cereal.services import SERVICE_LIST import openpilot.cereal.messaging as messaging
from openpilot.cereal.services import SERVICE_LIST
events = [evt for evt in log.Event.schema.union_fields if evt in SERVICE_LIST.keys()] events = [evt for evt in log.Event.schema.union_fields if evt in SERVICE_LIST.keys()]
@@ -23,10 +22,6 @@ def random_socks(num_socks=10):
def random_bytes(length=1000): def random_bytes(length=1000):
return bytes([random.randrange(0xFF) for _ in range(length)]) return bytes([random.randrange(0xFF) for _ in range(length)])
def zmq_sleep(t=1):
if "ZMQ" in os.environ:
time.sleep(t)
# TODO: this should take any capnp struct and returrn a msg with random populated data # TODO: this should take any capnp struct and returrn a msg with random populated data
def random_carstate(): def random_carstate():
@@ -52,16 +47,6 @@ def delayed_send(delay, sock, dat):
class TestMessaging: class TestMessaging:
def setUp(self):
# TODO: ZMQ tests are too slow; all sleeps will need to be
# replaced with logic to block on the necessary condition
if "ZMQ" in os.environ:
pytest.skip()
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep()
@parameterized.expand(events) @parameterized.expand(events)
def test_new_message(self, evt): def test_new_message(self, evt):
try: try:
@@ -88,7 +73,6 @@ class TestMessaging:
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=1000) sub_sock = messaging.sub_sock(sock, timeout=1000)
zmq_sleep()
# no wait and no msgs in queue # no wait and no msgs in queue
msgs = func(sub_sock) msgs = func(sub_sock)
@@ -109,7 +93,6 @@ class TestMessaging:
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=100) sub_sock = messaging.sub_sock(sock, timeout=100)
zmq_sleep()
# no wait and no msg in queue, socket should timeout # no wait and no msg in queue, socket should timeout
recvd = messaging.recv_sock(sub_sock) recvd = messaging.recv_sock(sub_sock)
@@ -128,7 +111,6 @@ class TestMessaging:
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=1000) sub_sock = messaging.sub_sock(sock, timeout=1000)
zmq_sleep()
# no msg in queue, socket should timeout # no msg in queue, socket should timeout
recvd = messaging.recv_one(sub_sock) recvd = messaging.recv_one(sub_sock)
@@ -141,12 +123,10 @@ class TestMessaging:
assert isinstance(recvd, capnp._DynamicStructReader) assert isinstance(recvd, capnp._DynamicStructReader)
assert_carstate(msg.carState, recvd.carState) assert_carstate(msg.carState, recvd.carState)
@pytest.mark.xfail(condition="ZMQ" in os.environ, reason='ZMQ detected')
def test_recv_one_or_none(self): def test_recv_one_or_none(self):
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock) sub_sock = messaging.sub_sock(sock)
zmq_sleep()
# no msg in queue, socket shouldn't block # no msg in queue, socket shouldn't block
recvd = messaging.recv_one_or_none(sub_sock) recvd = messaging.recv_one_or_none(sub_sock)
@@ -164,16 +144,13 @@ class TestMessaging:
sock_timeout = 0.1 sock_timeout = 0.1
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000)) sub_sock = messaging.sub_sock(sock, timeout=round(sock_timeout*1000))
zmq_sleep()
# this test doesn't work with ZMQ since multiprocessing interrupts it # wait 5 socket timeouts and make sure it's still retrying
if "ZMQ" not in os.environ: p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,))
# wait 5 socket timeouts and make sure it's still retrying p.start()
p = multiprocessing.Process(target=messaging.recv_one_retry, args=(sub_sock,)) time.sleep(sock_timeout*5)
p.start() assert p.is_alive()
time.sleep(sock_timeout*5) p.terminate()
assert p.is_alive()
p.terminate()
# wait 5 socket timeouts before sending # wait 5 socket timeouts before sending
msg = random_carstate() msg = random_carstate()
@@ -1,21 +1,16 @@
import random import random
import time import time
from typing import Sized, cast from typing import cast
from collections.abc import Sized
import cereal.messaging as messaging import openpilot.cereal.messaging as messaging
from cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \ from openpilot.cereal.messaging.tests.test_messaging import events, random_sock, random_socks, \
random_bytes, random_carstate, assert_carstate, \ random_bytes, random_carstate, assert_carstate
zmq_sleep from openpilot.cereal.services import SERVICE_LIST
from cereal.services import SERVICE_LIST
class TestSubMaster: class TestSubMaster:
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
def test_init(self): def test_init(self):
sm = messaging.SubMaster(events) sm = messaging.SubMaster(events)
for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive, for p in [sm.updated, sm.recv_time, sm.recv_frame, sm.alive,
@@ -42,7 +37,6 @@ class TestSubMaster:
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sm = messaging.SubMaster([sock,]) sm = messaging.SubMaster([sock,])
zmq_sleep()
msg = random_carstate() msg = random_carstate()
pub_sock.send(msg.to_bytes()) pub_sock.send(msg.to_bytes())
@@ -54,7 +48,6 @@ class TestSubMaster:
sock = "carState" sock = "carState"
pub_sock = messaging.pub_sock(sock) pub_sock = messaging.pub_sock(sock)
sm = messaging.SubMaster([sock,]) sm = messaging.SubMaster([sock,])
zmq_sleep()
for i in range(10): for i in range(10):
msg = messaging.new_message(sock) msg = messaging.new_message(sock)
@@ -91,21 +84,13 @@ class TestSubMaster:
for service, (max_freq, min_freq) in checks.items(): for service, (max_freq, min_freq) in checks.items():
if max_freq is not None: if max_freq is not None:
assert min_freq is not None
assert sm._check_avg_freq(service) assert sm._check_avg_freq(service)
assert sm.freq_tracker[service].max_freq == max_freq*1.2 assert sm.freq_tracker[service].max_freq == max_freq*1.2
assert sm.freq_tracker[service].min_freq == min_freq*0.8 assert sm.freq_tracker[service].min_freq == min_freq*0.8
else: else:
assert not sm._check_avg_freq(service) assert not sm._check_avg_freq(service)
def test_alive(self):
pass
def test_ignore_alive(self):
pass
def test_valid(self):
pass
# SubMaster should always conflate # SubMaster should always conflate
def test_conflate(self): def test_conflate(self):
sock = "carState" sock = "carState"
@@ -124,11 +109,6 @@ class TestSubMaster:
class TestPubMaster: class TestPubMaster:
def setup_method(self):
# ZMQ pub socket takes too long to die
# sleep to prevent multiple publishers error between tests
zmq_sleep(3)
def test_init(self): def test_init(self):
messaging.PubMaster(events) messaging.PubMaster(events)
@@ -136,7 +116,6 @@ class TestPubMaster:
socks = random_socks() socks = random_socks()
pm = messaging.PubMaster(socks) pm = messaging.PubMaster(socks)
sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks} sub_socks = {s: messaging.sub_sock(s, conflate=True, timeout=1000) for s in socks}
zmq_sleep()
# PubMaster accepts either a capnp msg builder or bytes # PubMaster accepts either a capnp msg builder or bytes
for capnp in [True, False]: for capnp in [True, False]:
@@ -1,10 +1,10 @@
import os import subprocess
import tempfile import tempfile
from typing import Dict
from openpilot.common.parameterized import parameterized from openpilot.common.parameterized import parameterized
import cereal.services as services import openpilot.cereal.services as services
from cereal.services import SERVICE_LIST from openpilot.cereal.services import SERVICE_LIST
class TestServices: class TestServices:
@@ -17,5 +17,5 @@ class TestServices:
def test_generated_header(self): def test_generated_header(self):
with tempfile.NamedTemporaryFile(suffix=".h") as f: with tempfile.NamedTemporaryFile(suffix=".h") as f:
ret = os.system(f"python3 {services.__file__} > {f.name} && clang++ {f.name} -std=c++11") ret = subprocess.run(f"python3 {services.__file__} > {f.name} && clang++ {f.name} -std=c++11", shell=True).returncode
assert ret == 0, "generated services header is not valid C" assert ret == 0, "generated services header is not valid C"
@@ -1,6 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
from enum import IntEnum from enum import IntEnum
from typing import Optional
# TODO: this should be automatically determined using the capnp schema # TODO: this should be automatically determined using the capnp schema
@@ -11,7 +10,7 @@ class QueueSize(IntEnum):
class Service: class Service:
def __init__(self, should_log: bool, frequency: float, decimation: Optional[int] = None, def __init__(self, should_log: bool, frequency: float, decimation: int | None = None,
queue_size: QueueSize = QueueSize.SMALL): queue_size: QueueSize = QueueSize.SMALL):
self.should_log = should_log self.should_log = should_log
self.frequency = frequency self.frequency = frequency
@@ -41,7 +40,7 @@ _services: dict[str, tuple] = {
"liveCalibration": (True, 4., 4), "liveCalibration": (True, 4., 4),
"liveTorqueParameters": (True, 4., 1), "liveTorqueParameters": (True, 4., 1),
"liveDelay": (True, 4., 1), "liveDelay": (True, 4., 1),
"androidLog": (True, 0.), "operatingSystemLog": (True, 0.),
"carState": (True, 100., 10), "carState": (True, 100., 10),
"carControl": (True, 100., 10), "carControl": (True, 100., 10),
"carOutput": (True, 100., 10), "carOutput": (True, 100., 10),
@@ -125,8 +124,7 @@ def build_header():
for k, v in SERVICE_LIST.items(): for k, v in SERVICE_LIST.items():
should_log = "true" if v.should_log else "false" should_log = "true" if v.should_log else "false"
decimation = -1 if v.decimation is None else v.decimation decimation = -1 if v.decimation is None else v.decimation
h += ' { "%s", {"%s", %s, %f, %d, %d}},\n' % \ h += f' {{ "{k}", {{"{k}", {should_log}, {v.frequency:f}, {decimation:d}, {v.queue_size:d}}}}},\n'
(k, k, should_log, v.frequency, decimation, v.queue_size)
h += "};\n" h += "};\n"
h += "#endif\n" h += "#endif\n"
-1
View File
@@ -1 +0,0 @@
../common
@@ -5,6 +5,7 @@ common_libs = [
'swaglog.cc', 'swaglog.cc',
'util.cc', 'util.cc',
'ratekeeper.cc', 'ratekeeper.cc',
'yuv.cc',
] ]
_common = env.Library('common', common_libs, LIBS="json11") _common = env.Library('common', common_libs, LIBS="json11")
@@ -12,7 +13,7 @@ Export('_common')
if GetOption('extras'): if GetOption('extras'):
env.Program('tests/test_common', env.Program('tests/test_common',
['tests/test_runner.cc', 'tests/test_params.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'], ['tests/test_runner.cc', 'tests/test_util.cc', 'tests/test_swaglog.cc'],
LIBS=[_common, 'json11', 'zmq', 'pthread']) LIBS=[_common, 'json11', 'zmq', 'pthread'])
# Cython bindings # Cython bindings
@@ -4,7 +4,7 @@ import requests
import unicodedata import unicodedata
from datetime import datetime, timedelta, UTC from datetime import datetime, timedelta, UTC
from openpilot.common.hardware.hw import Paths from openpilot.common.hardware.hw import Paths
from openpilot.system.version import get_version from openpilot.common.version import get_version
# name: jwt signature algorithm # name: jwt signature algorithm
KEYS = {"id_rsa": "RS256", KEYS = {"id_rsa": "RS256",
@@ -38,6 +38,7 @@ class BaseApi:
} }
if payload_extra is not None: if payload_extra is not None:
payload.update(payload_extra) payload.update(payload_extra)
assert self.private_key is not None
token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm) token = jwt.encode(payload, self.private_key, algorithm=self.jwt_algorithm)
if isinstance(token, bytes): if isinstance(token, bytes):
token = token.decode('utf8') token = token.decode('utf8')
@@ -1,4 +1,4 @@
import os import os
BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")) BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../.."))
@@ -6,7 +6,6 @@ import fcntl
import hashlib import hashlib
import os import os
import requests import requests
import serial
import subprocess import subprocess
import sys import sys
import termios import termios
@@ -20,6 +19,7 @@ from pathlib import Path
from openpilot.common.time_helpers import system_time_valid from openpilot.common.time_helpers import system_time_valid
from openpilot.common.esim.base import LPABase, LPAError, LPAProfileNotFoundError, Profile from openpilot.common.esim.base import LPABase, LPAError, LPAProfileNotFoundError, Profile
from openpilot.common.serial import Serial, SerialException
GSMA_CI_BUNDLE = str(Path(__file__).parent / "gsma_ci_bundle.pem") GSMA_CI_BUNDLE = str(Path(__file__).parent / "gsma_ci_bundle.pem")
@@ -133,7 +133,7 @@ class AtClient:
self._device = device self._device = device
self._baud = baud self._baud = baud
self._timeout = timeout self._timeout = timeout
self._serial: serial.Serial | None = None self._serial: Serial | None = None
def send_raw(self, data: bytes) -> None: def send_raw(self, data: bytes) -> None:
self._ensure_serial() self._ensure_serial()
@@ -185,14 +185,14 @@ class AtClient:
pass pass
self._serial = None self._serial = None
if self._serial is None: if self._serial is None:
self._serial = serial.Serial(self._device, baudrate=self._baud, timeout=self._timeout) self._serial = Serial(self._device, baudrate=self._baud, timeout=self._timeout)
def query(self, cmd: str) -> list[str]: def query(self, cmd: str) -> list[str]:
self._ensure_serial() self._ensure_serial()
try: try:
self._send(cmd) self._send(cmd)
return self._expect() return self._expect()
except serial.SerialException: except SerialException:
self._ensure_serial(reconnect=True) self._ensure_serial(reconnect=True)
self._send(cmd) self._send(cmd)
return self._expect() return self._expect()
@@ -208,7 +208,7 @@ class AtClient:
if self._serial: if self._serial:
try: try:
self._serial.reset_input_buffer() self._serial.reset_input_buffer()
except (OSError, serial.SerialException, termios.error): except (OSError, SerialException, termios.error):
self._ensure_serial(reconnect=True) self._ensure_serial(reconnect=True)
for line in self.query(f'AT+CCHO="{ISDR_AID}"'): for line in self.query(f'AT+CCHO="{ISDR_AID}"'):
if line.startswith("+CCHO:") and (ch := line.split(":", 1)[1].strip()): if line.startswith("+CCHO:") and (ch := line.split(":", 1)[1].strip()):
@@ -230,7 +230,7 @@ class AtClient:
try: try:
self._open_isdr_once() self._open_isdr_once()
return return
except (RuntimeError, TimeoutError, termios.error, serial.SerialException): except (RuntimeError, TimeoutError, termios.error, SerialException):
time.sleep(OPEN_ISDR_RETRY_DELAY_S) time.sleep(OPEN_ISDR_RETRY_DELAY_S)
if attempt == OPEN_ISDR_RESET_ATTEMPT: if attempt == OPEN_ISDR_RESET_ATTEMPT:
self._reset_modem() self._reset_modem()
@@ -1,4 +1,5 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import io
import sys import sys
import math import math
import os import os
@@ -21,13 +22,12 @@ def get_chunk_targets(path, file_size):
def chunk_file(path, targets): def chunk_file(path, targets):
manifest_path, *chunk_paths = targets manifest_path, *chunk_paths = targets
with open(path, 'rb') as f: actual_num_chunks = max(1, math.ceil(os.path.getsize(path) / CHUNK_SIZE))
data = f.read()
actual_num_chunks = max(1, math.ceil(len(data) / CHUNK_SIZE))
assert len(chunk_paths) >= actual_num_chunks, f"Allowed {len(chunk_paths)} chunks but needs at least {actual_num_chunks}, for path {path}" assert len(chunk_paths) >= actual_num_chunks, f"Allowed {len(chunk_paths)} chunks but needs at least {actual_num_chunks}, for path {path}"
for i, chunk_path in enumerate(chunk_paths): with open(path, 'rb') as f:
with open(chunk_path, 'wb') as f: for chunk_path in chunk_paths:
f.write(data[i * CHUNK_SIZE:(i + 1) * CHUNK_SIZE]) with open(chunk_path, 'wb') as out:
out.write(f.read(CHUNK_SIZE))
Path(manifest_path).write_text(str(len(chunk_paths))) Path(manifest_path).write_text(str(len(chunk_paths)))
os.remove(path) os.remove(path)
@@ -39,14 +39,41 @@ def get_existing_chunks(path):
return _chunk_paths(path, num_chunks) return _chunk_paths(path, num_chunks)
raise FileNotFoundError(path) raise FileNotFoundError(path)
def read_file_chunked(path): class ChunkStream(io.RawIOBase):
def __init__(self, paths):
self._paths = iter(paths)
self._f = None
def readable(self):
return True
def readinto(self, b):
n = 0
view = memoryview(b)
while n < len(b):
if self._f is None:
p = next(self._paths, None)
if p is None:
break
self._f = open(p, 'rb')
count = self._f.readinto(view[n:])
if not count:
self._f.close()
self._f = None
continue
n += count
return n
def open_file_chunked(path):
manifest_path = get_manifest_path(path) manifest_path = get_manifest_path(path)
if os.path.isfile(manifest_path): if os.path.isfile(manifest_path):
num_chunks = int(Path(manifest_path).read_text().strip()) num_chunks = int(Path(manifest_path).read_text().strip())
return b''.join(Path(get_chunk_name(path, i, num_chunks)).read_bytes() for i in range(num_chunks)) paths = [get_chunk_name(path, i, num_chunks) for i in range(num_chunks)]
if os.path.isfile(path): elif os.path.isfile(path):
return Path(path).read_bytes() paths = [path]
raise FileNotFoundError(path) else:
raise FileNotFoundError(path)
return io.BufferedReader(ChunkStream(paths))
if __name__ == "__main__": if __name__ == "__main__":
@@ -5,7 +5,7 @@
#include <map> #include <map>
#include <string> #include <string>
#include "cereal/gen/cpp/log.capnp.h" #include "openpilot/cereal/gen/cpp/log.capnp.h"
// no-op base hw class // no-op base hw class
class HardwareNone { class HardwareNone {
@@ -2,7 +2,7 @@ import os
from abc import abstractmethod, ABC from abc import abstractmethod, ABC
from dataclasses import dataclass, fields from dataclasses import dataclass, fields
from cereal import log from openpilot.cereal import log
from openpilot.common.esim.base import LPABase from openpilot.common.esim.base import LPABase
NetworkType = log.DeviceState.NetworkType NetworkType = log.DeviceState.NetworkType
@@ -1,4 +1,4 @@
from cereal import log from openpilot.cereal import log
from openpilot.common.hardware.base import HardwareBase from openpilot.common.hardware.base import HardwareBase
class Pc(HardwareBase): class Pc(HardwareBase):
@@ -56,28 +56,28 @@
}, },
{ {
"name": "boot", "name": "boot",
"url": "https://commadist.azureedge.net/agnosupdate/boot-8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8.img.xz", "url": "https://commadist.azureedge.net/agnosupdate/boot-19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39.img.xz",
"hash": "8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8", "hash": "19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39",
"hash_raw": "8806802b195a5b1396a3ae8dd92a8b7711dc522f6aceafd820e871bae5c8a6d8", "hash_raw": "19ff57b68e219e4503fcaca716967098d5d0a1de8af833f04dbf13b99aeb4d39",
"size": 17487872, "size": 17487872,
"sparse": false, "sparse": false,
"full_check": true, "full_check": true,
"has_ab": true, "has_ab": true,
"ondevice_hash": "edca8bee1531e66953d107eeceeed2dc7b3ca46417e49d55508f94e58bf95db8" "ondevice_hash": "ddfe93cc6a8531af92ee331d9bbaeae2f1d933bdb38e579769dc9fe7998eb626"
}, },
{ {
"name": "system", "name": "system",
"url": "https://commadist.azureedge.net/agnosupdate/system-ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f.img.xz", "url": "https://commadist.azureedge.net/agnosupdate/system-a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724.img.xz",
"hash": "78acfe16a7b62a3a91fc7a81f40a693e4468cec1c69df7d0b1e550aacc646113", "hash": "4dc41c2c072f5f5d5cd484cd6173049cd96acfb9a67bc20049775585fe881539",
"hash_raw": "ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f", "hash_raw": "a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724",
"size": 4718592000, "size": 4718592000,
"sparse": true, "sparse": true,
"full_check": false, "full_check": false,
"has_ab": true, "has_ab": true,
"ondevice_hash": "743142c5a898f27b2a1029cca42c8a5d5d1fc0096414422b850fe84c8d0b8342", "ondevice_hash": "cf1229630b7a2b8497705bca4ba947dbf0c217418ff4febff571aa4f4a878134",
"alt": { "alt": {
"hash": "ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f", "hash": "a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724",
"url": "https://commadist.azureedge.net/agnosupdate/system-ef0d879302cb29e72110e9c8d3f947c830fd7d37c8192744fc9dbea1af78501f.img", "url": "https://commadist.azureedge.net/agnosupdate/system-a396dd98ffd49614fb198d1b022a0c7a6d0a1e563c20ce11b0a975105ab50724.img",
"size": 4718592000 "size": 4718592000
} }
} }
@@ -12,14 +12,14 @@ import requests
SPARSE_CHUNK_FMT = struct.Struct('H2xI4x') SPARSE_CHUNK_FMT = struct.Struct('H2xI4x')
AGNOS_MANIFEST_FILE = "system/hardware/tici/agnos.json" AGNOS_MANIFEST_FILE = "openpilot/system/hardware/tici/agnos.json"
class StreamingDecompressor: class StreamingDecompressor:
def __init__(self, url: str) -> None: def __init__(self, url: str) -> None:
self.buf = b"" self.buf = b""
self.req = requests.get(url, stream=True, headers={'Accept-Encoding': None}, timeout=60) self.req = requests.get(url, stream=True, headers={'Accept-Encoding': 'identity'}, timeout=60)
self.it = self.req.iter_content(chunk_size=1024 * 1024) self.it = self.req.iter_content(chunk_size=1024 * 1024)
self.decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO) self.decompressor = lzma.LZMADecompressor(format=lzma.FORMAT_AUTO)
self.eof = False self.eof = False
@@ -228,7 +228,7 @@ def flash_agnos_update(manifest_path: str, target_slot_number: int, cloudlog, st
cloudlog.info(f"Target slot {target_slot_number}") cloudlog.info(f"Target slot {target_slot_number}")
# set target slot as unbootable # set target slot as unbootable
os.system(f"abctl --set_unbootable {target_slot_number}") subprocess.run(f"abctl --set_unbootable {target_slot_number}", shell=True)
for partition in update: for partition in update:
success = False success = False
@@ -7,7 +7,7 @@ import time
from functools import cached_property, lru_cache from functools import cached_property, lru_cache
from pathlib import Path from pathlib import Path
from cereal import log from openpilot.cereal import log
from openpilot.common.utils import sudo_read, sudo_write from openpilot.common.utils import sudo_read, sudo_write
from openpilot.common.gpio import gpio_set, gpio_init, get_irqs_for_action from openpilot.common.gpio import gpio_set, gpio_init, get_irqs_for_action
from openpilot.common.esim.base import LPABase from openpilot.common.esim.base import LPABase
@@ -241,7 +241,7 @@ class Tici(HardwareBase):
return (self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) * self.read_param_file("/sys/class/power_supply/bms/current_now", int) / 1e12) return (self.read_param_file("/sys/class/power_supply/bms/voltage_now", int) * self.read_param_file("/sys/class/power_supply/bms/current_now", int) / 1e12)
def shutdown(self): def shutdown(self):
os.system("sudo poweroff") subprocess.run("sudo poweroff", shell=True)
def get_thermal_config(self): def get_thermal_config(self):
intake, exhaust, gnss, bottomSoc = None, None, None, None intake, exhaust, gnss, bottomSoc = None, None, None, None
@@ -335,11 +335,11 @@ class Tici(HardwareBase):
self.amplifier.initialize_configuration() self.amplifier.initialize_configuration()
# Allow hardwared to write engagement status to kmsg # Allow hardwared to write engagement status to kmsg
os.system("sudo chmod a+w /dev/kmsg") subprocess.run("sudo chmod a+w /dev/kmsg", shell=True)
# Ensure fan gpio is enabled so fan runs until shutdown, also turned on at boot by the ABL # Ensure fan gpio is enabled so fan runs until shutdown, also turned on at boot by the ABL
gpio_init(GPIO.SOM_ST_IO, True) gpio_init(GPIO.SOM_ST_IO, True)
gpio_set(GPIO.SOM_ST_IO, 1) gpio_set(GPIO.SOM_ST_IO, True)
# *** IRQ config *** # *** IRQ config ***
@@ -389,21 +389,21 @@ class Tici(HardwareBase):
gpio_init(GPIO.STM_RST_N, True) gpio_init(GPIO.STM_RST_N, True)
gpio_init(GPIO.STM_BOOT0, True) gpio_init(GPIO.STM_BOOT0, True)
gpio_set(GPIO.STM_RST_N, 1) gpio_set(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_BOOT0, 0) gpio_set(GPIO.STM_BOOT0, False)
time.sleep(0.01) time.sleep(0.01)
gpio_set(GPIO.STM_RST_N, 0) gpio_set(GPIO.STM_RST_N, False)
def recover_internal_panda(self): def recover_internal_panda(self):
gpio_init(GPIO.STM_RST_N, True) gpio_init(GPIO.STM_RST_N, True)
gpio_init(GPIO.STM_BOOT0, True) gpio_init(GPIO.STM_BOOT0, True)
gpio_set(GPIO.STM_RST_N, 1) gpio_set(GPIO.STM_RST_N, True)
gpio_set(GPIO.STM_BOOT0, 1) gpio_set(GPIO.STM_BOOT0, True)
time.sleep(0.01) time.sleep(0.01)
gpio_set(GPIO.STM_RST_N, 0) gpio_set(GPIO.STM_RST_N, False)
time.sleep(0.01) time.sleep(0.01)
gpio_set(GPIO.STM_BOOT0, 0) gpio_set(GPIO.STM_BOOT0, False)
def booted(self): def booted(self):
# this normally boots within 8s, but on rare occasions takes 30+s # this normally boots within 8s, but on rare occasions takes 30+s
@@ -3,7 +3,6 @@ import fcntl
import json import json
import logging import logging
import os import os
import serial
import signal import signal
import subprocess import subprocess
import tempfile import tempfile
@@ -13,6 +12,8 @@ from ipaddress import IPv4Address, AddressValueError
from enum import Enum from enum import Enum
from openpilot.common.serial import Serial
logging.basicConfig( logging.basicConfig(
level=logging.INFO, level=logging.INFO,
format="%(asctime)s.%(msecs)03d %(levelname)-7s modem: %(message)s", format="%(asctime)s.%(msecs)03d %(levelname)-7s modem: %(message)s",
@@ -51,7 +52,7 @@ PPPD_CMD = [
"novj", "novjccomp", "ipcp-accept-local", "ipcp-accept-remote", "nomagic", "novj", "novjccomp", "ipcp-accept-local", "ipcp-accept-remote", "nomagic",
"user", '""', "password", '""', "user", '""', "password", '""',
] ]
INITIAL_STATE = { INITIAL_STATE: dict[str, object] = {
"seconds_since_boot": 0, "seconds_since_boot": 0,
"state": "INITIALIZING", "state": "INITIALIZING",
"connected": False, "ip_address": "", "connected": False, "ip_address": "",
@@ -96,7 +97,7 @@ class PPPSession:
def reset_data_port(): def reset_data_port():
"""Drop DTR on PPP_PORT so the modem terminates any stuck PPP session.""" """Drop DTR on PPP_PORT so the modem terminates any stuck PPP session."""
try: try:
with serial.Serial(PPP_PORT, 460800, timeout=1) as s: with Serial(PPP_PORT, baudrate=460800, timeout=1) as s:
s.dtr = False s.dtr = False
time.sleep(0.2) time.sleep(0.2)
s.dtr = True s.dtr = True
@@ -220,7 +221,7 @@ class Modem:
os.close(fd) os.close(fd)
return [] return []
try: try:
with serial.Serial(AT_PORT, 9600, timeout=5) as ser: with Serial(AT_PORT, baudrate=9600, timeout=5) as ser:
ser.reset_input_buffer() ser.reset_input_buffer()
ser.write((cmd + "\r").encode()) ser.write((cmd + "\r").encode())
lines = [] lines = []
@@ -505,7 +506,11 @@ class Modem:
except (AddressValueError, ValueError): except (AddressValueError, ValueError):
pass pass
if not dns_servers: if not dns_servers:
logging.warning(f"no cellular DNS servers reported by modem: {v!r}") dns_servers = [
"8.8.8.8", # Google
"1.1.1.1", # Cloudflare
]
logging.warning(f"no cellular DNS servers reported by modem: {v!r}; using fallback {dns_servers}")
return dns_servers return dns_servers
def _poll_byte_counters(self) -> dict: def _poll_byte_counters(self) -> dict:

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