Compare commits

...

386 Commits

Author SHA1 Message Date
dragonpilot 0e17475449 Merge branch 'devel-en' into devel-zhs 2020-02-14 11:24:14 +10:00
dragonpilot 9ca8f9a047 Merge pull request #10 from dragonpilot-community/devel
dp 0.7.2 bug fixes
2020-02-14 11:19:18 +10:00
dragonpilot 89dfdd961f Merge branch 'devel' of https://github.com/commaai/openpilot into devel 2020-02-14 11:13:29 +10:00
dragonpilot 9a7dbd0201 DragonCachedSource does not use utf8 2020-02-14 11:13:07 +10:00
Willem Melching d25c617595 Add Corolla Hybrid TSS2 eps firmware version 2020-02-11 13:55:47 -08:00
Willem Melching b5807aab22 Add engine FW version for Camry Hybrid 2020-02-11 13:54:11 -08:00
dragonpilot d04f4ffa31 force git command to run in /data/openpilot/ 2020-02-11 17:08:15 +10:00
dragonpilot 3e2a9e8136 * delete ish dbc
* car_helpers to catch EOFError exception
* dashcam to catch OSError exception
* dragonconf default to stock settings
2020-02-11 12:12:41 +10:00
ZwX1616 7827a7cdba fix not resetting on interaction (#1063) 2020-02-08 11:22:21 -08:00
dragonpilot c8a01c5248 remove removed alerts 2020-02-08 13:42:57 +10:00
dragonpilot 83be042013 fix up translation 2020-02-08 13:37:33 +10:00
dragonpilot 8dd8d7e33e Merge branch 'devel-en' into devel-zhs 2020-02-08 13:27:01 +10:00
dragonpilot e594bd740e Merge pull request #9 from dragonpilot-community/devel
dp 0.7.2
2020-02-08 13:18:47 +10:00
dragonpilot 5cd69cb553 Merge branch 'devel-staging' of https://github.com/commaai/openpilot into devel 2020-02-07 12:30:47 +10:00
dragonpilot e1380aa34a Merge branch 'devel' of https://github.com/dragonpilot-community/dragonpilot into devel 2020-02-07 11:54:45 +10:00
dragonpilot fb1a9ca010 dp v0.7.2 init update
* migrate to v0.7.2
* increase mini dev bar font size
* update APKs
   * system APKs updated to v0.7.2
   * autonavi updated to v4.5.0.600053
* use old updated
* Add missing auto start Aegis app option.
2020-02-07 11:42:48 +10:00
Vehicle Researcher 21f4245444 openpilot v0.7.2 release 2020-02-06 13:51:42 -08:00
Vehicle Researcher 305037fc1a Merge opendbc subtree 2020-02-06 13:51:38 -08:00
Vehicle Researcher 69df34bf0f Squashed 'opendbc/' changes from 5081966f..d68f8ff0
d68f8ff0 Clean up .gitignore
e82757b9 Add Lexus NX300H (#214)
745a2bb0 Removed non high voltage items. Added units.
fafd091a Added High Voltage Management to powertrain file.
15b6b316 Update subaru_global_2017.dbc
a12af19a Add steering error signal in subaru global
d411c175 correct max value
881c065d add electrical gear and fix driver torque
1bbac4b8 Add reference to CANdevStudio in README file
8f70ea01 Adds 2016 Honda CR-V Executive

git-subtree-dir: opendbc
git-subtree-split: d68f8ff0cd6bd00a4aa5b7b83efd4b1aa9916452
2020-02-06 13:51:38 -08:00
Vehicle Researcher 7a69c82d65 Merge panda subtree 2020-02-06 13:51:37 -08:00
Vehicle Researcher 4ea182a1b1 Squashed 'panda/' changes from 3b356216..73a60d5c
73a60d5c uds: clear rx buffer on drain
3b20804b uds: rx message buffering
d034f3e9 Added the option to turn on IR in power savings mode (#431)
82cafd10 Allow fan control in power saving (#429)
186d9dcb Fixed GMLAN interrupts when used in Tesla safety (#428)
f67ec28e Fix msg checks for non Honda and Toyota (#426)

git-subtree-dir: panda
git-subtree-split: 73a60d5c9c358e9d5c24aff2f605c3ab650fc74d
2020-02-06 13:51:37 -08:00
Vehicle Researcher 7119634b5b Merge cereal subtree 2020-02-06 13:51:36 -08:00
Vehicle Researcher 60d3364233 Squashed 'cereal/' changes from 01942b89..ab32956a
ab32956a Merge pull request #27 from commaai/ublox-hw-status
2e7f4b90 Added ublox hw status
23abef4f add networkType to thermal
3f01dcf0 fix bad naming
4999e620 unconfusing and accessible to all
8f9aa8fc add fingerprintSource to carParams
57940309 better put
06f8d15c standalone monitorstate (#23)
6eb1e368 qlog at model rate
c38fb572 LateralParams
0c45f20d add uncertainty event name

git-subtree-dir: cereal
git-subtree-split: ab32956aaf927ee6318bcf639e3a25eea72027a9
2020-02-06 13:51:36 -08:00
dragonpilot 1f1ecd595d update spinner logo 2020-02-06 22:57:48 +10:00
dragonpilot 14e89f4b5c spinner use dp logo 2020-02-06 22:57:35 +10:00
dragonpilot 4c37e7a399 increase mini dev bar font size 2020-02-06 22:56:47 +10:00
dragonpilot 2eeb228895 add back deprecated param 2020-02-05 17:34:06 +10:00
dragonpilot dfa6cbee83 fix duplicate ordinal number 2020-02-05 17:26:58 +10:00
dragonpilot 97f1811159 add support of fw based cache fp 2020-02-05 14:34:43 +10:00
dragonpilot 87a694ebcb Merge branch 'devel-staging' of https://github.com/commaai/openpilot into devel 2020-02-05 13:46:07 +10:00
Vehicle Researcher 43c07122e2 openpilot v0.7.2 release 2020-02-03 16:15:37 -08:00
Vehicle Researcher 684b70d40b Merge opendbc subtree 2020-02-03 16:15:31 -08:00
Vehicle Researcher ecb3136cb7 Squashed 'opendbc/' changes from 5081966f..745a2bb0
745a2bb0 Removed non high voltage items. Added units.
fafd091a Added High Voltage Management to powertrain file.
15b6b316 Update subaru_global_2017.dbc
a12af19a Add steering error signal in subaru global
d411c175 correct max value
881c065d add electrical gear and fix driver torque
1bbac4b8 Add reference to CANdevStudio in README file
8f70ea01 Adds 2016 Honda CR-V Executive

git-subtree-dir: opendbc
git-subtree-split: 745a2bb00dad694fb8fcacaea5aaa9207bef06a7
2020-02-03 16:15:31 -08:00
Vehicle Researcher 72c815acef Merge panda subtree 2020-02-03 16:15:30 -08:00
Vehicle Researcher f5a2358cf5 Squashed 'panda/' changes from 3b356216..d034f3e9
d034f3e9 Added the option to turn on IR in power savings mode (#431)
82cafd10 Allow fan control in power saving (#429)
186d9dcb Fixed GMLAN interrupts when used in Tesla safety (#428)
f67ec28e Fix msg checks for non Honda and Toyota (#426)

git-subtree-dir: panda
git-subtree-split: d034f3e9c08130f7c933525af98e2c4ccb14b7c4
2020-02-03 16:15:30 -08:00
Vehicle Researcher 06bfe01802 Merge cereal subtree 2020-02-03 16:15:29 -08:00
Vehicle Researcher b160847119 Squashed 'cereal/' changes from 01942b89..23abef4f
23abef4f add networkType to thermal
3f01dcf0 fix bad naming
4999e620 unconfusing and accessible to all
8f9aa8fc add fingerprintSource to carParams
57940309 better put
06f8d15c standalone monitorstate (#23)
6eb1e368 qlog at model rate
c38fb572 LateralParams
0c45f20d add uncertainty event name

git-subtree-dir: cereal
git-subtree-split: 23abef4fdb18bc2b06281f9937ed3e7fc31e5c37
2020-02-03 16:15:29 -08:00
dragonpilot 50ecefc689 Hyundai to support 'Enable Lateral Control', 'Allow Gas', 'Enable Steering On Signal' features. 2020-02-03 14:36:28 +10:00
dragonpilot 28dc70fe29 Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot into devel-zhs 2020-01-31 17:29:05 +10:00
dragonpilot 272adcb960 keep chinese fonts 2020-01-31 17:20:58 +10:00
dragonpilot ac47815391 Merge branch 'devel-en' into devel-zhs 2020-01-31 17:19:46 +10:00
dragonpilot adc4f36962 remove temp/battery level display to fix black/freeze screen. 2020-01-31 17:18:40 +10:00
dragonpilot 1f9d3825bf Merge branch 'devel-en' into devel-zhs 2020-01-29 22:03:52 +10:00
dragonpilot 794d0c06e7 fix temp/battery display issue 2020-01-29 21:55:12 +10:00
dragonpilot b68f0cff4a Merge branch 'devel-en' into devel-zhs 2020-01-23 15:07:30 +10:00
dragonpilot 599510e7dc add battery level and temp to driving ui. 2020-01-23 14:56:07 +10:00
dragonpilot 9d945bded8 fixed issues in appd that cause offroad to crash. 2020-01-23 14:55:30 +10:00
dragonpilot 2ebed15fcf fix no keyboard issue in full screen app (waze) 2020-01-22 15:05:59 +10:00
dragonpilot b993595e81 fix display issue when opening full screen apps. 2020-01-22 15:04:55 +10:00
dragonpilot 6fec46efb0 add steer ratio learner toggle 2020-01-22 15:03:38 +10:00
dragonpilot 59e91b8774 Merge branch 'devel' of https://github.com/commaai/openpilot into devel 2020-01-22 14:31:29 +10:00
Willem Melching 1e1de64a1e update athenad.py 2020-01-21 12:18:16 -08:00
Willem Melching 67ab1c5b2e update common/android.py 2020-01-21 11:52:33 -08:00
dragonpilot fcc8ab650f Merge branch 'devel' of https://github.com/commaai/openpilot into devel 2020-01-21 14:12:40 +10:00
Willem Melching 460a8e3189 catch exception in uploader.py 2020-01-20 11:30:04 -08:00
Willem Melching 354d14515f update frame apk 2020-01-19 16:06:26 -08:00
andyh2 5c359f93ac apk lib: Grant offroad access to TelephonyManager 2020-01-19 15:17:12 -08:00
Willem Melching f60fe79999 update offroad apk: fix pairing 2020-01-19 14:00:39 -08:00
Willem Melching 21572ce67b Panda signature needs to be bytes 2020-01-19 09:42:10 -08:00
dragonpilot 6be0e673b3 add translations 2020-01-19 21:30:24 +10:00
dragonpilot 4b4c04b387 Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot into devel-zhs 2020-01-19 21:01:09 +10:00
dragonpilot 0f31b841ec Merge branch 'devel-en' into devel-zhs 2020-01-19 21:00:49 +10:00
dragonpilot b11f2770d6 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2020-01-19 20:41:39 +10:00
dragonpilot 5dd8ddd14f simplify alc logic 2020-01-19 20:29:24 +10:00
Willem Melching 8f62890de4 hotfix panda#426 2020-01-18 13:39:47 -08:00
dragonpilot 227a616db9 remove hotspot monkey script 2020-01-18 22:31:55 +10:00
dragonpilot ba77eccaf1 fix migration issue 2020-01-18 22:29:59 +10:00
dragonpilot b539f65a78 use pkill instead pm to close apps 2020-01-18 18:23:42 +10:00
dragonpilot 8ed17d2934 update apks to 0.7.1 version 2020-01-18 18:02:06 +10:00
dragonpilot 65ad81d805 fixing 0.7.1 merge conflicts 2020-01-17 22:32:21 +10:00
dragonpilot 97ee7bc139 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2020-01-17 22:31:23 +10:00
Willem Melching adf25bcb5e Merge pull request #949 from commaai/nightly
openpilot v0.7.1
2020-01-16 16:42:43 -08:00
Willem Melching 7c25bb6950 registration: send up both imeis 2020-01-16 11:43:09 -08:00
Vehicle Researcher 8da8b6135c openpilot v0.7.1 release 2020-01-15 14:05:04 -08:00
Vehicle Researcher 77e450db57 Squashed 'opendbc/' changes from 4f82d01e..5081966f
5081966f One more fix
fa5dc680 Fix honda dbc files after steer torque addition
e4dfb2fa update honda steering signals (#208)
53fc4487 added generator test (#207)
cb27d6e3 Honda Nidec: add new ACC_HUD signals to all other cars other than the CIVIC
6e6779f9 build on mac AND linux, also gotta not use these python files
79dbfc1a build on mac

git-subtree-dir: opendbc
git-subtree-split: 5081966f106e4ed385d756220cfd3dc502e737d9
2020-01-15 14:04:44 -08:00
Vehicle Researcher 25d18afad5 Merge opendbc subtree 2020-01-15 14:04:44 -08:00
Vehicle Researcher b0b7a768f0 Squashed 'panda/' content from commit 3b356216
git-subtree-dir: panda
git-subtree-split: 3b35621671aaa6de3fc66d85d30e4208a77e2489
2020-01-15 14:04:42 -08:00
Vehicle Researcher af301ad7b5 Merge commit 'b0b7a768f00d08fa30d7463efd0d05fcd5490088' as 'panda' 2020-01-15 14:04:42 -08:00
Vehicle Researcher ab415aa5fa Remove old panda subtree 2020-01-15 14:04:40 -08:00
Vehicle Researcher 9504037aa7 Squashed 'cereal/' changes from b8382bbb..01942b89
01942b89 add TODO
b74a456a don't hardcode the lists
ed5a4bf5 add face stds
396a2bb5 add can error counter to controlsState
c6b5c73b Switch default to msgq (#21)
a457ffa0 Fix indentation in readme.md
a1fc8c75 explicitly mention Python for syntax colouring (#20)
19e23931 Fix expected for cameraOdometry and liveCalibration
e7d2f978 Add radar comm issue error
db64cd43 Reserve safety #21 for VAG PQ35/PQ46/NMS (#19)
79d638d5 separate honda safety models between Bosch Giraffe and Bosch Nidec
2614a650 better name
b6b84cda add longitudinal
78f5934a Add canRxErrs to health
67588993 qlog liveCalibration
df80b870 add more stuff to fw log in CarParams
a87805ad fix doxs
4746b208 got doxed
21cf3f55 build on mac
31ac47c2 Add carUnrecognized event

git-subtree-dir: cereal
git-subtree-split: 01942b890d7acf19aecc09432fe5048ba21c0fc9
2020-01-15 14:04:38 -08:00
Vehicle Researcher 0440535f64 Merge cereal subtree 2020-01-15 14:04:38 -08:00
dragonpilot 294fd0eb8d Merge branch 'devel-en' into devel-zhs 2020-01-14 15:37:14 +10:00
dragonpilot f4aa4ab456 add ability to turn on hotspot on boot. 2020-01-14 15:29:00 +10:00
dragonpilot b4e991d714 refactor appd 2020-01-14 14:17:32 +10:00
dragonpilot 9501be7614 Merge branch 'devel-en' into devel-zhs 2020-01-08 15:05:46 +10:00
dragonpilot 27c2d13cb2 add DragonBTG mode 2020-01-08 15:05:31 +10:00
dragonpilot d020d2c83d Merge branch 'devel-en' into devel-zhs 2020-01-06 13:15:26 +10:00
dragonpilot 7001278d0e add support to 2018 Lexus RX300 China ver 2020-01-06 13:15:08 +10:00
dragonpilot 775edcf65f re-add missing apks 2019-12-31 18:12:59 +10:00
dragonpilot 444e219608 Merge branch 'devel-en' into devel-zhs 2019-12-31 18:11:58 +10:00
dragonpilot a6a54b7196 fix issue that may install apks every time 2019-12-31 18:11:46 +10:00
Rick Lan 147a7593e7 fix unable to launch app issue 2019-12-29 23:23:55 +10:00
Rick Lan 2376b8b2e0 Merge branch 'devel-en' into devel-zhs 2019-12-29 22:15:45 +10:00
Rick Lan 178db47eb9 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2019-12-29 21:17:25 +10:00
Rick Lan fb9373f5c9 Move ALCs min speed / timer to variables. 2019-12-29 21:13:22 +10:00
rbiasini a2ae18d1db Honda fwd fixes (#5)
- fix chime forwarding
- forward radar hud msg from stock
- no EON chime during stock fcw
2019-12-25 21:38:00 -08:00
dragonpilot 0ed5c393dc Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot into devel-zhs 2019-12-18 16:18:49 +10:00
dragonpilot 692129f012 appless version 2019-12-18 16:18:31 +10:00
dragonpilot a866998462 Merge branch 'devel-en' into devel-zhs 2019-12-18 14:42:24 +10:00
dragonpilot feff825283 increase min speed to use assist lc / auto lc 2019-12-18 14:34:12 +10:00
dragonpilot 78d7dedbde remove 2017 Civic Hatchback LX fingerprint because it will cause issue with others. 2019-12-18 14:30:55 +10:00
dragonpilot c500e51f29 Merge branch 'devel-en' into devel-zhs 2019-12-18 11:57:22 +10:00
dragonpilot 4959f95dbd update auto_lc logic, fix incorrect auto_lc alert. 2019-12-18 11:57:11 +10:00
dragonpilot ddda7c7953 update translation 2019-12-17 12:54:25 +10:00
Riccardo 8f78b61a47 README update with FCA harness support 2019-12-16 18:33:21 -08:00
dragonpilot 8d10aeb437 Merge branch 'devel-en' into devel-zhs 2019-12-17 11:03:03 +10:00
dragonpilot 542fef8a5a auto lane change send alerts 2019-12-17 11:02:36 +10:00
dragonpilot e6647e61db Merge branch 'devel-en' into devel-zhs 2019-12-17 11:01:56 +10:00
dragonpilot 73d8a0ca40 auto lane change send alerts 2019-12-17 11:01:48 +10:00
dragonpilot 264e56f228 update translation 2019-12-17 10:31:10 +10:00
dragonpilot c16791d735 Merge branch 'devel-en' into devel-zhs 2019-12-17 10:08:25 +10:00
dragonpilot f74a810456 Merge pull request #8 from eFiniLan/dp-devel-en
Auto LC
2019-12-17 10:06:22 +10:00
dragonpilot 5ff77e4500 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2019-12-17 10:03:28 +10:00
dragonpilot 17cdb7e476 fix langauge issue 2019-12-17 10:02:02 +10:00
rbiasini 69fb8b312f Honda Nidec: fix missing signals from dbc files (#919) 2019-12-16 20:27:01 +01:00
Rick Lan b98bbcd72f update apks, fix up ALC logic 2019-12-17 01:18:45 +10:00
dragonpilot 30446d0c74 migrate to 0.7 2019-12-16 17:13:44 +10:00
dragonpilot 4da1d8bf9d Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2019-12-16 11:23:05 +10:00
Willem Melching e0d7a55eab add common/kalman/.gitignore 2019-12-14 12:47:28 -08:00
Riccardo a4b4513149 Allow more time for snapshots and increase alert priority for disallowed community feature 2019-12-14 10:36:39 -08:00
Vehicle Researcher c025b96e8a openpilot v0.7 release 2019-12-13 13:03:08 -08:00
Vehicle Researcher 683b6151ce Squashed 'opendbc/' changes from c0eba096..4f82d01e
4f82d01e gitignore
5cb83454 Honda FCM: diagnostic signals
d309cdce Added linter to opendbc (#203)
d452706f add requirements.txt
ec3b4595 deterministic dependency order
a265d351 Azure pipelines ci (#202)
bce9a2e1 packer depends on libdbc
5d5fdd6a no more python version of libdbc, everything through cython
541705bf move CANDefine to parser code
da25c52a add test for can define
0ba7926b unify can packer and parser
25d88009 consistent naming
a5c640a5 fix linter
be210fef remove obsolete make file
ffd9dca7 opendbc needs cereal
b559f63d remove more make
d0929496 seems to work now
41e80836 don't make
3254d1fc think scons works
eb78f6aa scons sort of working
0ef1e35d fix gitignore
e155e017 Can migration (#199)
3eded83a Honda: correct steering torque sensor sign to be consistent with standard convention (left+)
32f70e2f Fix outback endianness consistency (#196)
a7da471f Update subaru_outback_2015_eyesight.dbc (#195)

git-subtree-dir: opendbc
git-subtree-split: 4f82d01ebc78109888954d9807d320e3c27896fd
2019-12-13 13:02:48 -08:00
Vehicle Researcher 261fb00e11 Merge opendbc subtree 2019-12-13 13:02:48 -08:00
Vehicle Researcher df875819f5 Merge panda subtree 2019-12-13 13:02:46 -08:00
Vehicle Researcher bc7b9b38ae Squashed 'panda/' changes from 256d274e..a648ccae
a648ccae Add os import
042562dd Extracted wifi connect from test helpers
ac0fd5dd query fw versions example - use extended diagnostic session
4e9d788a Remove not-needed cadillac-init
f0a5d154 typo
c093286b Add bootkick after re-enabling phone power (#401)
eadb0dbb security upgrades (#397)
7c13bec0 Command to get signature (#399)
dad439a4 static assert on size of health packet (#398)
da9da466 Fix VERSION
df4159c8 Revert "Revert "Register readback on most modules. Still need to convert the other ones (#396)""
56ec2150 Revert "Register readback on most modules. Still need to convert the other ones (#396)"
893e4861 Register readback on most modules. Still need to convert the other ones (#396)
6bbae7be VW safety: allow cancel spam on both buses to be compatible with camera and gateway integration
d5f7a287 bump panda
1bcc351f ignition_can: set it to False after 2s of not seeing CAN msgs
96137f1a VW can based ignition not needed. it has ignition line at camera as well.
1b004a18 Same flake8 version as the one in openpilot
e82ba5f2 Same pylint version as the one in openpilot
656f99b0 Interrupt refactor (NVIC_SM_1: #334) and Fault handling (#377) (PR #373)
000282e5 Fix can_logger.py to run correctly on python3 (#392)
7f9b4a59 Fix USB device enumeration on Windows 8.1 and Windows 10 (#393)
dec565c7 Update Misra test coverage, which now includes rule 2.7
fb6bc3ba Fix Misra
878dd00a solve race condition is relay_malfunction right after changing the relay status by adding a counter
2d4cb05c add a safety mode counter
a6797a21 Implement USB power mode on uno
670f90cc Merge branch 'master' of github.com:commaai/panda
ca39a5d8 Added faults integer to health packet
e1c34a1a Panda Jungle testing (#394)
2a093a39 Added heartbeat to echo test
22464356 Fixed health struct size. We should really get an automated test for this
f458d67a Add uptime counter to the health packet (#391)
16624811 enable CAN transcievers outside the set_safety_mode function, which is not related
a7c98744 bump panda ver
1192d934 Power saving refactor (#389)
d58d08fb Fix Misra 17.8: can't mod function params
bc685ac9 Minor indent
a54b86c4 Failure of set_safety_mode falls back to SILENT. Failure to set silent results in hanging
597436d3 NOOUTPUT safety mode is now SILENT. NOOUTPUT still exists but keeps C… (#388)
d229f8dc ESP forced off in EON build. this prevents ESP to be turned on when e… (#387)
8a044b34 forgot Hyundai: now also using make_msg
4f9c8796 remove abunch of lines from safety regression tests by using common make_msg function
fb814143 mispelled word
57f5ef8c Fix misra: addr can't be more than 29 bits anyway
68ff5012 typo
d5c772b0 Fixe Toyota message white-list
48197a92 Better masking for ELM mode
b8fe78c3 VW is also tested for safety replay
212d336b Safety Chrysler: Added cancel spam button check
d44b5621 fix print in example
02d579a5 functional addr handling
6249a183 tx_hook shall have a white-list of messages (#381)
8138fc14 uds: handle function addrs and fw version query example
6626a542 Fixed python health api
b9b79e8b uds zero second timeout
e0de1a4f define ALLOW_DEBUG in safety tests
86dec4b8 Safety modes that violate ISO26262 requirements are not compiled in RELEASE build
e74ed936 safety tests a bit more simplified
2027765b relay malfunction test centralized
8af1a01a clean up safety tests
e8f7a3b2 upd panda
cfcce8f0 WIP: Relay malfunction (#384)
69d9d610 No tabs in mazda safety
a86418c1 insignificant changes
f239b996 single addr was better
d063a188 Hyundai safety: re-enable button spam safety check
4d1edc06 skip tx_hook if a message is forwarded (#379)
df2ff045 bump version
168461d5 added fault state to health packet
b3e1a133 uds: better debug prints
68c39fb3 uds: no need for threads if you always drain rx
91b7c5bb bump Panda Ver
26cb4dc4 Fixed pylint error
32725cc3 Fixed misra compliance
e33b4bea Added echo script
312ba62d minor comment cleanupo
e90897a8 Fix board detection on white
0e72c183 always stop executing if safety mode fails to be set (suggested by jyoung8607)
e8d7ed1d Rename function name to not confuse safety_set_mode and set_safety_mode
ff86db65 improve uds message processing
512ab3f2 except Exception
37ce507a py3 all
bac4d854 dos and python3
501db8d1 uds drain before send and use has_obd()
f2cbec16 Added has_obd() to python library
48e5b182 Add SDK downloading to the build step (#314)
e0762c2e Add Python & USB API for controlling phone power (#313)
ba9fb69f New health packet struct also in the python libs

git-subtree-dir: panda
git-subtree-split: a648ccae4b3661ca6de7a4ac199cc44a41442b74
2019-12-13 13:02:46 -08:00
Vehicle Researcher e3b21173a5 Squashed 'cereal/' changes from 90e48c54..b8382bbb
b8382bbb steerLimitTimer should be car dependent
9a229687 add pa0 temp to ThermalData
f6f0f60e Add stock Fcw to carState
b608683f no l/r distinction for LDW
555f48d6 Add ldw alert
8e8b4a4a Remove plusFrame socket in favor of UiLayoutState
3410325c log stock AEB events
2219f2bd Add warning about not using cython version of sec_since_boot
8f1a5122 for legacy-testing reasons, better to define the used percent instead of avail
e86d9545 adding low memory event
ad238340 remove TODO
d0962b34 log mem available and cpu perc in thermald
3b753be9 Implement error handling and exceptions (#18)
a7d5bb76 add explicit dependencies on services.h
1ba64677 fix linter
c7d215b6 Added communityFeatureDisallowed event
492140a5 Added communityFeature bit detection to CarParams
266a5fed log Panda fault types
347a8661 Switch from polling on FIFOs to signal (#12)
e25bba77 no need to double build the objects
fe43a994 20Hz for radar time step is very standard
2aabf1ee Added radar time step to car params
e8ae9086 Generate capnp for java
57126a23 cereal_shared
da655cd3 Add uptime to health
f6a8e394 add test with multiple subscribers
84b3af53 comment out the debugging
4b9c942a added power save state to health packet
66be3708 run python unittest in ci
52c6db87 Run scons in CI (#14)
9414615b do need it, but only for arm
2856c37c remove gnustl_shared
7f05ee64 fix apks
e3a6bded Revert "no more makefiles"
487fbd06 don't rely on BASEDIR, and add zmq library
223e37a5 no more makefiles
da2ed115 don't link the wrong one
fe9fe2a2 scons builds the python lib now
2f81135e err, it can't build services.h
57b03f8b now we shouldn't need that yaml crap everywhere
f8e53277 bridge builds with services.h
2b0cb608 noOutput safety mode is now called silent
83880d51 add msgq tests
bcad1848 msgq: dont block when fifo does not exists
b4b26782 Default to zmq
473e2912 fix compilation in docker
30aaaddc msgq: try again when no timeout on poll but also no message
c4f2ad53 msgq: make sure read_fifos is initalized so we dont close random fds
4e513a85 msgq: dont clean up uninitialized sockerts
c008b630 also remove the fifo from disk
ef64eb27 MSGQ stability improvements when opening and closing lots of queues
e147abcc Revert "Revert "deprecate irpwr""
932dc32e Revert "deprecate irpwr"
a6844150 disengage
ec27e18c capnpc also generated the header files
ee52ab9e deprecate irpwr
301c74c8 Merge branch 'master' of github.com:commaai/cereal
6da7d55a add front frame
a5944eb4 add conflate parameter for SubSocket::create
ca8df170 Add fault status to health
ef4ded06 add conflate support in SubSocket constructor
7fd314af update scons build file
93d814e4 add saturated flags to indi and lqr logs
50302fee add steeringRateLimited to car.capnp
05e3513d add msgq readme
a6759a95 faster make
94b73778 Add struct to log FW version
64ce0b5f add scons build
dc9ad18a add debug print statement on SIGINT
4a612698 Merge pull request #10 from commaai/msgq
4873449a use recv one or none after poll
a054864b default to msgq
fbc4a4cf oops bad number
5067cf4c add meta
cbd02865 fix export prefix and make shared library world readable
c2730541 add c exports for jni usage
e77f41ef zmq already sets the errno correctly
3196cf69 Fix service list path in bridge
d35515a2 add all msgq files, but dont use as default
a68a38fa Don't delete context from python side only
bd46c225 Revert "zmq_ctx_term is blocking"
a1fc26b8 zmq_ctx_term is blocking
09021820 remote address support
21a35361 only delete subsocket when created by same object
34df7351 remove extra underscore from __dealloc__
c8748f86 fix internal refs
79b2fbf7 fixups
23ad2563 import messaging and services

git-subtree-dir: cereal
git-subtree-split: b8382bbb2b8156f2f1d7e1c1b42b46c54d85761f
2019-12-13 13:02:45 -08:00
Vehicle Researcher 391eb0b74b Merge cereal subtree 2019-12-13 13:02:45 -08:00
rbiasini 7be62e781d Update README.md and SAFETY.md (#907)
* Update README.md and SAFETY.md
2019-12-10 19:36:06 -08:00
dragonpilot 800a4a137c Merge branch 'devel-unsupported-cars' into devel-en 2019-12-10 16:26:15 +10:00
dragonpilot d170a9a78a remove duplicated fp 2019-12-10 16:25:36 +10:00
dragonpilot c9bb9a9929 Merge branch 'devel-unsupported-cars' into devel-en 2019-12-10 16:24:46 +10:00
dragonpilot 3e8f177745 add 2 more fingerprints from shell 2019-12-10 16:24:21 +10:00
dragonpilot fc88fa63c2 Merge branch 'devel-unsupported-cars' into devel-en 2019-12-10 16:12:25 +10:00
dragonpilot d8e166f7d9 add 17' Civic Hatchback LX fingerprint from CFranHonda 2019-12-10 16:12:05 +10:00
dragonpilot 78b7dc0606 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-unsupported-cars 2019-12-10 16:08:43 +10:00
dragonpilot 5d900611ff Merge branch 'devel-en' into devel-zhs 2019-12-10 11:41:32 +10:00
dragonpilot 9bfb70bf0c add waze mode 2019-12-10 11:24:49 +10:00
Arne Schwarck 02c4ade948 Battery protection (#888)
* Battery protection

If your car battery voltage is lower than 0% switch off charging to stop the Eon from damaging the 12v car battery. Leaving you with a car that can not start but has a fully charged eon ;-)

* add rbiasini comment && !ignition

* Update Offroad_ChargeDisabled with voltage low

* simplify alert

* non-temporal hysteresis from @rbiasini

And up the start charge limit to 12v. i.e. 50% car battery voltage

* once battery power recovers to 11.500 volts charge

This leaves 1v inbetween for any fluctuations that could occur.

* fix indent

* Fix indent of whole block

It looks like sometimes when you copy and paste into the github web interface some white spacing gets added or removed. BE AWARE!
2019-12-04 11:46:39 -08:00
dragonpilot e70b8e80ba add china 2019 corolla 2019-11-28 14:38:12 +10:00
dragonpilot 10aa84a2a4 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-unsupported-cars 2019-11-28 14:37:24 +10:00
dragonpilot 65adf79be6 add ability to disable steering ratio learner 2019-11-27 10:09:41 +10:00
Shane Smiskol 84ef9d50b7 Fix typo (#891) 2019-11-25 21:40:51 -08:00
dragonpilot 29128cb006 Merge branch 'devel-en' into devel-zhs 2019-11-21 09:23:02 +10:00
dragonpilot 574518f163 update APK, allow use of lead car moving alert without enable OP 2019-11-21 09:21:58 +10:00
dragonpilot 5d0fccc8e4 Merge branch 'devel-en' into devel-zhs 2019-11-19 16:04:30 +10:00
dragonpilot ea93808331 update APK 2019-11-19 16:03:42 +10:00
dragonpilot 38f446dfd0 Merge branch 'devel-en' into devel-zhs 2019-11-19 10:12:04 +10:00
dragonpilot b06266f922 update APK 2019-11-19 10:10:00 +10:00
dragonpilot db753906ad Merge branch 'devel-en' into devel-zhs 2019-11-18 08:02:21 +10:00
dragonpilot 33d7a6d045 update APK 2019-11-18 08:02:07 +10:00
dragonpilot b9981168f1 bug fix 2019-11-15 18:29:30 +10:00
dragonpilot 266fa89ade bug fix 2019-11-15 18:28:59 +10:00
dragonpilot a50dbb22d0 Merge branch 'devel-en' into devel-zhs 2019-11-15 09:26:22 +10:00
dragonpilot f04279a147 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2019-11-15 09:25:54 +10:00
dragonpilot f3eb105e7a Merge branch 'devel-en' into devel-zhs 2019-11-15 09:11:40 +10:00
dragonpilot 5db0c82411 update batt ctrl logic, update APK 2019-11-15 09:10:53 +10:00
Willem Melching 812f93a5a5 Update driving model (#880) 2019-11-14 13:51:35 -08:00
dragonpilot 5dbcd65a7d Merge branch 'devel-en' into devel-zhs 2019-11-13 13:19:07 +10:00
dragonpilot eac595fc85 update APK 2019-11-13 13:13:07 +10:00
dragonpilot 5bf6471944 only check hw type once in thermald automatically 2019-11-13 11:35:10 +10:00
Jason Young 1e1065874b Fixes for various merge and refactoring fallout, typo fixes. (#878)
* Fixes for various merge and refactoring fallout, typo fixes.

* Tab->Spaces
2019-11-12 17:19:34 -08:00
dragonpilot dddc29fdb7 Merge branch 'devel-en' into devel-zhs 2019-11-12 12:40:18 +10:00
dragonpilot ed03d69604 add dragon_is_eon param 2019-11-12 11:00:19 +10:00
dragonpilot 9bfdbab1da Merge branch 'devel-en' into devel-zhs 2019-11-11 10:48:47 +10:00
dragonpilot a334a1353d Merge branch 'devel' of https://github.com/commaai/openpilot into devel-en 2019-11-11 10:48:03 +10:00
dragonpilot 68670e0c48 update APKs, add lead car detected alert 2019-11-11 10:16:43 +10:00
Alex Wang d4eb5a6eaf Add fingerprint (#875) 2019-11-08 23:34:19 -08:00
Willem Melching 3f4695de53 Make DBC preprocessing deterministic 2019-11-08 17:26:48 -08:00
Willem Melching d20896ced5 Make visiond compile on pc (#874) 2019-11-08 12:49:30 -08:00
dragonpilot a9570e7eab Merge branch 'devel-en' into devel-zhs 2019-11-08 13:11:20 +10:00
dragonpilot f4e9e339f2 fix GSH issue 2019-11-08 13:10:44 +10:00
Willem Melching a649732568 Fix unicode bug in DoUninstall reading 2019-11-07 13:53:42 -08:00
Willem Melching 3c6d8846ac Fix fan control when not plugged into panda 2019-11-07 11:28:35 -08:00
dragonpilot 0612f6162b Merge branch 'devel-en' into devel-zhs 2019-11-07 11:55:41 +10:00
dragonpilot c7e52af67d update APK 2019-11-07 11:53:09 +10:00
dragonpilot bdc5497603 Merge branch 'devel-en' into devel-zhs 2019-11-07 11:42:52 +10:00
dragonpilot c293bc4a36 update APK 2019-11-07 11:42:17 +10:00
dragonpilot 461b0adcb2 Merge branch 'devel-en' into devel-zhs 2019-11-06 16:45:04 +10:00
dragonpilot c375fcc8c6 Add mock radar for Bosch https://github.com/kegman/openpilot/commit/53c945c5cd6716e3953a9baae1431c9a8d984e83 2019-11-06 16:44:43 +10:00
dragonpilot 04d7684b7c Merge branch 'devel-en' into devel-zhs 2019-11-06 16:34:31 +10:00
dragonpilot b2e5aac1f3 fix appd/dashcamd error due to changes in messaging 2019-11-06 16:34:14 +10:00
dragonpilot 30737d6f18 Merge branch 'devel-en' into devel-zhs 2019-11-06 15:22:00 +10:00
dragonpilot cb3af07e47 disable update prompt 2019-11-06 15:21:46 +10:00
dragonpilot 2d9cc41871 Merge branch 'devel-en' into devel-zhs 2019-11-06 14:58:03 +10:00
dragonpilot e14c6757d8 add tw.com.ainvest.outpack to android_packages 2019-11-06 14:57:47 +10:00
dragonpilot 6a353954e8 Merge branch 'devel-en' into devel-zhs 2019-11-06 14:51:29 +10:00
dragonpilot 667f4abccb delete signed firmware 2019-11-06 14:50:53 +10:00
dragonpilot b0fcfe4069 update APK 2019-11-06 12:25:39 +10:00
dragonpilot 4576e32f43 Merge branch 'devel-unsupported-cars' into devel-en 2019-11-06 12:15:05 +10:00
dragonpilot 599458f768 Merge branch 'devel' of https://github.com/commaai/openpilot into devel-unsupported-cars 2019-11-06 12:00:30 +10:00
dragonpilot 2069ee8ee6 fix GSH issue, ISH use better steer angle sensor 2019-11-06 11:57:08 +10:00
dragonpilot 4507453c1d Merge branch 'devel-en' into devel-zhs 2019-11-05 14:41:47 +10:00
Riccardo 29642139f0 Decrease build time for dbc files 2019-11-04 19:23:02 -08:00
Vehicle Researcher d7f0b402a8 openpilot v0.6.6 release 2019-11-04 15:13:52 -08:00
dragonpilot 7ea0f9636f Merge branch 'devel-en' into devel-zhs 2019-11-04 16:44:08 +10:00
dragonpilot 682bb349df Merge branch 'devel-en' into devel-zhs 2019-11-01 13:39:18 +10:00
dragonpilot 14fd00051f Merge branch 'devel-en' into devel-zhs 2019-11-01 13:35:46 +10:00
dragonpilot d8160015b7 Merge branch 'devel-en' into devel-zhs 2019-11-01 11:11:39 +10:00
Vehicle Researcher 67c4121f62 Squashed 'opendbc/' changes from f3b573559..c0eba096b
c0eba096b remove obsolete Subaru dbc file
f7bce9ee0 Fixes to vw dbc
adb672657 Added VW comment about ignition bit
c51631617 Fixes and new message for VW MQB, fix for Accord Touring (#193)
a09bf725e fixed to luxgen dbc file
f00f6289a Create luxgen_s5_2014.dbc (#101)
024612b20 Fix steer angle factor for toyota
7311ee70e Lexus is adjustment (#192)
f04ce577e Updates for Volkswagen support (#191)

git-subtree-dir: opendbc
git-subtree-split: c0eba096bc74033ea54abfd56406b5af3108727c
2019-10-31 17:02:32 -07:00
Vehicle Researcher b4f4b92ecf Merge opendbc subtree 2019-10-31 17:02:32 -07:00
Vehicle Researcher 22023ebd58 Squashed 'panda/' changes from 30c7ca8a5..256d274e7
256d274e7 Fix Mac installation instruction per: https://github.com/commaai/panda/pull/308/files
bfd8ff1b1 Update cppcheck commit with more coverage
b143a1cf9 Fixed Misra complaint
606f1d913 Fixed RTC on non-uno boards, second try. Cannot work when there is no xtal.
933c75770 Fix RTC on non-uno boards (#311)
48d0d0c78 VW button spam: fix safety and add tests (#306)
6cccf969a Fan and IR at 0 when in power savings mode (#309)
05373282a board get_sdk scripts were left on python2
de18a7ef1 bump version after uno merge
1965817d3 Changed default values for testing
a12a148d5 Uno (#274)
7d29dc5a2 bump panda version. We really need a better way
40075321d VW: stricter limits to comply with comma safety policy
e2e2be92c add safety mode to health packet
101238c7f turned on VW ignition based CAN logic
a0d8d5dae fix misra 5.3: check_ignition is intended as check_started and can't be used twice
ea636de61 made check_ignition function to both look at ignition_line and ignition_can
1102e6965 make ignition logic common for all cars (#303)
3a110c6f6 bump version after CMSIS core upgrade
55dfa5230 Update core to CMSIS 5.6 release  (#251)
ee864907c fix linter 2
f410b110d fix linter
55957d6e4 proper python3 exception inheritance
6ba0f47b5 fix linter errors
5c49fe050 Merge pull request #145 from gregjhogan/uds
0f361999b timeout is float
396d6aad5 safety_replay only installs few extra requirements
25af7d301 Misra also need python 3 env
7434c5ce2 centralize requirements for tests
a0c37c70a coverage not needed in linter reqs
fce38a91d Linter python (#299)
62e2f5caa update cppcheck commit
711810d2f more uds debug
4454e3a6b better CAN comm abstraction
6b1f28f57 fix more encoding and some bytes cleanup (#300)
43adad311 fix WARNING_INDICATOR_REQUESTED name
9c857da37 0x
b64d6fa5d typing
768fdf7e1 bytes() > chr().encode()
1be15ea93 custom errors from thread
68da8315f more python3
eb358e81c uds lib example
4f288586d updates for python3
932745f62 support tx flow control for chunked messages
b1c371292 add timeout param
cdf2f626b bug fixes
b1a319577 fix rx message filtering bug
80fb6a6fa convert uds lib to class
59cd2b47f handle separation time in microseconds
4429600d8 fix separation time parsing
c641e66f7 fix typo
48b8dcc6f fix flow control delay scale
78f413d88 flow control delay
33a5167d9 bug fixes
8ee89a091 multi-frame tx
5e89a9c72 clear rx buffer and numeric error ids
966230063 fix remaining size calculation
01ef1fae3 zero pad messages before sending
1ddc9735d uds can communication
dca176e71 syntax errors
95be4811e SERVICE_TYPE enum
98e73b51d more UDS message type implementation
c1c5b0356 uds lib
162f4853d fix chr to bytes conversions (#298)
4972376de Update VW regression test to follow Comma safety index refactoring (#296)
f9053f5df more Python 3 fixes, attempting to fix jenkins wifi regresison test (#295)
2f9e07628 Panda safety code for Volkswagen, Audi, SEAT, and Škoda (#293)

git-subtree-dir: panda
git-subtree-split: 256d274e760ce00d4e5ff5e0d9b86d0fb5924568
2019-10-31 17:02:31 -07:00
Vehicle Researcher 97a289e6a9 Merge panda subtree 2019-10-31 17:02:31 -07:00
Vehicle Researcher 047924cb35 Squashed 'cereal/' changes from 3d90c7877..90e48c549
90e48c549 add ir pwr field
101facee1 added safety model to health packet
fe09e4c07 distinguish between ignition_line and ignition_can

git-subtree-dir: cereal
git-subtree-split: 90e48c549c505383a7242cfddd32984cd5c268b8
2019-10-31 17:02:27 -07:00
Vehicle Researcher 38e7d54d5d Merge cereal subtree 2019-10-31 17:02:27 -07:00
dragonpilot 53422a42e4 Merge branch 'devel-en' into devel-zhs 2019-10-31 11:25:29 +10:00
dragonpilot b7ae456df0 Merge branch 'devel-en' into devel-zhs 2019-10-30 11:56:24 +10:00
dragonpilot 6cbfa9ef2b Merge branch 'devel-en' into devel-zhs 2019-10-30 10:37:42 +10:00
dragonpilot debfe847ff Merge branch 'devel-en' into devel-zhs 2019-10-30 09:32:04 +10:00
dragonpilot ae0dbf52d9 update APK 2019-10-29 10:17:41 +10:00
dragonpilot ab305f4d4f Merge branch 'devel-en' into devel-zhs 2019-10-29 10:04:16 +10:00
dragonpilot 3ba8e21aa8 Merge branch 'devel-en' into devel-zhs 2019-10-28 12:34:23 +10:00
dragonpilot e7580fd47f Merge branch 'devel-en' into devel-zhs 2019-10-27 09:56:45 +10:00
dragonpilot 5281c6e047 Merge branch 'devel-en' into devel-zhs 2019-10-25 09:18:19 +10:00
dragonpilot 2100ebb4db Merge branch 'devel-en' into devel-zhs 2019-10-24 13:44:15 +10:00
dragonpilot 97c10c6a76 Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot into devel-zhs 2019-10-22 16:54:10 +10:00
dragonpilot eb4c746f9e Merge branch 'devel-en' into devel-zhs 2019-10-22 16:53:48 +10:00
dragonpilot 06d301042a Merge branch 'devel-en' into devel-zhs 2019-10-21 19:04:50 +10:00
dragonpilot c5a1244bfe update APK 2019-10-21 11:23:59 +10:00
dragonpilot 2a5625e43d Merge branch 'devel-en' into devel-zhs 2019-10-21 11:20:49 +10:00
dragonpilot f5a4fee857 Merge branch 'devel-en' into devel-zhs 2019-10-18 09:52:42 +10:00
dragonpilot a6527a4af1 Merge branch 'devel-en' into devel-zhs 2019-10-18 09:42:02 +10:00
dragonpilot 69c15b6c24 update APK 2019-10-17 14:29:54 +10:00
dragonpilot 74d5114bb3 Merge branch 'devel-en' into devel-zhs 2019-10-17 14:29:44 +10:00
dragonpilot 51e3102563 Merge branch 'devel-en' into devel-zhs 2019-10-17 13:35:17 +10:00
dragonpilot 01e859daee update APK 2019-10-17 10:39:03 +10:00
dragonpilot b255a2b3a8 Merge branch 'devel-en' into devel-zhs 2019-10-17 10:37:34 +10:00
dragonpilot 26f73d91bc Merge branch 'devel-en' into devel-zhs 2019-10-16 17:22:31 +10:00
dragonpilot 9080ac3b59 Merge branch 'devel-en' into devel-zhs 2019-10-16 16:11:23 +10:00
dragonpilot 1d99e4bed7 Merge branch 'devel-en' into devel-zhs 2019-10-16 11:58:03 +10:00
dragonpilot 409de73850 Merge branch 'devel-en' into devel-zhs 2019-10-16 10:36:45 +10:00
dragonpilot 7d24dfc389 Merge branch 'devel-en' into devel-zhs 2019-10-15 12:02:50 +10:00
dragonpilot ad6a84d1da Update APK 2019-10-14 17:20:03 +10:00
dragonpilot f875a55221 Merge branch 'devel-en' into devel-zhs 2019-10-14 17:19:03 +10:00
dragonpilot a7f87c55cb Merge branch 'devel-en' into devel-zhs 2019-10-14 16:56:25 +10:00
dragonpilot 0fbd36f6a5 Merge branch 'devel-en' into devel-zhs 2019-10-14 16:04:14 +10:00
dragonpilot ba85e0125a Merge branch 'devel-en' into devel-zhs 2019-10-14 13:59:49 +10:00
dragonpilot c9ce994f5e update APK 2019-10-14 13:51:23 +10:00
dragonpilot b21b4c4d5c Merge branch 'devel-en' into devel-zhs 2019-10-14 13:51:15 +10:00
dragonpilot 231a84bbda update APK 2019-10-14 12:37:36 +10:00
dragonpilot 6798f3ea7f Merge branch 'devel-en' into devel-zhs 2019-10-14 11:04:37 +10:00
dragonpilot 06cbc7c363 Merge branch 'devel-en' into devel-zhs 2019-10-13 10:37:31 +10:00
dragonpilot 46c180dc2c Merge branch 'devel-en' into devel-zhs 2019-10-11 13:44:32 +10:00
dragonpilot 08cd6e0c10 Update APK 2019-10-11 13:14:38 +10:00
dragonpilot b0e1df656b Merge branch 'devel-en' into devel-zhs 2019-10-11 13:14:08 +10:00
dragonpilot 30a17d23cc Merge branch 'devel-en' into devel-zhs 2019-10-10 23:24:14 +10:00
dragonpilot a647d01502 Merge branch 'devel-en' into devel-zhs 2019-10-09 14:46:35 +10:00
dragonpilot a2ca21b502 Merge branch 'devel-en' into devel-zhs 2019-10-08 14:43:33 +10:00
dragonpilot d04fd932e4 Update APK 2019-10-08 11:21:22 +10:00
dragonpilot 9ed6830263 Merge branch 'devel-en' into devel-zhs 2019-10-08 10:50:08 +10:00
dragonpilot d14540b46a Merge branch 'devel-en' into devel-zhs 2019-10-08 10:25:54 +10:00
dragonpilot f05c53ad8c Merge branch 'devel-en' into devel-zhs 2019-10-07 21:11:53 +10:00
dragonpilot 2ee5cb61ee Merge branch 'devel-en' into devel-zhs 2019-10-06 20:20:20 +10:00
dragonpilot 82721d8bc8 Merge branch 'devel-en' into devel-zhs 2019-10-01 12:18:30 +10:00
dragonpilot 6f91fc9051 Merge branch 'devel-en' into devel-zhs 2019-09-30 12:47:58 +10:00
dragonpilot c9ef907a3f Merge branch 'devel-en' into devel-zhs 2019-09-30 11:44:49 +10:00
dragonpilot fff423ea5e Merge branch 'devel-en' into devel-zhs 2019-09-28 16:39:06 +10:00
dragonpilot 1aefaf9bcf Merge branch 'devel-en' into devel-zhs 2019-09-27 15:11:51 +10:00
dragonpilot ee5945fcb9 Merge branch 'devel-en' into devel-zhs 2019-09-26 16:59:27 +10:00
dragonpilot b852ef96e4 Merge branch 'devel-en' into devel-zhs 2019-09-26 16:51:01 +10:00
dragonpilot 50e0ee1e98 Update APK 2019-09-25 11:06:03 +10:00
dragonpilot 794331b9b3 Merge branch 'devel-en' into devel-zhs 2019-09-25 10:59:53 +10:00
dragonpilot 1b13875c24 Merge branch 'devel-en' into devel-zhs 2019-09-23 14:44:33 +10:00
dragonpilot e308d9df21 Update APK 2019-09-23 14:29:17 +10:00
dragonpilot c47d92d53e Merge branch 'devel-en' into devel-zhs 2019-09-23 14:28:54 +10:00
dragonpilot ffba949e80 update APK 2019-09-23 13:46:45 +10:00
dragonpilot 62aff30042 Merge branch 'devel-en' into devel-zhs 2019-09-23 13:44:48 +10:00
dragonpilot a39185d4ff Merge branch 'devel-en' into devel-zhs 2019-09-23 12:38:14 +10:00
dragonpilot 8c0a81dd51 update APK 2019-09-20 16:00:21 +10:00
dragonpilot 00b52381e7 Merge branch 'devel-en' into devel-zhs 2019-09-20 16:00:10 +10:00
dragonpilot 8f89061cc8 Merge branch 'devel-en' into devel-zhs 2019-09-20 15:24:48 +10:00
dragonpilot f447d535ce Merge branch 'devel-en' into devel-zhs 2019-09-19 16:40:03 +10:00
dragonpilot 2212764112 Merge branch 'devel-en' into devel-zhs 2019-09-17 12:41:58 +10:00
dragonpilot 0539ed33de Merge branch 'devel-en' into devel-zhs 2019-09-14 18:20:34 +10:00
dragonpilot 4f75739f81 Update APK 2019-09-13 23:11:38 +10:00
dragonpilot 7f895f57e4 Merge branch 'devel-en' into devel-zhs 2019-09-13 23:11:12 +10:00
dragonpilot ff616558cc Merge branch 'devel-en' into devel-zhs 2019-09-09 14:25:23 +10:00
dragonpilot 9750c8eae1 Merge branch 'devel-en' into devel-zhs 2019-09-09 14:18:08 +10:00
dragonpilot ce85c85a40 更新APK 2019-09-09 13:03:50 +10:00
dragonpilot cdcf110c97 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.frame.apk
#	apk/ai.comma.plus.offroad.apk
2019-09-09 12:57:52 +10:00
dragonpilot 08071b48af Merge branch 'devel-en' into devel-zhs 2019-09-05 15:33:34 +10:00
dragonpilot c050b6c383 Merge branch 'devel-en' into devel-zhs 2019-09-05 11:16:27 +10:00
dragonpilot e5783bf3fd Merge branch 'devel-en' into devel-zhs 2019-09-04 15:37:53 +10:00
dragonpilot 8cd913dade Merge branch 'devel-en' into devel-zhs 2019-09-04 14:40:32 +10:00
dragonpilot 50fbc5cf71 Merge branch 'devel-zhs' of https://dragonpilot@github.com/dragonpilot-community/dragonpilot.git; branch 'devel-en' into devel-zhs 2019-09-04 12:23:40 +10:00
dragonpilot 921c91993a Merge branch 'devel-en' into devel-zhs 2019-09-02 15:35:18 +10:00
dragonpilot 0ebb6441e9 Merge branch 'devel-en' into devel-zhs 2019-09-02 14:46:03 +10:00
dragonpilot f46f416556 Merge branch 'devel-en' into devel-zhs 2019-09-02 13:24:29 +10:00
dragonpilot a926ee5ef7 更新APK 2019-09-02 11:58:08 +10:00
dragonpilot ce7f054671 Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot into devel-zhs 2019-09-02 11:51:10 +10:00
dragonpilot 0f987c799c Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.frame.apk
2019-09-02 11:50:24 +10:00
dragonpilot 39a3480d26 Merge branch 'devel-en' into devel-zhs 2019-08-30 20:51:05 +10:00
dragonpilot c4afd612cf 更新APK 2019-08-30 15:24:42 +10:00
dragonpilot df7d57c657 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-30 15:19:45 +10:00
dragonpilot db709ce0ce Merge branch 'devel-en' into devel-zhs 2019-08-30 14:14:08 +10:00
dragonpilot d3084128e4 Merge branch 'devel-en' into devel-zhs 2019-08-30 13:56:55 +10:00
dragonpilot 4f7b7aac14 更新APK 2019-08-30 13:41:03 +10:00
dragonpilot 3957d92c14 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-30 13:36:52 +10:00
dragonpilot 19d91897aa 更新APK 2019-08-30 12:04:49 +10:00
dragonpilot 41b57f4568 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-30 12:03:25 +10:00
dragonpilot d99dce1aa5 更新APK 2019-08-28 16:22:25 +10:00
dragonpilot fdde1eba3d Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-28 16:22:11 +10:00
dragonpilot 8f981df2bb Merge branch 'devel-en' into devel-zhs 2019-08-28 16:08:50 +10:00
dragonpilot 10e0ed5461 Merge branch 'devel-en' into devel-zhs 2019-08-28 16:06:50 +10:00
dragonpilot f569f9a2f3 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-28 11:23:51 +10:00
dragonpilot 880ba97b8d 更新APK 2019-08-27 13:59:20 +10:00
dragonpilot 9c4e6e4f1a Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-27 13:59:11 +10:00
dragonpilot b70736ab33 Merge branch 'devel-en' into devel-zhs 2019-08-23 01:26:06 +10:00
dragonpilot a35b875282 Merge branch 'devel-en' into devel-zhs 2019-08-23 01:15:50 +10:00
dragonpilot 19ae57ad46 更新APK 2019-08-23 00:43:50 +10:00
dragonpilot 7a60cdd3aa Merge branch 'devel-en' into devel-zhs 2019-08-23 00:43:18 +10:00
dragonpilot fd194c14a3 Merge branch 'devel-en' into devel-zhs 2019-08-22 18:05:37 +10:00
dragonpilot 017c2e8473 更新APK 2019-08-22 16:28:43 +10:00
dragonpilot d47895f42e Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-22 16:27:24 +10:00
dragonpilot 68a2fc2424 更新APK 2019-08-22 16:00:31 +10:00
dragonpilot e9340892f6 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-22 16:00:00 +10:00
dragonpilot e71738a666 Merge branch 'devel-en' into devel-zhs 2019-08-22 00:11:59 +10:00
dragonpilot c9171abe1c Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-21 17:46:28 +10:00
dragonpilot 1014772fd5 更新APK 2019-08-20 16:51:28 +10:00
dragonpilot 809ed323e9 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-20 16:49:20 +10:00
dragonpilot 1128037183 Merge branch 'devel-en' into devel-zhs 2019-08-19 16:50:11 +10:00
dragonpilot 46994e713f Merge branch 'devel-en' into devel-zhs 2019-08-19 15:26:41 +10:00
dragonpilot 6c0ef49134 Merge branch 'devel-en' into devel-zhs 2019-08-19 14:26:35 +10:00
dragonpilot 4e3cfb5eeb Merge branch 'devel-en' into devel-zhs 2019-08-19 12:49:09 +10:00
dragonpilot 21e04e4859 Merge branch 'devel-en' into devel-zhs 2019-08-19 12:26:02 +10:00
dragonpilot ba6b5a754d Merge branch 'devel-en' into devel-zhs 2019-08-19 12:12:03 +10:00
dragonpilot 495cfc9f9d Merge branch 'devel-en' into devel-zhs 2019-08-19 12:10:06 +10:00
dragonpilot b44d0d9a41 更新APK 2019-08-19 11:53:36 +10:00
dragonpilot 94bace2180 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.frame.apk
#	apk/ai.comma.plus.offroad.apk
2019-08-19 11:52:23 +10:00
dragonpilot 5992dfad64 Merge branch 'devel-en' into devel-zhs 2019-08-19 10:30:42 +10:00
dragonpilot 24587c52ad Merge branch 'devel-en' into devel-zhs 2019-08-15 17:16:29 +10:00
dragonpilot 84829791ec Merge branch 'devel-en' into devel-zhs 2019-08-15 15:37:58 +10:00
dragonpilot 3e8377ec69 更新預設語系 2019-08-15 15:16:05 +10:00
dragonpilot 91c106c50d Merge branch 'devel-en' into devel-zhs 2019-08-15 15:15:37 +10:00
dragonpilot f1c249c315 Merge branch 'devel-en' into devel-zhs 2019-08-14 13:59:50 +10:00
dragonpilot 33db3a46a6 更新APK 2019-08-14 12:14:42 +10:00
dragonpilot b6a7a76f94 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-14 12:12:59 +10:00
dragonpilot 201147b641 更新APK 2019-08-14 11:01:06 +10:00
dragonpilot 31f25d67b9 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-14 10:47:01 +10:00
dragonpilot e0c027647f 更新APK 2019-08-12 23:15:53 +10:00
dragonpilot 3811b73472 conflict 2019-08-12 23:15:33 +10:00
dragonpilot e4e0f9ae0e 加入高德地圖 2019-08-11 08:08:24 +10:00
dragonpilot 2dec513506 Merge branch 'devel-en' into devel-zhs 2019-08-11 02:06:53 +10:00
dragonpilot 1b10f26612 Merge branch 'devel-en' into devel-zhs 2019-08-06 15:43:33 +10:00
Dragonpilot db8f6f2030 Merge branch 'devel-en' into devel-zhs 2019-08-02 09:18:26 +10:00
Dragonpilot f3d4fc2fb0 Merge branch 'devel-en' into devel-zhs 2019-08-02 08:53:51 +10:00
Dragonpilot a9dfc2c6b7 更新 APK 2019-08-01 11:44:16 +10:00
Dragonpilot 4acf552ee2 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-08-01 11:31:23 +10:00
dragonpilot 1a6246dc26 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-31 23:22:10 +10:00
Dragonpilot 402bbc38dc 更新 APK 2019-07-31 11:31:16 +10:00
Dragonpilot 2a28a5d45c Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-31 11:28:48 +10:00
Dragonpilot 91c322f32b 更新 APK 2019-07-31 09:38:03 +10:00
dragonpilot cecd626758 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-31 08:37:43 +10:00
Dragonpilot c8d0db8245 Merge branch 'devel-en' into devel-zhs 2019-07-29 10:39:42 +10:00
dragonpilot 7f0d7ad126 Merge branch 'devel-en' into devel-zhs 2019-07-28 10:22:48 +10:00
Dragonpilot c39515d089 更新 APK 2019-07-26 15:31:41 +10:00
Dragonpilot b3a5ca8665 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-26 15:29:03 +10:00
Dragonpilot 0b34cf80ce Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-26 12:03:24 +10:00
dragonpilot 448e332a6c 更新 APK 2019-07-25 22:18:12 +10:00
dragonpilot d7ac244156 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-25 22:01:27 +10:00
dragonpilot 0d40204bab Merge branch 'devel-en' into devel-zhs 2019-07-24 00:29:25 +10:00
dragonpilot 5c1834fd74 Merge branch 'devel-zhs' of https://github.com/dragonpilot-community/dragonpilot-dev into devel-zhs 2019-07-24 00:29:20 +10:00
Dragonpilot 4c19b948a2 Merge branch 'devel-en' into devel-zhs 2019-07-23 15:52:07 +10:00
Dragonpilot 677070934a Merge branch 'devel-en' into devel-zhs 2019-07-23 15:40:53 +10:00
Dragonpilot 42ef74155a 更新 APK 2019-07-23 12:29:02 +10:00
Dragonpilot 7153b10dc9 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-23 12:28:46 +10:00
Dragonpilot 66c382734a 更新 APK 2019-07-23 11:01:13 +10:00
Dragonpilot d3fadbb53c Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-23 10:59:49 +10:00
Dragonpilot 1db92a0295 Merge branch 'devel-en' into devel-zhs 2019-07-16 15:25:12 +10:00
Dragonpilot 9b58d66b0c Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-16 11:34:44 +10:00
Dragonpilot 1249d3ceeb 更新 APK 2019-07-15 11:44:15 +10:00
Dragonpilot d71241393b 更新 APK 2019-07-15 11:33:44 +10:00
dragonpilot 4a7b35aa5f Merge branch 'devel-en' into devel-zhs 2019-07-13 22:47:19 +10:00
dragonpilot b9668d3992 Merge branch 'devel-en' into devel-zhs 2019-07-13 22:38:08 +10:00
dragonpilot 21689dc822 更新 APK 2019-07-12 21:05:38 +10:00
dragonpilot e77a179265 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-12 21:00:09 +10:00
dragonpilot 1cea4442f0 Merge branch 'devel-en' into devel-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-12 20:23:46 +10:00
Dragonpilot b175441c76 更新 APK 2019-07-12 13:27:53 +10:00
Dragonpilot c137dd39bd Merge branch 'dragonpilot-dev-en' of https://github.com/dragonpilot/dragonpilot-dev into dragonpilot-dev-zhs 2019-07-12 12:58:37 +10:00
Dragonpilot fe55d580f8 更新 APK 2019-07-11 10:55:33 +10:00
Dragonpilot 5d6cc9667f Merge branch 'dragonpilot-dev' into dragonpilot-dev-zhs
# Conflicts:
#	apk/ai.comma.plus.offroad.apk
2019-07-11 10:54:52 +10:00
dragonpilot 5e3bb1dcb9 Add zhs apks 2019-07-04 23:11:11 +10:00
Rick Lan d23aee32c1 Merge branch 'dragonpilot-dev-zhs' of https://github.com/dragonpilot-community/dragonpilot-dev into dragonpilot-dev-zhs 2019-07-04 21:32:24 +10:00
dragonpilot 9a62d62e7c Merge pull request #3 from dingliangxue/devel
add support Simplified Chinese Language
2019-07-04 21:31:51 +10:00
dragonpilot acf9e76c49 Merge branch 'dragonpilot-dev-zhs' into devel 2019-07-04 21:31:31 +10:00
Rick Lan e799115747 Merge branch 'devel' of https://github.com/dingliangxue/dragonpilot-dev into dragonpilot-dev-zhs
# Conflicts:
#	selfdrive/controls/lib/alerts.py
2019-07-04 21:24:53 +10:00
dinglx 3dcd643ac6 add support Simplified Chinese Language 2019-07-04 15:19:07 +08:00
1323 changed files with 264201 additions and 42798 deletions
+1 -1
View File
@@ -16,7 +16,7 @@ Steps to reproduce the behavior, or a explorer/cabana link to the exact drive an
**Expected behavior**
A clear and concise description of what you expected to happen.
** Device/Version information (please complete the following information):**
**Device/Version information (please complete the following information):**
- Device: [e.g. EON/EON Gold]
- Version: [e.g. 0.6.4], or commit hash when on devel
- Car make/model [e.g. Toyota Prius 2016]
+17 -3
View File
@@ -3,11 +3,14 @@ venv/
.tags
.ipynb_checkpoints
.idea
.overlay_init
.overlay_consistent
.sconsign.dblite
.vscode
model2.png
a.out
*.dylib
*.DSYM
*.d
*.pyc
@@ -15,7 +18,9 @@ a.out
.*.swp
.*.swo
.*.un~
*.tmp
*.o
*.os
*.so
*.a
*.clb
@@ -25,21 +30,30 @@ a.out
config.json
clcache
persist
board/obj/
selfdrive/boardd/boardd
selfdrive/logcatd/logcatd
selfdrive/mapd/default_speeds_by_region.json
selfdrive/proclogd/proclogd
selfdrive/ui/ui
selfdrive/ui/_ui
selfdrive/test/longitudinal_maneuvers/out
selfdrive/visiond/visiond
selfdrive/loggerd/loggerd
selfdrive/sensord/gpsd
selfdrive/sensord/sensord
selfdrive/sensord/_gpsd
selfdrive/sensord/_sensord
selfdrive/camerad/camerad
selfdrive/modeld/_modeld
selfdrive/modeld/_dmonitoringmodeld
/src/
one
openpilot
notebooks
xx
panda_jungle
.coverage*
htmlcov
pandaextra
+9
View File
@@ -29,3 +29,12 @@ Code is automatically check for style by travis as part of the automated tests.
We've released a [Model Port guide](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) for porting to Toyota/Lexus models.
If you port openpilot to a substantially new car brand, see this more generic [Brand Port guide](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84). You might also be eligible for a bounty. See our bounties at [comma.ai/bounties.html](https://comma.ai/bounties.html)
## Pull Requests
Pull requests should be against the master branch. Before running master on in-car hardware, you'll need to run
```
git submodule init
git submodule update
```
in order to pull down the submodules, such as `panda` and `opendbc`.
-80
View File
@@ -1,80 +0,0 @@
FROM ubuntu:16.04
ENV PYTHONUNBUFFERED 1
RUN apt-get update && apt-get install -y \
autoconf \
build-essential \
bzip2 \
clang \
cmake \
curl \
ffmpeg \
git \
libarchive-dev \
libbz2-dev \
libcurl4-openssl-dev \
libeigen3-dev \
libffi-dev \
libglew-dev \
libglib2.0-0 \
liblzma-dev \
libmysqlclient-dev \
libomp-dev \
libopencv-dev \
libssl-dev \
libtool \
libusb-1.0-0 \
libzmq5-dev \
locales \
ocl-icd-libopencl1 \
ocl-icd-opencl-dev \
opencl-headers \
python-dev \
python-pip \
screen \
sudo \
vim \
wget
RUN sed -i -e 's/# en_US.UTF-8 UTF-8/en_US.UTF-8 UTF-8/' /etc/locale.gen && locale-gen
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
RUN pyenv install 3.7.3
RUN pyenv global 3.7.3
RUN pyenv rehash
RUN pip install pipenv==2018.11.26
COPY Pipfile /tmp/
COPY Pipfile.lock /tmp/
RUN python --version
RUN cd /tmp && pipenv install --system --deploy
# Install subset of dev dependencies needed for CI
RUN pip install matplotlib==3.1.1 dictdiffer==0.8.0 fastcluster==1.1.25 aenum==2.2.1 scipy==1.3.1 lru-dict==1.1.6 tenacity==5.1.1 azure-common==1.1.23 azure-nspkg==3.0.2 azure-storage-blob==2.1.0 azure-storage-common==2.1.0 azure-storage-nspkg==3.1.0 pycurl==7.43.0.3
COPY phonelibs/install_capnp.sh /tmp/install_capnp.sh
RUN /tmp/install_capnp.sh
RUN git clone --branch v0.6.5 https://github.com/commaai/openpilot-tools.git /tmp/openpilot/tools
ENV PYTHONPATH /tmp/openpilot:${PYTHONPATH}
COPY ./.pylintrc /tmp/openpilot/.pylintrc
COPY ./common /tmp/openpilot/common
COPY ./cereal /tmp/openpilot/cereal
COPY ./opendbc /tmp/openpilot/opendbc
COPY ./selfdrive /tmp/openpilot/selfdrive
COPY ./phonelibs /tmp/openpilot/phonelibs
COPY ./pyextra /tmp/openpilot/pyextra
COPY ./panda /tmp/openpilot/panda
RUN mkdir -p /tmp/openpilot/selfdrive/test/out
RUN make -C /tmp/openpilot/selfdrive/controls/lib/longitudinal_mpc clean
RUN make -C /tmp/openpilot/selfdrive/controls/lib/lateral_mpc clean
-9
View File
@@ -1,9 +0,0 @@
code_dir := $(shell pwd)
# TODO: Add a global build system
.PHONY: all
all:
cd selfdrive && PYTHONPATH=$(code_dir) PREPAREONLY=1 ./manager.py
-144
View File
@@ -1,144 +0,0 @@
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
opencv-python= "==3.4.2.17"
PyQt5 = "*"
ipython = "*"
azure-common = "*"
azure-nspkg = "*"
azure-storage-blob = "*"
azure-storage-common = "*"
azure-storage-nspkg = "*"
bincopy = "*"
bleach = "*"
boto = "*"
"boto3" = "*"
celery = "*"
control = "*"
datadog = "*"
decorator = "*"
dlib = "*"
dominate = "*"
elasticsearch = "*"
fasteners = "*"
future = "*"
futures = "*"
gevent = "*"
pycocotools = {git = "https://github.com/cocodataset/cocoapi.git",subdirectory = "PythonAPI"}
gunicorn = "*"
"h5py" = "*"
hexdump = "*"
"html5lib" = "*"
imageio = "*"
intervaltree = "*"
ipykernel = "*"
joblib = "*"
json-logging-py = "*"
jupyter = "*"
libarchive = "*"
lru-dict = "*"
lxml = "*"
"mpld3" = "*"
msgpack-python = "*"
nbstripout = "*"
nose-parameterized = "*"
numpy = "*"
osmium = "*"
pbr = "*"
percache = "*"
pprofile = "*"
psutil = "*"
pycurl = "*"
git-pylint-commit-hook = "*"
pymongo = "*"
"pynmea2" = "*"
pypolyline = "*"
pysendfile = "*"
python-logstash = "*"
pyvcd = "*"
redis = "*"
redlock = "*"
"s2sphere" = "*"
scikit-image = "*"
"subprocess32" = "*"
supervisor = "*"
tenacity = "*"
tensorflow-gpu = ""
utm = "*"
"v4l2" = "*"
PyJWT = "==1.4.1"
PyMySQL = "==0.9.2"
Theano = "*"
Werkzeug = "*"
"backports.lzma" = "*"
Flask-Cors = "*"
Flask-SocketIO = "*"
"GeoAlchemy2" = "*"
Pygments = "*"
PyNaCl = "*"
"PySDL2" = "*"
reverse_geocoder = "*"
Shapely = "*"
SQLAlchemy = "*"
uWSGI = "*"
scipy = "*"
fastcluster = "*"
backports-abc = "*"
pygame = "*"
simplejson = "*"
python-logstash-async = "*"
seaborn = "*"
tensorflow-estimator = "*"
pyproj = "*"
mock = "*"
blinker = "*"
gast = "==0.2.2"
matplotlib = "*"
dictdiffer = "*"
aenum = "*"
[packages]
overpy = {git = "https://github.com/commaai/python-overpy.git",ref = "f86529af402d4642e1faeb146671c40284007323"}
atomicwrites = "*"
cffi = "*"
crcmod = "*"
hexdump = "*"
libusb1 = "*"
numpy = "*"
psutil = "*"
pycapnp = "*"
cryptography = "*"
pyserial = "*"
python-dateutil = "*"
pyzmq = "*"
raven = "*"
requests = "*"
setproctitle = "*"
six = "*"
smbus2 = "*"
sympy = "*"
tqdm = "*"
Cython = "*"
PyYAML = "*"
websocket_client = "*"
Logentries = {git = "https://github.com/commaai/le_python.git",ref = "feaeacb48f7f4bdb02c0a8fc092326d4e101b7f2"}
urllib3 = "*"
chardet = "*"
idna = "*"
gunicorn = "*"
utm = "*"
json-rpc = "*"
Flask = "*"
PyJWT = "*"
"Jinja2" = "*"
nose = "*"
pyflakes = "*"
pylint = "*"
pycryptodome = "*"
pillow = "*"
[requires]
python_version = "3.7.3"
Generated
-2714
View File
File diff suppressed because it is too large Load Diff
+231 -167
View File
@@ -1,182 +1,280 @@
[![](https://i.imgur.com/UetIFyH.jpg)](#)
Welcome to openpilot
======
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, it performs the functions of Adaptive Cruise Control (ACC) and Lane Keeping Assist System (LKAS) for selected Honda, Toyota, Acura, Lexus, Chevrolet, Hyundai, Kia. It's about on par with Tesla Autopilot and GM Super Cruise, and better than [all other manufacturers](http://www.thedrive.com/tech/5707/the-war-for-autonomous-driving-part-iii-us-vs-germany-vs-japan).
The openpilot codebase has been written to be concise and to enable rapid prototyping. We look forward to your contributions - improving real vehicle automation has never been easier.
[![](https://i.imgur.com/UelUjKAh.png)](#)
Table of Contents
=======================
* [Community](#community)
* [Hardware](#hardware)
* [What is openpilot?](#what-is-openpilot)
* [Integration with Stock Features](#integration-with-stock-features)
* [Supported Hardware](#supported-hardware)
* [Supported Cars](#supported-cars)
* [Community Maintained Cars](#community-maintained-cars)
* [In Progress Cars](#in-progress-cars)
* [How can I add support for my car?](#how-can-i-add-support-for-my-car)
* [Directory structure](#directory-structure)
* [User Data / chffr Account / Crash Reporting](#user-data--chffr-account--crash-reporting)
* [Community Maintained Cars and Features](#community-maintained-cars-and-features)
* [Installation Instructions](#installation-instructions)
* [Limitations of openpilot ALC and LDW](#limitations-of-openpilot-alc-and-ldw)
* [Limitations of openpilot ACC and FCW](#limitations-of-openpilot-acc-and-fcw)
* [Limitations of openpilot DM](#limitations-of-openpilot-dm)
* [User Data and comma Account](#user-data-and-comma-account)
* [Safety and Testing](#safety-and-testing)
* [Testing on PC](#testing-on-pc)
* [Contributing](#contributing)
* [Community and Contributing](#community-and-contributing)
* [Directory Structure](#directory-structure)
* [Licensing](#licensing)
---
Community
What is openpilot?
------
openpilot is developed by [comma.ai](https://comma.ai/) and users like you.
We have a [Twitter you should follow](https://twitter.com/comma_ai).
Also, we have a several thousand people community on [Discord](https://discord.comma.ai).
[openpilot](http://github.com/commaai/openpilot) is an open source driver assistance system. Currently, openpilot performs the functions of Adaptive Cruise Control (ACC), Automated Lane Centering (ALC), Forward Collision Warning (FCW) and Lane Departure Warning (LDW) for a growing variety of supported [car makes, models and model years](#supported-cars). In addition, while openpilot is engaged, a camera based Driver Monitoring (DM) feature alerts distracted and asleep drivers.
<table>
<tr>
<td><a href="https://www.youtube.com/watch?v=ICOIin4p70w" title="YouTube" rel="noopener"><img src="https://i.imgur.com/gBTo7yB.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=1zCtj3ckGFo" title="YouTube" rel="noopener"><img src="https://i.imgur.com/gNhhcep.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=Qd2mjkBIRx0" title="YouTube" rel="noopener"><img src="https://i.imgur.com/tFnSexp.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=ju12vlBm59E" title="YouTube" rel="noopener"><img src="https://i.imgur.com/3BKiJVy.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=mgAbfr42oI8" title="YouTube" rel="noopener"><img src="https://i.imgur.com/kAtT6Ei.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=394rJKeh76k" title="YouTube" rel="noopener"><img src="https://i.imgur.com/lTt8cS2.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=1iNOc3cq8cs" title="YouTube" rel="noopener"><img src="https://i.imgur.com/ANnuSpe.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=Vr6NgrB-zHw" title="YouTube" rel="noopener"><img src="https://i.imgur.com/Qypanuq.png"></a></td>
</tr>
<tr>
<td><a href="https://www.youtube.com/watch?v=Z5VY5FzgNt4" title="YouTube" rel="noopener"><img src="https://i.imgur.com/3I9XOK2.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=blnhZC7OmMg" title="YouTube" rel="noopener"><img src="https://i.imgur.com/f9IgX6s.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=iRkz7FuJsA8" title="YouTube" rel="noopener"><img src="https://i.imgur.com/Vo5Zvmn.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=IHjEqAKDqjM" title="YouTube" rel="noopener"><img src="https://i.imgur.com/V9Zd81n.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=Ug41KIKF0oo" title="YouTube" rel="noopener"><img src="https://i.imgur.com/3caZ7xM.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=NVR_CdG1FRg" title="YouTube" rel="noopener"><img src="https://i.imgur.com/bAZOwql.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=tkEvIdzdfUE" title="YouTube" rel="noopener"><img src="https://i.imgur.com/EFINEzG.png"></a></td>
<td><a href="https://www.youtube.com/watch?v=_P-N1ewNne4" title="YouTube" rel="noopener"><img src="https://i.imgur.com/gAyAq22.png"></a></td>
</tr>
</table>
Hardware
Integration with Stock Features
------
At the moment openpilot supports the [EON Dashcam DevKit](https://comma.ai/shop/products/eon-dashcam-devkit). A [panda](https://shop.comma.ai/products/panda-obd-ii-dongle) and a [giraffe](https://comma.ai/shop/products/giraffe/) are recommended tools to interface the EON with the car. We'd like to support other platforms as well.
In all supported cars:
* Stock Lane Keep Assist (LKA) and stock ALC are replaced by openpilot ALC, which only functions when openpilot is engaged by the user.
* Stock LDW is replaced by openpilot LDW.
Install openpilot on a neo device by entering ``https://openpilot.comma.ai`` during NEOS setup.
Additionally, on specific supported cars (see ACC column in [supported cars](#supported-cars)):
* Stock ACC is replaced by openpilot ACC.
* openpilot FCW operates in addition to stock FCW.
openpilot should preserve all other vehicle's stock features, including, but are not limited to: FCW, Automatic Emergency Braking (AEB), auto high-beam, blind spot warning, and side collision warning.
Supported Hardware
------
At the moment, openpilot supports the [EON DevKit](https://comma.ai/shop/products/eon-dashcam-devkit) and the [comma two](https://comma.ai/shop/products/comma-two-devkit). A [car harness](https://comma.ai/shop/products/car-harness) is recommended to connect the EON or comma two to the car. In the future, we'd like to support other platforms as well, like gaming PCs.
Supported Cars
------
| Make | Model (US Market Reference)| Supported Package | Lateral | Longitudinal | No Accel Below | No Steer Below | Giraffe |
| ---------------------| ---------------------------| ---------------------| --------| ---------------| -----------------| ---------------|-------------------|
| Acura | ILX 2016-18 | AcuraWatch Plus | Yes | Yes | 25mph<sup>1</sup>| 25mph | Nidec |
| Acura | RDX 2016-18 | AcuraWatch Plus | Yes | Yes | 25mph<sup>1</sup>| 12mph | Nidec |
| Buick<sup>3</sup> | Regal 2018 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Chevrolet<sup>3</sup>| Malibu 2017 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Chevrolet<sup>3</sup>| Volt 2017-18 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Cadillac<sup>3</sup> | ATS 2018 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Chrysler | Pacifica 2017-18 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
| Chrysler | Pacifica Hybrid 2019 | Adaptive Cruise | Yes | Stock | 0mph | 39mph | FCA |
| GMC<sup>3</sup> | Acadia Denali 2018 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Holden<sup>3</sup> | Astra 2017 | Adaptive Cruise | Yes | Yes | 0mph | 7mph | Custom<sup>6</sup>|
| Honda | Accord 2018-19 | All | Yes | Stock | 0mph | 3mph | Bosch |
| Honda | Accord Hybrid 2018-19 | All | Yes | Stock | 0mph | 3mph | Bosch |
| Honda | Civic Sedan/Coupe 2016-18 | Honda Sensing | Yes | Yes | 0mph | 12mph | Nidec |
| Honda | Civic Sedan/Coupe 2019 | Honda Sensing | Yes | Stock | 0mph | 2mph | Bosch |
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | CR-V 2015-16 | Touring | Yes | Yes | 25mph<sup>1</sup>| 12mph | Nidec |
| Honda | CR-V 2017-19 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Yes | Stock | 0mph | 12mph | Bosch |
| Honda | Fit 2018-19 | Honda Sensing | Yes | Yes | 25mph<sup>1</sup>| 12mph | Inverted Nidec |
| Honda | Odyssey 2018-19 | Honda Sensing | Yes | Yes | 25mph<sup>1</sup>| 0mph | Inverted Nidec |
| Honda | Passport 2019 | All | Yes | Yes | 25mph<sup>1</sup>| 12mph | Inverted Nidec |
| Honda | Pilot 2016-18 | Honda Sensing | Yes | Yes | 25mph<sup>1</sup>| 12mph | Nidec |
| Honda | Pilot 2019 | All | Yes | Yes | 25mph<sup>1</sup>| 12mph | Inverted Nidec |
| Honda | Ridgeline 2017-19 | Honda Sensing | Yes | Yes | 25mph<sup>1</sup>| 12mph | Nidec |
| Hyundai | Santa Fe 2019 | All | Yes | Stock | 0mph | 0mph | Custom<sup>5</sup>|
| Hyundai | Elantra 2017-19 | SCC + LKAS | Yes | Stock | 19mph | 34mph | Custom<sup>5</sup>|
| Hyundai | Genesis 2018 | All | Yes | Stock | 19mph | 34mph | Custom<sup>5</sup>|
| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Yes | Stock | 0mph | 9mph | FCA |
| Jeep | Grand Cherokee 2019 | Adaptive Cruise | Yes | Stock | 0mph | 39mph | FCA |
| Kia | Optima 2019 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>5</sup>|
| Kia | Sorento 2018 | All | Yes | Stock | 0mph | 0mph | Custom<sup>5</sup>|
| Kia | Stinger 2018 | SCC + LKAS | Yes | Stock | 0mph | 0mph | Custom<sup>5</sup>|
| Lexus | CT Hybrid 2017-18 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Lexus | ES 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Lexus | ES Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Lexus | RX Hybrid 2016-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Lexus | IS 2017-2019 | All | Yes | Stock | 22mph | 0mph | Toyota |
| Lexus | IS Hybrid 2017 | All | Yes | Stock | 0mph | 0mph | Toyota |
| Subaru | Crosstrek 2018-19 | EyeSight | Yes | Stock | 0mph | 0mph | Subaru |
| Subaru | Impreza 2019-20 | EyeSight | Yes | Stock | 0mph | 0mph | Subaru |
| Toyota | Avalon 2016 | TSS-P | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Avalon 2017-18 | All | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Camry 2018-19 | All | Yes | Stock | 0mph<sup>4</sup> | 0mph | Toyota |
| Toyota | Camry Hybrid 2018-19 | All | Yes | Stock | 0mph<sup>4</sup> | 0mph | Toyota |
| Toyota | C-HR 2017-19 | All | Yes | Stock | 0mph | 0mph | Toyota |
| Toyota | C-HR Hybrid 2017-19 | All | Yes | Stock | 0mph | 0mph | Toyota |
| Toyota | Corolla 2017-19 | All | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Corolla 2020 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Corolla Hatchback 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Corolla Hybrid 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Highlander 2017-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Highlander Hybrid 2017-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Prius 2016 | TSS-P | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Prius 2017-19 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Prius Prime 2017-20 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Rav4 2016 | TSS-P | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Rav4 2017-18 | All | Yes | Yes<sup>2</sup>| 20mph<sup>1</sup>| 0mph | Toyota |
| Toyota | Rav4 2019 | All | Yes | Yes | 0mph | 0mph | Toyota |
| Toyota | Rav4 Hybrid 2016 | TSS-P | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Rav4 Hybrid 2017-18 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Toyota | Sienna 2018 | All | Yes | Yes<sup>2</sup>| 0mph | 0mph | Toyota |
| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
| ----------| ------------------------------| ------------------| -----------------| -------------------| -------------|
| Acura | ILX 2016-18 | AcuraWatch Plus | openpilot | 25mph<sup>5</sup> | 25mph |
| Acura | RDX 2016-18 | AcuraWatch Plus | openpilot | 25mph<sup>5</sup> | 12mph |
| Chrysler | Pacifica 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Chrysler | Pacifica Hybrid 2017-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Chrysler | Pacifica Hybrid 2019-20 | Adaptive Cruise | Stock | 0mph | 39mph |
| Honda | Accord 2018-19 | All | Stock | 0mph | 3mph |
| Honda | Accord Hybrid 2018-19 | All | Stock | 0mph | 3mph |
| Honda | Civic Hatchback 2017-19 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2016-18 | Honda Sensing | openpilot | 0mph | 12mph |
| Honda | Civic Sedan/Coupe 2019 | Honda Sensing | Stock | 0mph | 2mph |
| Honda | CR-V 2015-16 | Touring | openpilot | 25mph<sup>5</sup> | 12mph |
| Honda | CR-V 2017-19 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | CR-V Hybrid 2017-2019 | Honda Sensing | Stock | 0mph | 12mph |
| Honda | Fit 2018-19 | Honda Sensing | openpilot | 25mph<sup>5</sup> | 12mph |
| Honda | Odyssey 2018-20 | Honda Sensing | openpilot | 25mph<sup>5</sup> | 0mph |
| Honda | Passport 2019 | All | openpilot | 25mph<sup>5</sup> | 12mph |
| Honda | Pilot 2016-18 | Honda Sensing | openpilot | 25mph<sup>5</sup> | 12mph |
| Honda | Pilot 2019 | All | openpilot | 25mph<sup>5</sup> | 12mph |
| Honda | Ridgeline 2017-19 | Honda Sensing | openpilot | 25mph<sup>5</sup> | 12mph |
| Hyundai | Elantra 2017-19<sup>1</sup> | SCC + LKAS | Stock | 19mph | 34mph |
| Hyundai | Genesis 2018<sup>1</sup> | All | Stock | 19mph | 34mph |
| Hyundai | Santa Fe 2019<sup>1</sup> | All | Stock | 0mph | 0mph |
| Jeep | Grand Cherokee 2016-18 | Adaptive Cruise | Stock | 0mph | 9mph |
| Jeep | Grand Cherokee 2019 | Adaptive Cruise | Stock | 0mph | 39mph |
| Kia | Optima 2019<sup>1</sup> | SCC + LKAS | Stock | 0mph | 0mph |
| Kia | Sorento 2018<sup>1</sup> | All | Stock | 0mph | 0mph |
| Kia | Stinger 2018<sup>1</sup> | SCC + LKAS | Stock | 0mph | 0mph |
| Lexus | CT Hybrid 2017-18 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Lexus | ES 2019 | All | openpilot | 0mph | 0mph |
| Lexus | ES Hybrid 2019 | All | openpilot | 0mph | 0mph |
| Lexus | IS 2017-2019 | All | Stock | 22mph | 0mph |
| Lexus | IS Hybrid 2017 | All | Stock | 0mph | 0mph |
| Lexus | RX 2016-17 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Lexus | RX 2020 | All | openpilot | 0mph | 0mph |
| Lexus | RX Hybrid 2016-19 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Subaru | Crosstrek 2018-19 | EyeSight | Stock | 0mph | 0mph |
| Subaru | Impreza 2019-20 | EyeSight | Stock | 0mph | 0mph |
| Toyota | Avalon 2016 | TSS-P | Stock<sup>4</sup>| 20mph<sup>5</sup> | 0mph |
| Toyota | Avalon 2017-18 | All | Stock<sup>4</sup>| 20mph<sup>5</sup> | 0mph |
| Toyota | Camry 2018-19 | All | Stock | 0mph<sup>2</sup> | 0mph |
| Toyota | Camry Hybrid 2018-19 | All | Stock | 0mph<sup>2</sup> | 0mph |
| Toyota | C-HR 2017-19 | All | Stock | 0mph | 0mph |
| Toyota | C-HR Hybrid 2017-19 | All | Stock | 0mph | 0mph |
| Toyota | Corolla 2017-19 | All | Stock<sup>4</sup>| 20mph<sup>5</sup> | 0mph |
| Toyota | Corolla 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Corolla Hatchback 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Corolla Hybrid 2020 | All | openpilot | 0mph | 0mph |
| Toyota | Highlander 2017-19 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Highlander Hybrid 2017-19 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Prius 2016 | TSS-P | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Prius 2017-19 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Prius Prime 2017-20 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Rav4 2016 | TSS-P | Stock<sup>4</sup>| 20mph<sup>5</sup> | 0mph |
| Toyota | Rav4 2017-18 | All | Stock<sup>4</sup>| 20mph<sup>5</sup> | 0mph |
| Toyota | Rav4 2019 | All | openpilot | 0mph | 0mph |
| Toyota | Rav4 Hybrid 2016 | TSS-P | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Rav4 Hybrid 2017-18 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Toyota | Rav4 Hybrid 2019-20 | All | openpilot | 0mph | 0mph |
| Toyota | Sienna 2018 | All | Stock<sup>4</sup>| 0mph | 0mph |
| Volkswagen| Golf 2016-19<sup>3</sup> | Driver Assistance | Stock | 0mph | 0mph |
<sup>1</sup>[Comma Pedal](https://community.comma.ai/wiki/index.php/Comma_Pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. Here is how to [build a Comma Pedal](https://medium.com/@jfrux/comma-pedal-building-with-macrofab-6328bea791e8). ***NOTE: The Comma Pedal is not officially supported by [comma.ai](https://comma.ai).*** <br />
<sup>2</sup>When disconnecting the Driver Support Unit (DSU), otherwise longitudinal control is stock ACC. For DSU locations, see [Toyota Wiki page](https://community.comma.ai/wiki/index.php/Toyota). ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).*** <br />
<sup>3</sup>[GM installation guide](https://zoneos.com/volt/). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).*** <br />
<sup>4</sup>28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
<sup>5</sup>Open sourced [Hyundai Giraffe](https://github.com/commaai/neo/tree/master/giraffe/hyundai) is designed for the 2019 Sante Fe; pinout may differ for other Hyundais. <br />
<sup>6</sup>Community built Giraffe, find more information [here](https://zoneos.com/shop/). <br />
<sup>1</sup>Requires a [panda](https://comma.ai/shop/products/panda-obd-ii-dongle) and open sourced [Hyundai giraffe](https://github.com/commaai/neo/tree/master/giraffe/hyundai), designed for the 2019 Sante Fe; pinout may differ for other Hyundai and Kia models. <br />
<sup>2</sup>28mph for Camry 4CYL L, 4CYL LE and 4CYL SE which don't have Full-Speed Range Dynamic Radar Cruise Control. <br />
<sup>3</sup>Requires a [custom connector](https://community.comma.ai/wiki/index.php/Volkswagen#Integration_at_R242_Camera) for the [car harness](https://comma.ai/shop/products/car-harness) <br />
Community Maintained Cars
Community Maintained Cars and Features
------
| Make | Model | Supported Package | Lateral | Longitudinal | No Accel Below | No Steer Below | Giraffe |
| ---------------------| -------------------------| ---------------------| --------| ---------------| -----------------| ---------------|-------------------|
| Tesla | Model S 2012-13 | All | Yes | Not yet | Not applicable | 0mph | Custom<sup>7</sup>|
| Make | Model (US Market Reference) | Supported Package | ACC | No ACC accel below | No ALC below |
| ----------| ------------------------------| ------------------| -----------------| -------------------| -------------|
| Buick | Regal 2018<sup>6</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
| Cadillac | ATS 2018<sup>6</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
| Chevrolet | Malibu 2017<sup>6</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
| Chevrolet | Volt 2017-18<sup>6</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
| GMC | Acadia Denali 2018<sup>6</sup>| Adaptive Cruise | openpilot | 0mph | 7mph |
| Holden | Astra 2017<sup>6</sup> | Adaptive Cruise | openpilot | 0mph | 7mph |
[[Tesla Model S Pull Request]](https://github.com/commaai/openpilot/pull/246) <br />
<sup>7</sup>Community built Giraffe, find more information here [Community Tesla Giraffe](https://github.com/jeankalud/neo/tree/tesla_giraffe/giraffe/tesla) <br />
<sup>4</sup>When disconnecting the Driver Support Unit (DSU), openpilot ACC will replace stock ACC. For DSU locations, see [Toyota Wiki page](https://community.comma.ai/wiki/index.php/Toyota). ***NOTE: disconnecting the DSU disables Automatic Emergency Braking (AEB).*** <br />
<sup>5</sup>[Comma Pedal](https://community.comma.ai/wiki/index.php/Comma_Pedal) is used to provide stop-and-go capability to some of the openpilot-supported cars that don't currently support stop-and-go. Here is how to [build a Comma Pedal](https://medium.com/@jfrux/comma-pedal-building-with-macrofab-6328bea791e8). ***NOTE: The Comma Pedal is not officially supported by [comma](https://comma.ai).*** <br />
<sup>6</sup>Requires a [panda](https://comma.ai/shop/products/panda-obd-ii-dongle) and [community built giraffe](https://zoneos.com/volt/). ***NOTE: disconnecting the ASCM disables Automatic Emergency Braking (AEB).*** <br />
Community Maintained Cars are not confirmed by comma.ai to meet our [safety model](https://github.com/commaai/openpilot/blob/devel/SAFETY.md). Be extra cautious using them.
Community Maintained Cars and Features are not verified by comma to meet our [safety model](SAFETY.md). Be extra cautious using them. They are only available after enabling the toggle in `Settings->Developer->Enable Community Features`.
In Progress Cars
------
- All TSS-P Toyota with Steering Assist and LSS-P Lexus with Steering Assist or Lane Keep Assist.
- All Hyundai with SmartSense.
- All Kia, Genesis with SCC and LKAS.
- All Chrysler, Jeep, Fiat with Adaptive Cruise Control and LaneSense.
- All Subaru with EyeSight.
How can I add support for my car?
Installation Instructions
------
If your car has adaptive cruise control and lane keep assist, you are in luck. Using a [panda](https://comma.ai/shop/products/panda-obd-ii-dongle/) and [cabana](https://community.comma.ai/cabana/), you can understand how to make your car drive by wire.
Install openpilot on a EON by entering ``https://openpilot.comma.ai`` during the installer setup.
We've written guides for [Brand](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84) and [Model](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) ports. These guides might help you after you have the basics figured out.
Follow this [video instructions](https://youtu.be/3nlkomHathI) to properly mount the EON on the windshield. Note: openpilot features an automatic pose calibration routine and openpilot performance should not be affected by small pitch and yaw misalignments caused by imprecise EON mounting.
- BMW, Audi, Volvo, and Mercedes all use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) and can be supported after [FlexRay support](https://github.com/commaai/openpilot/pull/463) is merged.
- We put time into a Ford port, but the steering has a 10 second cutout limitation that makes it unusable.
- The 2016-2017 Honda Accord uses a custom signaling protocol for steering that's unlikely to ever be upstreamed.
Before placing the device on your windshield, check the state and local laws and ordinances where you drive. Some state laws prohibit or restrict the placement of objects on the windshield of a motor vehicle.
Directory structure
You will be able to engage openpilot after reviewing the onboarding screens and finishing the calibration procedure.
Limitations of openpilot ALC and LDW
------
openpilot ALC and openpilot LDW do not automatically drive the vehicle or reduce the amount of attention that must be paid to operate your vehicle. The driver must always keep control of the steering wheel and be ready to correct the openpilot ALC action at all times.
While changing lanes, openpilot is not capable of looking next to you or checking your blind spot. Only nudge the wheel to initiate a lane change after you have confirmed it's safe to do so.
Many factors can impact the performance of openpilot ALC and openpilot LDW, causing them to be unable to function as intended. These include, but are not limited to:
* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
* The road facing camera is obstructed, covered or damaged by mud, ice, snow, etc.
* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
* The EON is mounted incorrectly.
* When in sharp curves, like on-off ramps, intersections etc...; openpilot is designed to be limited in the amount of steering torque it can produce.
* In the presence of restricted lanes or construction zones.
* When driving on highly banked roads or in presence of strong cross-wind.
* Extremely hot or cold temperatures.
* Bright light (due to oncoming headlights, direct sunlight, etc.).
* Driving on hills, narrow, or winding roads.
The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
Limitations of openpilot ACC and FCW
------
openpilot ACC and openpilot FCW are not systems that allow careless or inattentive driving. It is still necessary for the driver to pay close attention to the vehicles surroundings and to be ready to re-take control of the gas and the brake at all times.
Many factors can impact the performance of openpilot ACC and openpilot FCW, causing them to be unable to function as intended. These include, but are not limited to:
* Poor visibility (heavy rain, snow, fog, etc.) or weather conditions that may interfere with sensor operation.
* The road facing camera or radar are obstructed, covered, or damaged by mud, ice, snow, etc.
* Obstruction caused by applying excessive paint or adhesive products (such as wraps, stickers, rubber coating, etc.) onto the vehicle.
* The EON is mounted incorrectly.
* Approaching a toll booth, a bridge or a large metal plate.
* When driving on roads with pedestrians, cyclists, etc...
* In presence of traffic signs or stop lights, which are not detected by openpilot at this time.
* When the posted speed limit is below the user selected set speed. openpilot does not detect speed limits at this time.
* In presence of vehicles in the same lane that are not moving.
* When abrupt braking maneuvers are required. openpilot is designed to be limited in the amount of deceleration and acceleration that it can produce.
* When surrounding vehicles perform close cut-ins from neighbor lanes.
* Driving on hills, narrow, or winding roads.
* Extremely hot or cold temperatures.
* Bright light (due to oncoming headlights, direct sunlight, etc.).
* Interference from other equipment that generates radar waves.
The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. It is the driver's responsibility to be in control of the vehicle at all times.
Limitations of openpilot DM
------
openpilot DM should not be considered an exact measurements of the status of alertness of the driver.
Many factors can impact the performance of openpilot DM, causing it to be unable to function as intended. These include, but are not limited to:
* Low light conditions, such as driving at night or in dark tunnels.
* Bright light (due to oncoming headlights, direct sunlight, etc.).
* The driver face is partially or completely outside field of view of the driver facing camera.
* Right hand driving vehicles.
* The driver facing camera is obstructed, covered, or damaged.
The list above does not represent an exhaustive list of situations that may interfere with proper operation of openpilot components. A driver should not rely on openpilot DM to assess their level of attention.
User Data and comma Account
------
By default, openpilot uploads the driving data to our servers. You can also access your data by pairing with the comma connect app ([iOS](https://apps.apple.com/us/app/comma-connect/id1456551889), [Android](https://play.google.com/store/apps/details?id=ai.comma.connect&hl=en_US)). We use your data to train better models and improve openpilot for everyone.
openpilot is open source software: the user is free to disable data collection if they wish to do so.
openpilot logs the road facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
The driver facing camera is only logged if you explicitly opt-in in settings. The microphone is not recorded.
By using openpilot, you agree to [our Privacy Policy](https://my.comma.ai/privacy). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma for the use of this data.
Safety and Testing
----
* openpilot observes ISO26262 guidelines, see [SAFETY.md](SAFETY.md) for more detail.
* openpilot has software in the loop [tests](run_docker_tests.sh) that run on every commit.
* The safety model code lives in panda and is written in C, see [code rigor](https://github.com/commaai/panda#code-rigor) for more details.
* panda has software in the loop [safety tests](https://github.com/commaai/panda/tree/master/tests/safety).
* Internally, we have a hardware in the loop Jenkins test suite that builds and unit tests the various processes.
* panda has additional hardware in the loop [tests](https://github.com/commaai/panda/blob/master/Jenkinsfile).
* We run the latest openpilot in a testing closet containing 10 EONs continuously replaying routes.
Testing on PC
------
Check out the tools directory in master: lots of tools you can use to replay driving data, test and develop openpilot from your pc.
Community and Contributing
------
openpilot is developed by [comma](https://comma.ai/) and by users like you. We welcome both pull requests and issues on [GitHub](http://github.com/commaai/openpilot). Bug fixes and new car ports are encouraged.
You can add support for your car by following guides we have written for [Brand](https://medium.com/@comma_ai/how-to-write-a-car-port-for-openpilot-7ce0785eda84) and [Model](https://medium.com/@comma_ai/openpilot-port-guide-for-toyota-models-e5467f4b5fe6) ports. Generally, a car with adaptive cruise control and lane keep assist is a good candidate. [Join our Discord](https://discord.comma.ai) to discuss car ports: most car makes have a dedicated channel.
Want to get paid to work on openpilot? [comma is hiring](https://comma.ai/jobs/). We also have a [bounty program](https://comma.ai/bounties.html).
And [follow us on Twitter](https://twitter.com/comma_ai).
Directory Structure
------
.
├── apk # The apk files used for the UI
├── cereal # The messaging spec used for all logs on EON
├── cereal # The messaging spec and libs used for all logs on EON
├── common # Library like functionality we've developed here
├── installer/updater # Manages auto-updates of openpilot
├── opendbc # Files showing how to interpret data from cars
├── panda # Code used to communicate on CAN and LIN
├── panda # Code used to communicate on CAN
├── phonelibs # Libraries used on EON
├── pyextra # Libraries used on EON
└── selfdrive # Code needed to drive the car
├── assets # Fonts and images for UI
├── athena # Allows communication with the app
├── boardd # Daemon to talk to the board
├── can # Helpers for parsing CAN messages
├── camerad # Driver to capture images from the camera sensors
├── car # Car specific code to read states and control actuators
├── common # Shared C/C++ code for the daemons
├── controls # Perception, planning and controls
@@ -184,54 +282,20 @@ Directory structure
├── locationd # Soon to be home of precise location
├── logcatd # Android logcat as a service
├── loggerd # Logger and uploader of car data
├── modeld # Driving and monitoring model runners
├── proclogd # Logs information from proc
├── sensord # IMU / GPS interface code
├── test # Car simulator running code through virtual maneuvers
── ui # The UI
└── visiond # Vision pipeline
├── tests # Unit tests, system tests and a car simulator
── ui # The UI
To understand how the services interact, see `selfdrive/service_list.yaml`
User Data / chffr Account / Crash Reporting
------
By default, openpilot creates an account and includes a client for chffr, our dashcam app. We use your data to train better models and improve openpilot for everyone.
It's open source software, so you are free to disable it if you wish.
It logs the road facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
The user facing camera is only logged if you explicitly opt-in in settings.
It does not log the microphone.
By using it, you agree to [our privacy policy](https://community.comma.ai/privacy.html). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma.ai. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma.ai for the use of this data.
Testing on PC
------
Check out [openpilot-tools](https://github.com/commaai/openpilot-tools): lots of tools you can use to replay driving data, test and develop openpilot from your pc.
Also, within openpilot there is a rudimentary infrastructure to run a basic simulation and generate a report of openpilot's behavior in different longitudinal control scenarios.
```bash
# Requires working docker
./run_docker_tests.sh
```
Contributing
------
We welcome both pull requests and issues on [github](http://github.com/commaai/openpilot). Bug fixes and new car ports encouraged.
We also have a [bounty program](https://comma.ai/bounties.html).
Want to get paid to work on openpilot? [comma.ai is hiring](https://comma.ai/jobs/)
To understand how the services interact, see `cereal/service_list.yaml`.
Licensing
------
openpilot is released under the MIT license. Some parts of the software are released under other licenses as specified.
Any user of this software shall indemnify and hold harmless Comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys fees and costs) which arise out of, relate to or result from any use of this software by user.
Any user of this software shall indemnify and hold harmless comma.ai, Inc. and its directors, officers, employees, agents, stockholders, affiliates, subcontractors and customers from and against all allegations, claims, actions, suits, demands, damages, liabilities, obligations, losses, settlements, judgments, costs and expenses (including without limitation attorneys fees and costs) which arise out of, relate to or result from any use of this software by user.
**THIS IS ALPHA QUALITY SOFTWARE FOR RESEARCH PURPOSES ONLY. THIS IS NOT A PRODUCT.
YOU ARE RESPONSIBLE FOR COMPLYING WITH LOCAL LAWS AND REGULATIONS.
-36
View File
@@ -1,36 +0,0 @@
Welcome to chffrplus
======
[chffrplus](https://github.com/commaai/chffrplus) is an open source dashcam.
This is the shipping reference software for the comma EON Dashcam DevKit. It keeps many of the niceities of [openpilot](https://github.com/commaai/openpilot), like high quality sensors, great camera, and good autostart and stop. Though unlike openpilot, it cannot control your car. chffrplus can interface with your car through a [panda](https://shop.comma.ai/products/panda-obd-ii-dongle), but just like our dashcam app [chffr](https://getchffr.com/), it is read only.
It integrates with the rest of the comma ecosystem, so you can view your drives on the [chffr](https://getchffr.com/) app for Android or iOS, and reverse engineer your car with [cabana](https://community.comma.ai/cabana/?demo=1).
Hardware
------
Right now chffrplus supports the [EON Dashcam DevKit](https://shop.comma.ai/products/eon-dashcam-devkit) for hardware to run on.
Install chffrplus on a EON device by entering ``https://chffrplus.comma.ai`` during NEOS setup.
User Data / chffr Account / Crash Reporting
------
By default chffrplus creates an account and includes a client for chffr, our dashcam app.
It's open source software, so you are free to disable it if you wish.
It logs the road facing camera, CAN, GPS, IMU, magnetometer, thermal sensors, crashes, and operating system logs.
It does not log the user facing camera or the microphone.
By using it, you agree to [our privacy policy](https://beta.comma.ai/privacy.html). You understand that use of this software or its related services will generate certain types of user data, which may be logged and stored at the sole discretion of comma.ai. By accepting this agreement, you grant an irrevocable, perpetual, worldwide right to comma.ai for the use of this data.
Licensing
------
chffrplus is released under the MIT license.
+48 -2
View File
@@ -1,8 +1,54 @@
Version 0.7.2 (2020-02-07)
========================
* ECU firmware version based fingerprinting for Honda & Toyota
* New driving model: improved path prediction during turns and lane changes and better lead speed tracking
* Improve driver monitoring under extreme lighting and add low accuracy alert
* Support for 2019 Rav4 Hybrid thanks to illumiN8i!
* Support for 2016, 2017 and 2020 Lexus RX thanks to illumiN8i!
* Support for 2020 Chrysler Pacifica Hybrid thanks to adhintz!
Version 0.7.1 (2020-01-20)
========================
* comma two support!
* Lane Change Assist above 45 mph!
* Replace zmq with custom messaging library, msgq!
* Supercombo model: calibration and driving models are combined for better lead estimate
* More robust updater thanks to jyoung8607! Requires NEOS update
* Improve low speed ACC tuning
Version 0.7 (2019-12-13)
========================
* Move to SCons build system!
* Add Lane Departure Warning (LDW) for all supported vehicles!
* NEOS update: increase wifi speed thanks to jyoung8607!
* Adaptive driver monitoring based on scene
* New driving model trained end-to-end: improve lane lines and lead detection
* Smarter torque limit alerts for all cars
* Improve GM longitudinal control: proper computations for 15Hz radar
* Move GM port, Toyota with DSU removed, comma pedal in community features; toggle switch required
* Remove upload over cellular toggle: only upload qlog and qcamera files if not on wifi
* Refactor Panda code towards ISO26262 and SIL2 compliancy
* Forward stock FCW for Honda Nidec
* Volkswagen port now standard: comma Harness intercepts stock camera
Version 0.6.6 (2019-11-05)
========================
* Volkswagen support thanks to jyoung8607!
* Toyota Corolla Hybrid with TSS 2.0 support thanks to u8511049!
* Lexus ES with TSS 2.0 support thanks to energee!
* Fix GM ignition detection and lock safety mode not required anymore
* Log panda firmware and dongle ID thanks to martinl!
* New driving model: improve path prediction and lead detection
* New driver monitoring model, 4x smaller and running on DSP
* Display an alert and don't start openpilot if panda has wrong firmware
* Fix bug preventing EON from terminating processes after a drive
* Remove support for Toyota giraffe without the 120Ohm resistor
Version 0.6.5 (2019-10-07)
========================
* NEOS update: upgrade to Python3 and new installer!
* comma Harness support!
* New driving model: lateral control has lower reliance on lanelines
* New driving model: improve path prediction
* New driver monitoring model: more accurate face and eye detection
* Redesign offroad screen to display updates and alerts
* Increase maximum allowed acceleration
@@ -62,7 +108,7 @@ Version 0.6 (2019-07-01)
* Panda safety code is MISRA compliant and ships with a signed version on release2
* New NEOS is 500MB smaller and has a reproducible usr/pipenv
* Lexus ES Hybrid support thanks to wocsor!
* Improve tuning for supported Toyota with TSS2
* Improve tuning for supported Toyota with TSS 2.0
* Various other stability improvements
Version 0.5.13 (2019-05-31)
+16 -133
View File
@@ -1,16 +1,26 @@
openpilot Safety
======
openpilot is an Adaptive Cruise Control (ACC) and Lane Keeping Assist (LKA) system.
Like other ACC and LKA systems, openpilot requires the driver to be alert and to
pay attention at all times. We repeat, **driver alertness is necessary, but not
sufficient, for openpilot to be used safely**.
openpilot is an Adaptive Cruise Control (ACC) and Automated Lane Centering (ALC) system.
Like other ACC and ALC systems, openpilot is a failsafe passive system and it requires the
driver to be alert and to pay attention at all times.
In order to enforce driver alertness, openpilot includes a driver monitoring feature
that alerts the driver when distracted.
However, even with an attentive driver, we must make further efforts for the system to be
safe. We have designed openpilot with two other safety considerations.
safe. We repeat, **driver alertness is necessary, but not sufficient, for openpilot to be
used safely** and openpilot is provided with no warranty of fitness for any purpose.
openpilot is developed in good faith to be compliant with FMVSS requirements and to follow
industry standards of safety for Level 2 Driver Assistance Systems. In particular, we observe
ISO26262 guidelines, including those from [pertinent documents](https://www.nhtsa.gov/sites/nhtsa.dot.gov/files/documents/13498a_812_573_alcsystemreport.pdf)
released by NHTSA. In addition, we impose strict coding guidelines (like [MISRA C : 2012](https://www.misra.org.uk/MISRAHome/MISRAC2012/tabid/196/Default.aspx))
on parts of openpilot that are safety relevant. We also perform software-in-the-loop,
hardware-in-the-loop and in-vehicle tests before each software release.
Following Hazard and Risk Analysis and FMEA, at a very high level, we have designed openpilot
ensuring two main safety requirements.
1. The driver must always be capable to immediately retake manual control of the vehicle,
by stepping on either pedal or by pressing the cancel button.
@@ -18,134 +28,7 @@ safe. We have designed openpilot with two other safety considerations.
react. This means that while the system is engaged, the actuators are constrained
to operate within reasonable limits.
Following are details of the car specific safety implementations:
Honda/Acura
------
- While the system is engaged, gas, brake and steer commands are subject to the same limits used by
the stock system.
- Without an interceptor, the gas is controlled by the Powertrain Control Module (PCM).
The PCM limits acceleration to what is reasonable for a cruise control system. With an
interceptor, the gas is clipped to 60%.
- The brake is controlled by the 0x1FA CAN message. This message allows full
braking, although the panda firmware and openpilot clip it to 1/4th of the max.
This is approximately 0.3g of braking.
- Steering is controlled by the 0xE4 CAN message. The Electronic Power Steering (EPS)
controller in the car limits the torque to a very small amount, so regardless of the
message, the controller cannot jerk the wheel.
- Brake and gas pedal pressed signals are contained in the 0x17C CAN message. A rising edge of
either signals triggers a disengagement, which is enforced by the panda firmware and by openpilot. The
white led on the panda signifies if the panda is allowing control messages.
- Honda CAN uses both a counter and a checksum to ensure integrity and prevent
replay of the same message.
Toyota/Lexus
------
- While the system is engaged, gas, brake and steer commands are subject to the same limits used by
the stock system.
- With the stock Driving Support Unit (DSU) connected (or in DSU-less models like Camry and C-HR),
the acceleration is controlled by the stock system and is subject to the stock adaptive cruise
control limits. Without the stock DSU connected, the acceleration command is controlled by the
0x343 CAN message and its value is limited between .3g of deceleration and .15g of acceleration
by the panda firmware and by openpilot. The acceleration command is ignored by the Engine Control
Module (ECM) while the cruise control system is disengaged.
- Steering torque is controlled through the 0x2E4 CAN message and it's limited by the panda firmware and by
openpilot to a value between -1500 and 1500. In addition, the vehicle EPS unit will not respond to
commands outside these limits. A steering torque rate limit is enforced by the panda firmware and by
openpilot, so that the commanded steering torque must rise from 0 to max value no faster than
1.5s. Commanded steering torque is limited by the panda firmware and by openpilot to be no more than 350
units above the actual EPS generated motor torque to ensure limited differences between
commanded and actual torques.
- Brake and gas pedal pressed signals are contained in the 0x224 and 0x1D2 CAN messages,
respectively. A rising edge of either signals triggers a disengagement, which is enforced by the
panda firmware and by openpilot. Additionally, the cruise control system disengages on the rising edge of
the brake pedal pressed signal.
- The cruise control system state is contained in the 0x1D2 message. No control messages are
allowed if the cruise control system is not active. This is enforced by openpilot and the
panda firmware. The white led on the panda signifies if the panda is allowing control messages.
GM/Chevrolet
------
- While the system is engaged, gas, brake and steer commands are subject to the same limits used by
the stock system.
- The gas and regen are controlled by the 0x2CB message and it's limited by the panda firmware and by
openpilot to a value between 1404 and 3072. the minimum value correspond to a mild decel due to regen,
while 3072 correspond to approximately 0.18g of acceleration from stop.
- The friction brakes are controlled by the 0x315 message and its value is limited by the panda firmware
and openpilot to 350. This is approximately 0.3g of braking.
- Steering torque is controlled through the 0x180 CAN message and it's limited by the panda firmware and by
openpilot to a value between -300 and 300. In addition, the vehicle EPS unit will fault for
commands outside these limits. A steering torque rate limit is enforced by the panda firmware and by
openpilot, so that the commanded steering torque must rise from 0 to max value no faster than
0.75s. Commanded steering torque is gradually limited by the panda firmware and by openpilot if the driver's
torque exceeds 12 units in the opposite dicrection to ensure limited applied torque against the
driver's will.
- Brake pedal and gas pedal potentiometer signals are contained in the 0xF1 and 0x1A1 CAN messages,
respectively. A rising edge of either signals triggers a disengagement, which is enforced by the
panda firmware and by openpilot. Additionally, the cruise control system disengages on the rising edge of
the brake pedal pressed signal. The regen paddle pressed signal is in the 0xBD message. When the
regen paddle is pressed, a disengagement is enforced by both the firmware and by openpilot.
- GM CAN uses both a counter and a checksum to ensure integrity and prevent
replay of the same message.
Hyundai/Kia (Lateral only)
------
- While the system is engaged, steer commands are subject to the same limits used by
the stock system.
- Steering torque is controlled through the 0x340 CAN message and it's limited by the panda firmware and by
openpilot to a value between -255 and 255. In addition, the vehicle EPS unit will fault for
commands outside the values of -409 and 409. A steering torque rate limit is enforced by the panda firmware and by
openpilot, so that the commanded steering torque must rise from 0 to max value no faster than
0.85s. Commanded steering torque is gradually limited by the panda firmware and by openpilot if the driver's
torque exceeds 50 units in the opposite dicrection to ensure limited applied torque against the
driver's will.
Chrysler/Jeep/Fiat (Lateral only)
------
- While the system is engaged, steer commands are subject to the same limits used by
the stock system.
- Steering torque is controlled through the 0x292 CAN message and it's limited by the panda firmware and by
openpilot to a value between -261 and 261. In addition, the vehicle EPS unit will fault for
commands outside these limits. A steering torque rate limit is enforced by the panda firmware and by
openpilot, so that the commanded steering torque must rise from 0 to max value no faster than
0.87s. Commanded steering torque is limited by the panda firmware and by openpilot to be no more than 80
units above the actual EPS generated motor torque to ensure limited differences between
commanded and actual torques.
Subaru (Lateral only)
------
- While the system is engaged, steer commands are subject to the same limits used by
the stock system.
- Steering torque is controlled through the 0x122 CAN message and it's limited by the panda firmware and by
openpilot to a value between -255 and 255. In addition, the vehicle EPS unit will fault for
commands outside the values of -2047 and 2047. A steering torque rate limit is enforced by the panda firmware and by
openpilot, so that the commanded steering torque must rise from 0 to max value no faster than
0.41s. Commanded steering torque is gradually limited by the panda firmware and by openpilot if the driver's
torque exceeds 60 units in the opposite dicrection to ensure limited applied torque against the
driver's will.
For vehicle specific implementation of the safety concept, refer to `panda/board/safety/`.
**Extra note**: comma.ai strongly discourages the use of openpilot forks with safety code either missing or
not fully meeting the above requirements.
+232
View File
@@ -0,0 +1,232 @@
import os
import subprocess
import sys
import platform
AddOption('--test',
action='store_true',
help='build test files')
AddOption('--asan',
action='store_true',
help='turn on ASAN')
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
if platform.system() == "Darwin":
arch = "Darwin"
if arch == "aarch64":
lenv = {
"LD_LIBRARY_PATH": '/data/data/com.termux/files/usr/lib',
"PATH": os.environ['PATH'],
"ANDROID_DATA": os.environ['ANDROID_DATA'],
"ANDROID_ROOT": os.environ['ANDROID_ROOT'],
}
cpppath = [
"#phonelibs/opencl/include",
]
libpath = [
"#phonelibs/snpe/aarch64-android-clang3.8",
"/usr/lib",
"/data/data/com.termux/files/usr/lib",
"/system/vendor/lib64",
"/system/comma/usr/lib",
"#phonelibs/nanovg",
"#phonelibs/libyuv/lib",
]
cflags = ["-DQCOM", "-mcpu=cortex-a57"]
cxxflags = ["-DQCOM", "-mcpu=cortex-a57"]
rpath = ["/system/vendor/lib64"]
else:
lenv = {
"PATH": "#external/bin:" + os.environ['PATH'],
}
cpppath = [
"#phonelibs/capnp-cpp/include",
"#phonelibs/capnp-c/include",
"#phonelibs/zmq/x64/include",
"#external/tensorflow/include",
]
if arch == "Darwin":
libpath = [
"#phonelibs/capnp-cpp/mac/lib",
"#phonelibs/capnp-c/mac/lib",
"#phonelibs/libyuv/mac/lib",
"#cereal",
"#selfdrive/common",
"/usr/local/lib",
"/System/Library/Frameworks/OpenGL.framework/Libraries",
]
else:
libpath = [
"#phonelibs/capnp-cpp/x64/lib",
"#phonelibs/capnp-c/x64/lib",
"#phonelibs/snpe/x86_64-linux-clang",
"#phonelibs/zmq/x64/lib",
"#phonelibs/libyuv/x64/lib",
"#external/zmq/lib",
"#external/tensorflow/lib",
"#cereal",
"#selfdrive/common",
"/usr/lib",
"/usr/local/lib",
]
rpath = ["phonelibs/capnp-cpp/x64/lib",
"phonelibs/zmq/x64/lib",
"external/tensorflow/lib",
"cereal",
"selfdrive/common"]
# allows shared libraries to work globally
rpath = [os.path.join(os.getcwd(), x) for x in rpath]
cflags = []
cxxflags = []
ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"] if GetOption('asan') else []
ldflags_asan = ["-fsanitize=address"] if GetOption('asan') else []
# change pythonpath to this
lenv["PYTHONPATH"] = Dir("#").path
env = Environment(
ENV=lenv,
CCFLAGS=[
"-g",
"-fPIC",
"-O2",
"-Werror=implicit-function-declaration",
"-Werror=incompatible-pointer-types",
"-Werror=int-conversion",
"-Werror=return-type",
"-Werror=format-extra-args",
] + cflags + ccflags_asan,
CPPPATH=cpppath + [
"#",
"#selfdrive",
"#phonelibs/bzip2",
"#phonelibs/libyuv/include",
"#phonelibs/openmax/include",
"#phonelibs/json/src",
"#phonelibs/json11",
"#phonelibs/eigen",
"#phonelibs/curl/include",
"#phonelibs/opencv/include",
"#phonelibs/libgralloc/include",
"#phonelibs/android_frameworks_native/include",
"#phonelibs/android_hardware_libhardware/include",
"#phonelibs/android_system_core/include",
"#phonelibs/linux/include",
"#phonelibs/snpe/include",
"#phonelibs/nanovg",
"#selfdrive/common",
"#selfdrive/camerad",
"#selfdrive/camerad/include",
"#selfdrive/loggerd/include",
"#selfdrive/modeld",
"#cereal/messaging",
"#cereal",
"#opendbc/can",
],
CC='clang',
CXX='clang++',
LINKFLAGS=ldflags_asan,
RPATH=rpath,
CFLAGS=["-std=gnu11"] + cflags,
CXXFLAGS=["-std=c++14"] + cxxflags,
LIBPATH=libpath +
[
"#cereal",
"#selfdrive/common",
"#phonelibs",
]
)
if os.environ.get('SCONS_CACHE'):
CacheDir('/tmp/scons_cache')
node_interval = 5
node_count = 0
def progress_function(node):
global node_count
node_count += node_interval
sys.stderr.write("progress: %d\n" % node_count)
if os.environ.get('SCONS_PROGRESS'):
Progress(progress_function, interval=node_interval)
SHARED = False
def abspath(x):
if arch == 'aarch64':
pth = os.path.join("/data/pythonpath", x[0].path)
env.Depends(pth, x)
return File(pth)
else:
# rpath works elsewhere
return x[0].path.rsplit("/", 1)[1][:-3]
#zmq = 'zmq'
# still needed for apks
zmq = FindFile("libzmq.a", libpath)
Export('env', 'arch', 'zmq', 'SHARED')
# cereal and messaging are shared with the system
SConscript(['cereal/SConscript'])
if SHARED:
cereal = abspath([File('cereal/libcereal_shared.so')])
messaging = abspath([File('cereal/libmessaging_shared.so')])
else:
cereal = [File('#cereal/libcereal.a')]
messaging = [File('#cereal/libmessaging.a')]
Export('cereal', 'messaging')
SConscript(['selfdrive/common/SConscript'])
Import('_common', '_visionipc', '_gpucommon', '_gpu_libs')
if SHARED:
common, visionipc, gpucommon = abspath(common), abspath(visionipc), abspath(gpucommon)
else:
common = [_common, 'json']
visionipc = _visionipc
gpucommon = [_gpucommon] + _gpu_libs
Export('common', 'visionipc', 'gpucommon')
SConscript(['opendbc/can/SConscript'])
SConscript(['common/SConscript'])
SConscript(['common/kalman/SConscript'])
SConscript(['phonelibs/SConscript'])
if arch != "Darwin":
SConscript(['selfdrive/camerad/SConscript'])
SConscript(['selfdrive/modeld/SConscript'])
SConscript(['selfdrive/controls/lib/cluster/SConscript'])
SConscript(['selfdrive/controls/lib/lateral_mpc/SConscript'])
SConscript(['selfdrive/controls/lib/longitudinal_mpc/SConscript'])
SConscript(['selfdrive/boardd/SConscript'])
SConscript(['selfdrive/proclogd/SConscript'])
SConscript(['selfdrive/ui/SConscript'])
SConscript(['selfdrive/loggerd/SConscript'])
if arch == "aarch64":
SConscript(['selfdrive/logcatd/SConscript'])
SConscript(['selfdrive/sensord/SConscript'])
SConscript(['selfdrive/clocksd/SConscript'])
SConscript(['selfdrive/locationd/SConscript'])
# TODO: finish cereal, dbcbuilder, MPC
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
View File
Binary file not shown.
Executable
+11
View File
@@ -0,0 +1,11 @@
#!/usr/bin/bash
mode=$1
if [ $1 -eq 1 ]; then
printf %s "1" > /data/params/d/DragonBTG
fi
if [ $1 -eq 0 ]; then
printf %s "0" > /data/params/d/DragonBTG
fi
rm -rf /data/openpilot/selfdrive/boardd/boardd && reboot
+1
View File
@@ -0,0 +1 @@
.sconsign.dblite
+8
View File
@@ -3,4 +3,12 @@ node_modules
package-lock.json
*.pyc
__pycache__
.*.swp
.*.swo
libcereal*.a
libmessaging.*
libmessaging_shared.*
services.h
.sconsign.dblite
libcereal_shared.*
+19
View File
@@ -0,0 +1,19 @@
from ubuntu:16.04
RUN apt-get update && apt-get install -y libzmq3-dev clang wget git autoconf libtool curl make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
RUN pyenv install 3.7.3
RUN pyenv global 3.7.3
RUN pyenv rehash
RUN pip3 install pyyaml==5.1.2 Cython==0.29.14 scons==3.1.1 pycapnp==0.6.4
WORKDIR /project/cereal
COPY install_capnp.sh .
RUN ./install_capnp.sh
ENV PYTHONPATH=/project
COPY . .
RUN scons -c && scons -j$(nproc)
-62
View File
@@ -1,62 +0,0 @@
PWD := $(shell pwd)
SRCS := log.capnp car.capnp
GENS := gen/cpp/car.capnp.c++ gen/cpp/log.capnp.c++
JS := gen/js/car.capnp.js gen/js/log.capnp.js
UNAME_M ?= $(shell uname -m)
GENS += gen/c/car.capnp.c gen/c/log.capnp.c gen/c/include/c++.capnp.h gen/c/include/java.capnp.h
ifeq ($(UNAME_M),x86_64)
ifneq (, $(shell which capnpc-java))
GENS += gen/java/Car.java gen/java/Log.java
else
$(warning capnpc-java not found, skipping java build)
endif
endif
ifeq ($(UNAME_M),aarch64)
CAPNPC=PATH=$(PWD)/../phonelibs/capnp-cpp/aarch64/bin/:$$PATH capnpc
else
CAPNPC=capnpc
endif
.PHONY: all
all: $(GENS)
js: $(JS)
.PHONY: clean
clean:
rm -rf gen
rm -rf node_modules
rm -rf package-lock.json
gen/c/%.capnp.c: %.capnp
@echo "[ CAPNPC C ] $@"
mkdir -p gen/c/
$(CAPNPC) '$<' -o c:gen/c/
gen/js/%.capnp.js: %.capnp
@echo "[ CAPNPC JavaScript ] $@"
mkdir -p gen/js/
sh ./generate_javascript.sh
gen/cpp/%.capnp.c++: %.capnp
@echo "[ CAPNPC C++ ] $@"
mkdir -p gen/cpp/
$(CAPNPC) '$<' -o c++:gen/cpp/
gen/java/Car.java gen/java/Log.java: $(SRCS)
@echo "[ CAPNPC java ] $@"
mkdir -p gen/java/
$(CAPNPC) $^ -o java:gen/java
# c-capnproto needs some empty headers
gen/c/include/c++.capnp.h gen/c/include/java.capnp.h:
mkdir -p gen/c/include
touch '$@'
+42
View File
@@ -0,0 +1,42 @@
What is cereal?
----
cereal is both a messaging spec for robotics systems as well as generic high performance IPC pub sub messaging with a single publisher and multiple subscribers.
Imagine this use case:
* A sensor process reads gyro measurements directly from an IMU and publishes a sensorEvents packet
* A calibration process subscribes to the sensorEvents packet to use the IMU
* A localization process subscribes to the sensorEvents packet to use the IMU also
Messaging Spec
----
You'll find the message types in [log.capnp](log.capnp). It uses [Cap'n proto](https://capnproto.org/capnp-tool.html) and defines one struct called Event.
All Events have a logMonoTime and a valid. Then a big union defines the packet type.
Pub Sub Backends
----
cereal supports two backends, one based on [zmq](https://zeromq.org/), the other called msgq, a custom pub sub based on shared memory that doesn't require the bytes to pass through the kernel.
Example
---
```python
import cereal.messaging as messaging
# in subscriber
sm = messaging.SubMaster(['sensorEvents'])
while 1:
sm.update()
print(sm['sensorEvents'])
# in publisher
pm = messaging.PubMaster(['sensorEvents'])
dat = messaging.new_message()
dat.init('sensorEvents', 1)
dat.sensorEvents[0] = {"gyro": {"v": [0.1, -0.1, 0.1]}}
pm.send('sensorEvents', dat)
```
+68
View File
@@ -0,0 +1,68 @@
Import('env', 'arch', 'zmq')
gen_dir = Dir('gen')
messaging_dir = Dir('messaging')
# TODO: remove src-prefix and cereal from command string. can we set working directory?
env.Command(["gen/c/include/c++.capnp.h", "gen/c/include/java.capnp.h"], [], "mkdir -p " + gen_dir.path + "/c/include && touch $TARGETS")
env.Command(
['gen/c/car.capnp.c', 'gen/c/log.capnp.c', 'gen/c/car.capnp.h', 'gen/c/log.capnp.h'],
['car.capnp', 'log.capnp'],
'capnpc $SOURCES --src-prefix=cereal -o c:' + gen_dir.path + '/c/')
env.Command(
['gen/cpp/car.capnp.c++', 'gen/cpp/log.capnp.c++', 'gen/cpp/car.capnp.h', 'gen/cpp/log.capnp.h'],
['car.capnp', 'log.capnp'],
'capnpc $SOURCES --src-prefix=cereal -o c++:' + gen_dir.path + '/cpp/')
import shutil
if shutil.which('capnpc-java'):
env.Command(
['gen/java/Car.java', 'gen/java/Log.java'],
['car.capnp', 'log.capnp'],
'capnpc $SOURCES --src-prefix=cereal -o java:' + gen_dir.path + '/java/')
# TODO: remove non shared cereal and messaging
cereal_objects = env.SharedObject([
'gen/c/car.capnp.c',
'gen/c/log.capnp.c',
'gen/cpp/car.capnp.c++',
'gen/cpp/log.capnp.c++',
])
env.Library('cereal', cereal_objects)
env.SharedLibrary('cereal_shared', cereal_objects, LIBS=["capnp_c"])
cereal_dir = Dir('.')
services_h = env.Command(
['services.h'],
['service_list.yaml', 'services.py'],
'python3 ' + cereal_dir.path + '/services.py > $TARGET')
messaging_objects = env.SharedObject([
'messaging/messaging.cc',
'messaging/impl_zmq.cc',
'messaging/impl_msgq.cc',
'messaging/msgq.cc',
])
messaging_lib = env.Library('messaging', messaging_objects)
Depends('messaging/impl_zmq.cc', services_h)
# note, this rebuilds the deps shared, zmq is statically linked to make APK happy
# TODO: get APK to load system zmq to remove the static link
shared_lib_shared_lib = [zmq, 'm', 'stdc++'] + ["gnustl_shared"] if arch == "aarch64" else [zmq]
env.SharedLibrary('messaging_shared', messaging_objects, LIBS=shared_lib_shared_lib)
env.Program('messaging/bridge', ['messaging/bridge.cc'], LIBS=[messaging_lib, 'zmq'])
Depends('messaging/bridge.cc', services_h)
# different target?
#env.Program('messaging/demo', ['messaging/demo.cc'], LIBS=[messaging_lib, 'zmq'])
env.Command(['messaging/messaging_pyx.so'],
[messaging_lib, 'messaging/messaging_pyx_setup.py', 'messaging/messaging_pyx.pyx', 'messaging/messaging.pxd'],
"cd " + messaging_dir.path + " && python3 messaging_pyx_setup.py build_ext --inplace")
if GetOption('test'):
env.Program('messaging/test_runner', ['messaging/test_runner.cc', 'messaging/msgq_tests.cc'], LIBS=[messaging_lib])
+49
View File
@@ -0,0 +1,49 @@
import os
import subprocess
zmq = 'zmq'
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
cereal_dir = Dir('.')
cpppath = [
cereal_dir,
'/usr/lib/include',
]
AddOption('--test',
action='store_true',
help='build test files')
AddOption('--asan',
action='store_true',
help='turn on ASAN')
ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"] if GetOption('asan') else []
ldflags_asan = ["-fsanitize=address"] if GetOption('asan') else []
env = Environment(
ENV=os.environ,
CC='clang',
CXX='clang++',
CCFLAGS=[
"-g",
"-fPIC",
"-O2",
"-Werror=implicit-function-declaration",
"-Werror=incompatible-pointer-types",
"-Werror=int-conversion",
"-Werror=return-type",
"-Werror=format-extra-args",
] + ccflags_asan,
LDFLAGS=ldflags_asan,
LINKFLAGS=ldflags_asan,
CFLAGS="-std=gnu11",
CXXFLAGS="-std=c++14",
CPPPATH=cpppath,
)
Export('env', 'zmq', 'arch')
SConscript(['SConscript'])
+14
View File
@@ -0,0 +1,14 @@
pr: none
pool:
vmImage: 'ubuntu-16.04'
steps:
- script: |
set -e
docker build -t cereal .
docker run cereal bash -c "scons --test --asan -j$(nproc) && messaging/test_runner"
docker run cereal bash -c "ZMQ=1 python -m unittest discover ."
docker run cereal bash -c "MSGQ=1 python -m unittest discover ."
displayName: 'Run Tests'
+61 -10
View File
@@ -84,9 +84,21 @@ struct CarEvent @0x9b1657f34caf3ad3 {
laneChange @59;
invalidGiraffeToyota @60;
internetConnectivityNeeded @61;
manualSteeringRequired @62;
manualSteeringRequiredBlinkersOn @63;
leadCarMoving @64;
communityFeatureDisallowed @62;
lowMemory @63;
stockAeb @64;
ldw @65;
carUnrecognized @66;
radarCommIssue @67;
driverMonitorLowAcc @68;
# dragonpilot
manualSteeringRequired @69;
manualSteeringRequiredBlinkersOn @70;
leadCarMoving @71;
leadCarDetected @72;
preAutoLaneChangeLeft @73;
preAutoLaneChangeRight @74;
autoLaneChange @75;
}
}
@@ -120,6 +132,9 @@ struct CarState {
steeringTorque @8 :Float32; # TODO: standardize units
steeringTorqueEps @27 :Float32; # TODO: standardize units
steeringPressed @9 :Bool; # if the user is using the steering wheel
steeringRateLimited @29 :Bool; # if the torque is limited by the rate limiter
stockAeb @30 :Bool;
stockFcw @31 :Bool;
# cruise state
cruiseState @10 :CruiseState;
@@ -173,7 +188,6 @@ struct CarState {
manumatic @9;
}
# send on change
struct ButtonEvent {
pressed @0 :Bool;
@@ -317,7 +331,7 @@ struct CarParams {
minEnableSpeed @7 :Float32;
minSteerSpeed @8 :Float32;
safetyModel @9 :SafetyModel;
safetyModelPassive @42 :SafetyModel = noOutput;
safetyModelPassive @42 :SafetyModel = silent;
safetyParam @10 :Int16;
steerMaxBP @11 :List(Float32);
@@ -327,7 +341,6 @@ struct CarParams {
brakeMaxBP @15 :List(Float32);
brakeMaxV @16 :List(Float32);
# things about the car in the manual
mass @17 :Float32; # [kg] running weight
wheelbase @18 :Float32; # [m] distance from rear to front axle
@@ -341,6 +354,7 @@ struct CarParams {
tireStiffnessRear @24 :Float32; # [N/rad] rear tire coeff of stiff
longitudinalTuning @25 :LongitudinalPIDTuning;
lateralParams @48 :LateralParams;
lateralTuning :union {
pid @26 :LateralPIDTuning;
indi @27 :LateralINDITuning;
@@ -348,6 +362,7 @@ struct CarParams {
}
steerLimitAlert @28 :Bool;
steerLimitTimer @47 :Float32; # time before steerLimitAlert is issued
vEgoStopping @29 :Float32; # Speed at which the car goes into stopping state
directAccelControl @30 :Bool; # Does the car have direct accel control or just gas/brake
@@ -363,6 +378,15 @@ struct CarParams {
isPandaBlack @39: Bool;
dashcamOnly @41: Bool;
transmissionType @43 :TransmissionType;
carFw @44 :List(CarFw);
radarTimeStep @45: Float32 = 0.05; # time delta between radar updates, 20Hz is very standard
communityFeature @46: Bool; # true if a community maintained feature is detected
fingerprintSource @49: FingerprintSource;
struct LateralParams {
torqueBP @0 :List(Int32);
torqueV @1 :List(Int32);
}
struct LateralPIDTuning {
kpBP @0 :List(Float32);
@@ -381,7 +405,6 @@ struct CarParams {
deadzoneV @5 :List(Float32);
}
struct LateralINDITuning {
outerLoopGain @0 :Float32;
innerLoopGain @1 :Float32;
@@ -404,12 +427,12 @@ struct CarParams {
}
enum SafetyModel {
noOutput @0;
honda @1;
silent @0;
hondaNidec @1;
toyota @2;
elm327 @3;
gm @4;
hondaBosch @5;
hondaBoschGiraffe @5;
ford @6;
cadillac @7;
hyundai @8;
@@ -423,6 +446,9 @@ struct CarParams {
toyotaIpas @16;
allOutput @17;
gmAscm @18;
noOutput @19; # like silent but without silent CAN TXs
hondaBoschHarness @20;
volkswagenPq @21;
}
enum SteerControlType {
@@ -435,4 +461,29 @@ struct CarParams {
automatic @1;
manual @2;
}
struct CarFw {
ecu @0 :Ecu;
fwVersion @1 :Data;
address @2: UInt32;
subAddress @3: UInt8;
}
enum Ecu {
eps @0;
esp @1;
fwdRadar @2;
fwdCamera @3;
engine @4;
unknown @5;
# Toyota only
dsu @6;
apgs @7;
}
enum FingerprintSource {
can @0;
fw @1;
}
}
+4 -3
View File
@@ -8,7 +8,8 @@ tar xvf capnproto-c++-${VERSION}.tar.gz
cd capnproto-c++-${VERSION}
CXXFLAGS="-fPIC" ./configure
make -j4
make -j$(nproc)
make install
# manually build binaries statically
g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread -pthread -o .libs/capnp src/capnp/compiler/module-loader.o src/capnp/compiler/capnp.o ./.libs/libcapnpc.a ./.libs/libcapnp.a ./.libs/libkj.a -lpthread -pthread
@@ -18,7 +19,6 @@ g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -D
g++ -std=gnu++11 -I./src -I./src -DKJ_HEADER_WARNINGS -DCAPNP_HEADER_WARNINGS -DCAPNP_INCLUDE_DIR=\"/usr/local/include\" -pthread -O2 -DNDEBUG -pthread -pthread -o .libs/capnpc-capnp src/capnp/compiler/capnpc-capnp.o ./.libs/libcapnp.a ./.libs/libkj.a -lpthread -pthread
cp .libs/capnp /usr/local/bin/
ln -s /usr/local/bin/capnp /usr/local/bin/capnpc
cp .libs/capnpc-c++ /usr/local/bin/
cp .libs/capnpc-capnp /usr/local/bin/
cp .libs/*.a /usr/local/lib
@@ -30,7 +30,8 @@ cd c-capnproto
git submodule update --init --recursive
autoreconf -f -i -s
CXXFLAGS="-fPIC" ./configure
make -j4
make -j$(nproc)
make install
# manually build binaries statically
gcc -fPIC -o .libs/capnpc-c compiler/capnpc-c.o compiler/schema.capnp.o compiler/str.o ./.libs/libcapnp_c.a
+106 -5
View File
@@ -126,6 +126,7 @@ struct FrameData {
lensErr @13 :Float32;
lensTruePos @14 :Float32;
image @6 :Data;
gainFrac @15 :Float32;
frameType @7 :FrameType;
timestampSof @8 :UInt64;
@@ -137,6 +138,7 @@ struct FrameData {
unknown @0;
neo @1;
chffrAndroid @2;
front @3;
}
struct AndroidCaptureResult {
@@ -268,6 +270,7 @@ struct ThermalData {
mem @4 :UInt16;
gpu @5 :UInt16;
bat @6 :UInt32;
pa0 @21 :UInt16;
# not thermal
freeSpace @7 :Float32;
@@ -276,6 +279,7 @@ struct ThermalData {
batteryCurrent @15 :Int32;
batteryVoltage @16 :Int32;
usbOnline @12 :Bool;
networkType @22 :NetworkType;
fanSpeed @10 :UInt16;
started @11 :Bool;
@@ -284,7 +288,11 @@ struct ThermalData {
thermalStatus @14 :ThermalStatus;
chargingError @17 :Bool;
chargingDisabled @18 :Bool;
ipAddr @19 :Text;
memUsedPercent @19 :Int8;
cpuPerc @20 :Int8;
ipAddr @23 :Text; # dragonpilot
enum ThermalStatus {
green @0; # all processes run
@@ -292,23 +300,49 @@ struct ThermalData {
red @2; # no engage, will disengage
danger @3; # immediate process shutdown
}
enum NetworkType {
none @0;
wifi @1;
cell2G @2;
cell3G @3;
cell4G @4;
cell5G @5;
}
}
struct HealthData {
# from can health
voltage @0 :UInt32;
current @1 :UInt32;
started @2 :Bool;
ignitionLine @2 :Bool;
controlsAllowed @3 :Bool;
gasInterceptorDetected @4 :Bool;
startedSignalDetectedDeprecated @5 :Bool;
hasGps @6 :Bool;
canSendErrs @7 :UInt32;
canFwdErrs @8 :UInt32;
canRxErrs @19 :UInt32;
gmlanSendErrs @9 :UInt32;
hwType @10 :HwType;
fanSpeedRpm @11 :UInt16;
usbPowerMode @12 :UsbPowerMode;
ignitionCan @13 :Bool;
safetyModel @14 :Car.CarParams.SafetyModel;
faultStatus @15 :FaultStatus;
powerSaveEnabled @16 :Bool;
uptime @17 :UInt32;
faults @18 :List(FaultType);
enum FaultStatus {
none @0;
faultTemp @1;
faultPerm @2;
}
enum FaultType {
relayMalfunction @0;
}
enum HwType {
unknown @0;
@@ -463,6 +497,7 @@ struct ControlsState @0x97ff69c53601abf1 {
decelForTurn @47 :Bool;
decelForModel @54 :Bool;
canErrorCounter @57 :UInt32;
lateralControlState :union {
indiState @52 :LateralINDIState;
@@ -508,6 +543,7 @@ struct ControlsState @0x97ff69c53601abf1 {
delayedOutput @7 :Float32;
delta @8 :Float32;
output @9 :Float32;
saturated @10 :Bool;
}
struct LateralPIDState {
@@ -528,6 +564,7 @@ struct ControlsState @0x97ff69c53601abf1 {
i @2 :Float32;
output @3 :Float32;
lqrOutput @4 :Float32;
saturated @5 :Bool;
}
@@ -551,6 +588,8 @@ struct ModelData {
settings @5 :ModelSettings;
leadFuture @7 :LeadData;
speed @8 :List(Float32);
meta @10 :MetaData;
longitudinal @11 :LongitudinalData;
struct PathData {
points @0 :List(Float32);
@@ -581,6 +620,19 @@ struct ModelData {
yuvCorrection @5 :List(Float32);
inputTransform @6 :List(Float32);
}
struct MetaData {
engagedProb @0 :Float32;
desirePrediction @1 :List(Float32);
brakeDisengageProb @2 :Float32;
gasDisengageProb @3 :Float32;
steerOverrideProb @4 :Float32;
}
struct LongitudinalData {
speeds @0 :List(Float32);
accelerations @1 :List(Float32);
}
}
struct CalibrationFeatures {
@@ -714,6 +766,8 @@ struct PathPlan {
desire @17 :Desire;
laneChangeState @18 :LaneChangeState;
laneChangeDirection @19 :LaneChangeDirection;
# dragonpilot
autoLCAllowed @20 :Bool;
enum Desire {
none @0;
@@ -1382,6 +1436,7 @@ struct UbloxGnss {
measurementReport @0 :MeasurementReport;
ephemeris @1 :Ephemeris;
ionoData @2 :IonoData;
hwStatus @3 :HwStatus;
}
struct MeasurementReport {
@@ -1505,8 +1560,29 @@ struct UbloxGnss {
healthValid @5 :Bool;
ionoCoeffsValid @6 :Bool;
}
}
struct HwStatus {
noisePerMS @0 :UInt16;
agcCnt @1 :UInt16;
aStatus @2 :AntennaSupervisorState;
aPower @3 :AntennaPowerStatus;
jamInd @4 :UInt8;
enum AntennaSupervisorState {
init @0;
dontknow @1;
ok @2;
short @3;
open @4;
}
enum AntennaPowerStatus {
off @0;
on @1;
dontknow @2;
}
}
}
struct Clocks {
bootTimeNanos @0 :UInt64;
@@ -1648,6 +1724,7 @@ struct UiLayoutState {
home @0;
music @1;
nav @2;
settings @3;
}
}
@@ -1713,7 +1790,7 @@ struct OrbKeyFrame {
descriptors @3 :Data;
}
struct DriverMonitoring {
struct DriverState {
frameId @0 :UInt32;
descriptorDEPRECATED @1 :List(Float32);
stdDEPRECATED @2 :Float32;
@@ -1724,6 +1801,28 @@ struct DriverMonitoring {
rightEyeProb @7 :Float32;
leftBlinkProb @8 :Float32;
rightBlinkProb @9 :Float32;
irPwrDEPRECATED @10 :Float32;
faceOrientationStd @11 :List(Float32);
facePositionStd @12 :List(Float32);
}
struct DMonitoringState {
# TODO: deprecate old fields in controlsState
events @0 :List(Car.CarEvent);
faceDetected @1 :Bool;
isDistracted @2 :Bool;
awarenessStatus @3 :Float32;
isRHD @4 :Bool;
rhdChecked @5 :Bool;
posePitchOffset @6 :Float32;
posePitchValidCount @7 :UInt32;
poseYawOffset @8 :Float32;
poseYawValidCount @9 :UInt32;
stepChange @10 :Float32;
awarenessActive @11 :Float32;
awarenessPassive @12 :Float32;
isLowStd @13 :Bool;
hiStdCount @14 :UInt32;
}
struct Boot {
@@ -1845,7 +1944,7 @@ struct Event {
orbKeyFrame @56 :OrbKeyFrame;
uiLayoutState @57 :UiLayoutState;
orbFeaturesSummary @58 :OrbFeaturesSummary;
driverMonitoring @59 :DriverMonitoring;
driverState @59 :DriverState;
boot @60 :Boot;
liveParameters @61 :LiveParametersData;
liveMapData @62 :LiveMapData;
@@ -1855,5 +1954,7 @@ struct Event {
thumbnail @66: Thumbnail;
carEvents @68: List(Car.CarEvent);
carParams @69: Car.CarParams;
frontFrame @70: FrameData;
dMonitoringState @71: DMonitoringState;
}
}
+10
View File
@@ -0,0 +1,10 @@
demo
bridge
test_runner
*.o
*.os
*.d
*.a
*.so
messaging_pyx.cpp
build/
@@ -1,8 +1,23 @@
import zmq
# must be build with scons
from .messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error
from .messaging_pyx import MultiplePublishersError, MessagingError # pylint: disable=no-name-in-module, import-error
import capnp
assert MultiplePublishersError
assert MessagingError
from cereal import log
from common.realtime import sec_since_boot
from selfdrive.services import service_list
from cereal.services import service_list
# sec_since_boot is faster, but allow to run standalone too
try:
from common.realtime import sec_since_boot
except ImportError:
import time
sec_since_boot = time.time
print("Warning, using python time.time() instead of faster sec_since_boot")
context = Context()
def new_message():
dat = log.Event.new_message()
@@ -10,101 +25,108 @@ def new_message():
dat.valid = True
return dat
def pub_sock(port, addr="*"):
context = zmq.Context.instance()
sock = context.socket(zmq.PUB)
sock.bind("tcp://%s:%d" % (addr, port))
def pub_sock(endpoint):
sock = PubSocket()
sock.connect(context, endpoint)
return sock
def sub_sock(port, poller=None, addr="127.0.0.1", conflate=False, timeout=None):
context = zmq.Context.instance()
sock = context.socket(zmq.SUB)
if conflate:
sock.setsockopt(zmq.CONFLATE, 1)
sock.connect("tcp://%s:%d" % (addr, port))
sock.setsockopt(zmq.SUBSCRIBE, b"")
def sub_sock(endpoint, poller=None, addr="127.0.0.1", conflate=False, timeout=None):
sock = SubSocket()
addr = addr.encode('utf8')
sock.connect(context, endpoint, addr, conflate)
if timeout is not None:
sock.RCVTIMEO = timeout
sock.setTimeout(timeout)
if poller is not None:
poller.register(sock, zmq.POLLIN)
poller.registerSocket(sock)
return sock
def drain_sock_raw_poller(poller, sock, wait_for_one=False):
ret = []
if wait_for_one:
try:
ret.append(sock.recv())
except zmq.error.Again: # Thrown when there is timeout on the socket
return ret
while True:
if not poller.poll(0):
break # Socket has no more messages
ret.append(sock.recv())
return ret
def drain_sock_raw(sock, wait_for_one=False):
"""Receive all message currently available on the queue"""
ret = []
while 1:
try:
if wait_for_one and len(ret) == 0:
dat = sock.recv()
else:
dat = sock.recv(zmq.NOBLOCK)
ret.append(dat)
except zmq.error.Again:
if wait_for_one and len(ret) == 0:
dat = sock.receive()
else:
dat = sock.receive(non_blocking=True)
if dat is None:
break
ret.append(dat)
return ret
def drain_sock(sock, wait_for_one=False):
"""Receive all message currently available on the queue"""
ret = []
while 1:
try:
if wait_for_one and len(ret) == 0:
dat = sock.recv()
else:
dat = sock.recv(zmq.NOBLOCK)
dat = log.Event.from_bytes(dat)
ret.append(dat)
except zmq.error.Again:
if wait_for_one and len(ret) == 0:
dat = sock.receive()
else:
dat = sock.receive(non_blocking=True)
if dat is None: # Timeout hit
break
dat = log.Event.from_bytes(dat)
ret.append(dat)
return ret
# TODO: print when we drop packets?
def recv_sock(sock, wait=False):
"""Same as drain sock, but only returns latest message. Consider using conflate instead."""
dat = None
while 1:
try:
if wait and dat is None:
dat = sock.recv()
else:
dat = sock.recv(zmq.NOBLOCK)
except zmq.error.Again:
if wait and dat is None:
rcv = sock.receive()
else:
rcv = sock.receive(non_blocking=True)
if rcv is None: # Timeout hit
break
dat = rcv
if dat is not None:
dat = log.Event.from_bytes(dat)
return dat
def recv_one(sock):
dat = sock.receive()
if dat is not None:
dat = log.Event.from_bytes(dat)
return dat
def recv_one(sock):
return log.Event.from_bytes(sock.recv())
def recv_one_or_none(sock):
try:
return log.Event.from_bytes(sock.recv(zmq.NOBLOCK))
except zmq.error.Again:
return None
dat = sock.receive(non_blocking=True)
if dat is not None:
dat = log.Event.from_bytes(dat)
return dat
def recv_one_retry(sock):
"""Keep receiving until we get a message"""
while True:
dat = sock.receive()
if dat is not None:
return log.Event.from_bytes(dat)
# TODO: This does not belong in messaging
def get_one_can(logcan):
while True:
can = recv_one_retry(logcan)
if len(can.can) > 0:
return can
class SubMaster():
def __init__(self, services, ignore_alive=None, addr="127.0.0.1"):
self.poller = zmq.Poller()
self.poller = Poller()
self.frame = -1
self.updated = {s : False for s in services}
self.rcv_time = {s : 0. for s in services}
@@ -122,18 +144,17 @@ class SubMaster():
self.ignore_alive = []
for s in services:
# TODO: get address automatically from service_list
if addr is not None:
self.sock[s] = sub_sock(service_list[s].port, poller=self.poller, addr=addr, conflate=True)
self.sock[s] = sub_sock(s, poller=self.poller, addr=addr, conflate=True)
self.freq[s] = service_list[s].frequency
data = new_message()
if s in ['can', 'sensorEvents', 'liveTracks', 'sendCan',
'ethernetData', 'cellInfo', 'wifiScan',
'trafficEvents', 'orbObservation', 'carEvents']:
data.init(s, 0)
else:
try:
data.init(s)
except capnp.lib.capnp.KjException:
# lists
data.init(s, 0)
self.data[s] = getattr(data, s)
self.logMonoTime[s] = 0
self.valid[s] = data.valid
@@ -141,10 +162,10 @@ class SubMaster():
def __getitem__(self, s):
return self.data[s]
def update(self, timeout=-1):
def update(self, timeout=1000):
msgs = []
for sock, _ in self.poller.poll(timeout):
msgs.append(recv_one(sock))
for sock in self.poller.poll(timeout):
msgs.append(recv_one_or_none(sock))
self.update_msgs(sec_since_boot(), msgs)
def update_msgs(self, cur_time, msgs):
@@ -152,6 +173,9 @@ class SubMaster():
self.frame += 1
self.updated = dict.fromkeys(self.updated, False)
for msg in msgs:
if msg is None:
continue
s = msg.which()
self.updated[s] = True
self.rcv_time[s] = cur_time
@@ -188,7 +212,7 @@ class PubMaster():
def __init__(self, services):
self.sock = {}
for s in services:
self.sock[s] = pub_sock(service_list[s].port)
self.sock[s] = pub_sock(s)
def send(self, s, dat):
# accept either bytes or capnp builder
+64
View File
@@ -0,0 +1,64 @@
#include <iostream>
#include <string>
#include <cassert>
#include <csignal>
#include <map>
typedef void (*sighandler_t)(int sig);
#include "services.h"
#include "impl_msgq.hpp"
#include "impl_zmq.hpp"
void sigpipe_handler(int sig) {
assert(sig == SIGPIPE);
std::cout << "SIGPIPE received" << std::endl;
}
static std::vector<std::string> get_services() {
std::vector<std::string> name_list;
for (const auto& it : services) {
std::string name = it.name;
if (name == "plusFrame" || name == "uiLayoutState") continue;
name_list.push_back(name);
}
return name_list;
}
int main(void){
signal(SIGPIPE, (sighandler_t)sigpipe_handler);
auto endpoints = get_services();
std::map<SubSocket*, PubSocket*> sub2pub;
Context *zmq_context = new ZMQContext();
Context *msgq_context = new MSGQContext();
Poller *poller = new MSGQPoller();
for (auto endpoint: endpoints){
SubSocket * msgq_sock = new MSGQSubSocket();
msgq_sock->connect(msgq_context, endpoint, "127.0.0.1", false);
poller->registerSocket(msgq_sock);
PubSocket * zmq_sock = new ZMQPubSocket();
zmq_sock->connect(zmq_context, endpoint);
sub2pub[msgq_sock] = zmq_sock;
}
while (true){
for (auto sub_sock : poller->poll(100)){
Message * msg = sub_sock->receive();
if (msg == NULL) continue;
sub2pub[sub_sock]->sendMessage(msg);
delete msg;
}
}
return 0;
}
File diff suppressed because it is too large Load Diff
+50
View File
@@ -0,0 +1,50 @@
#include <iostream>
#include <cstddef>
#include <chrono>
#include <thread>
#include <cassert>
#include "messaging.hpp"
#include "impl_zmq.hpp"
#define MSGS 1e5
int main() {
Context * c = Context::create();
SubSocket * sub_sock = SubSocket::create(c, "controlsState");
PubSocket * pub_sock = PubSocket::create(c, "controlsState");
char data[8];
Poller * poller = Poller::create({sub_sock});
auto start = std::chrono::steady_clock::now();
for (uint64_t i = 0; i < MSGS; i++){
*(uint64_t*)data = i;
pub_sock->send(data, 8);
auto r = poller->poll(100);
for (auto p : r){
Message * m = p->receive();
uint64_t ii = *(uint64_t*)m->getData();
assert(i == ii);
delete m;
}
}
auto end = std::chrono::steady_clock::now();
double elapsed = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count() / 1e9;
double throughput = ((double) MSGS / (double) elapsed);
std::cout << throughput << " msg/s" << std::endl;
delete poller;
delete sub_sock;
delete pub_sock;
delete c;
return 0;
}
+30
View File
@@ -0,0 +1,30 @@
import time
from messaging_pyx import Context, Poller, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error
MSGS = 1e5
if __name__ == "__main__":
c = Context()
sub_sock = SubSocket()
pub_sock = PubSocket()
sub_sock.connect(c, "controlsState")
pub_sock.connect(c, "controlsState")
poller = Poller()
poller.registerSocket(sub_sock)
t = time.time()
for i in range(int(MSGS)):
bts = i.to_bytes(4, 'little')
pub_sock.send(bts)
for s in poller.poll(100):
dat = s.receive()
ii = int.from_bytes(dat, 'little')
assert(i == ii)
dt = time.time() - t
print("%.1f msg/s" % (MSGS / dt))
+195
View File
@@ -0,0 +1,195 @@
#include <cassert>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <csignal>
#include <cerrno>
#include "impl_msgq.hpp"
volatile sig_atomic_t msgq_do_exit = 0;
void sig_handler(int signal) {
assert(signal == SIGINT || signal == SIGTERM);
msgq_do_exit = 1;
}
MSGQContext::MSGQContext() {
}
MSGQContext::~MSGQContext() {
}
void MSGQMessage::init(size_t sz) {
size = sz;
data = new char[size];
}
void MSGQMessage::init(char * d, size_t sz) {
size = sz;
data = new char[size];
memcpy(data, d, size);
}
void MSGQMessage::takeOwnership(char * d, size_t sz) {
size = sz;
data = d;
}
void MSGQMessage::close() {
if (size > 0){
delete[] data;
}
size = 0;
}
MSGQMessage::~MSGQMessage() {
this->close();
}
int MSGQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate){
assert(context);
assert(address == "127.0.0.1");
q = new msgq_queue_t;
int r = msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE);
if (r != 0){
return r;
}
msgq_init_subscriber(q);
if (conflate){
q->read_conflate = true;
}
timeout = -1;
return 0;
}
Message * MSGQSubSocket::receive(bool non_blocking){
msgq_do_exit = 0;
void (*prev_handler_sigint)(int);
void (*prev_handler_sigterm)(int);
if (!non_blocking){
prev_handler_sigint = std::signal(SIGINT, sig_handler);
prev_handler_sigterm = std::signal(SIGTERM, sig_handler);
}
msgq_msg_t msg;
MSGQMessage *r = NULL;
int rc = msgq_msg_recv(&msg, q);
// Hack to implement blocking read with a poller. Don't use this
while (!non_blocking && rc == 0 && msgq_do_exit == 0){
msgq_pollitem_t items[1];
items[0].q = q;
int t = (timeout != -1) ? timeout : 100;
int n = msgq_poll(items, 1, t);
rc = msgq_msg_recv(&msg, q);
// The poll indicated a message was ready, but the receive failed. Try again
if (n == 1 && rc == 0){
continue;
}
if (timeout != -1){
break;
}
}
if (!non_blocking){
std::signal(SIGINT, prev_handler_sigint);
std::signal(SIGTERM, prev_handler_sigterm);
}
errno = msgq_do_exit ? EINTR : 0;
if (rc > 0){
if (msgq_do_exit){
msgq_msg_close(&msg); // Free unused message on exit
} else {
r = new MSGQMessage;
r->takeOwnership(msg.data, msg.size);
}
}
return (Message*)r;
}
void MSGQSubSocket::setTimeout(int t){
timeout = t;
}
MSGQSubSocket::~MSGQSubSocket(){
if (q != NULL){
msgq_close_queue(q);
delete q;
}
}
int MSGQPubSocket::connect(Context *context, std::string endpoint){
assert(context);
q = new msgq_queue_t;
msgq_new_queue(q, endpoint.c_str(), DEFAULT_SEGMENT_SIZE);
msgq_init_publisher(q);
return 0;
}
int MSGQPubSocket::sendMessage(Message *message){
msgq_msg_t msg;
msg.data = message->getData();
msg.size = message->getSize();
return msgq_msg_send(&msg, q);
}
int MSGQPubSocket::send(char *data, size_t size){
msgq_msg_t msg;
msg.data = data;
msg.size = size;
return msgq_msg_send(&msg, q);
}
MSGQPubSocket::~MSGQPubSocket(){
if (q != NULL){
msgq_close_queue(q);
delete q;
}
}
void MSGQPoller::registerSocket(SubSocket * socket){
assert(num_polls + 1 < MAX_POLLERS);
polls[num_polls].q = (msgq_queue_t*)socket->getRawSocket();
sockets.push_back(socket);
num_polls++;
}
std::vector<SubSocket*> MSGQPoller::poll(int timeout){
std::vector<SubSocket*> r;
msgq_poll(polls, num_polls, timeout);
for (size_t i = 0; i < num_polls; i++){
if (polls[i].revents){
r.push_back(sockets[i]);
}
}
return r;
}
+64
View File
@@ -0,0 +1,64 @@
#pragma once
#include "messaging.hpp"
#include "msgq.hpp"
#include <zmq.h>
#include <string>
#define MAX_POLLERS 128
class MSGQContext : public Context {
private:
void * context = NULL;
public:
MSGQContext();
void * getRawContext() {return context;}
~MSGQContext();
};
class MSGQMessage : public Message {
private:
char * data;
size_t size;
public:
void init(size_t size);
void init(char *data, size_t size);
void takeOwnership(char *data, size_t size);
size_t getSize(){return size;}
char * getData(){return data;}
void close();
~MSGQMessage();
};
class MSGQSubSocket : public SubSocket {
private:
msgq_queue_t * q = NULL;
int timeout;
public:
int connect(Context *context, std::string endpoint, std::string address, bool conflate=false);
void setTimeout(int timeout);
void * getRawSocket() {return (void*)q;}
Message *receive(bool non_blocking=false);
~MSGQSubSocket();
};
class MSGQPubSocket : public PubSocket {
private:
msgq_queue_t * q = NULL;
public:
int connect(Context *context, std::string endpoint);
int sendMessage(Message *message);
int send(char *data, size_t size);
~MSGQPubSocket();
};
class MSGQPoller : public Poller {
private:
std::vector<SubSocket*> sockets;
msgq_pollitem_t polls[MAX_POLLERS];
size_t num_polls = 0;
public:
void registerSocket(SubSocket *socket);
std::vector<SubSocket*> poll(int timeout);
~MSGQPoller(){};
};
+155
View File
@@ -0,0 +1,155 @@
#include <cassert>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <cerrno>
#include <zmq.h>
#include "services.h"
#include "impl_zmq.hpp"
static int get_port(std::string endpoint) {
int port = -1;
for (const auto& it : services) {
std::string name = it.name;
if (name == endpoint) {
port = it.port;
break;
}
}
assert(port >= 0);
return port;
}
ZMQContext::ZMQContext() {
context = zmq_ctx_new();
}
ZMQContext::~ZMQContext() {
zmq_ctx_term(context);
}
void ZMQMessage::init(size_t sz) {
size = sz;
data = new char[size];
}
void ZMQMessage::init(char * d, size_t sz) {
size = sz;
data = new char[size];
memcpy(data, d, size);
}
void ZMQMessage::close() {
if (size > 0){
delete[] data;
}
size = 0;
}
ZMQMessage::~ZMQMessage() {
this->close();
}
int ZMQSubSocket::connect(Context *context, std::string endpoint, std::string address, bool conflate){
sock = zmq_socket(context->getRawContext(), ZMQ_SUB);
if (sock == NULL){
return -1;
}
zmq_setsockopt(sock, ZMQ_SUBSCRIBE, "", 0);
if (conflate){
int arg = 1;
zmq_setsockopt(sock, ZMQ_CONFLATE, &arg, sizeof(int));
}
int reconnect_ivl = 500;
zmq_setsockopt(sock, ZMQ_RECONNECT_IVL_MAX, &reconnect_ivl, sizeof(reconnect_ivl));
full_endpoint = "tcp://" + address + ":";
full_endpoint += std::to_string(get_port(endpoint));
return zmq_connect(sock, full_endpoint.c_str());
}
Message * ZMQSubSocket::receive(bool non_blocking){
zmq_msg_t msg;
assert(zmq_msg_init(&msg) == 0);
int flags = non_blocking ? ZMQ_DONTWAIT : 0;
int rc = zmq_msg_recv(&msg, sock, flags);
Message *r = NULL;
if (rc >= 0){
// Make a copy to ensure the data is aligned
r = new ZMQMessage;
r->init((char*)zmq_msg_data(&msg), zmq_msg_size(&msg));
}
zmq_msg_close(&msg);
return r;
}
void ZMQSubSocket::setTimeout(int timeout){
zmq_setsockopt(sock, ZMQ_RCVTIMEO, &timeout, sizeof(int));
}
ZMQSubSocket::~ZMQSubSocket(){
zmq_close(sock);
}
int ZMQPubSocket::connect(Context *context, std::string endpoint){
sock = zmq_socket(context->getRawContext(), ZMQ_PUB);
if (sock == NULL){
return -1;
}
full_endpoint = "tcp://*:";
full_endpoint += std::to_string(get_port(endpoint));
return zmq_bind(sock, full_endpoint.c_str());
}
int ZMQPubSocket::sendMessage(Message *message){
return zmq_send(sock, message->getData(), message->getSize(), ZMQ_DONTWAIT);
}
int ZMQPubSocket::send(char *data, size_t size){
return zmq_send(sock, data, size, ZMQ_DONTWAIT);
}
ZMQPubSocket::~ZMQPubSocket(){
zmq_close(sock);
}
void ZMQPoller::registerSocket(SubSocket * socket){
assert(num_polls + 1 < MAX_POLLERS);
polls[num_polls].socket = socket->getRawSocket();
polls[num_polls].events = ZMQ_POLLIN;
sockets.push_back(socket);
num_polls++;
}
std::vector<SubSocket*> ZMQPoller::poll(int timeout){
std::vector<SubSocket*> r;
int rc = zmq_poll(polls, num_polls, timeout);
if (rc < 0){
return r;
}
for (size_t i = 0; i < num_polls; i++){
if (polls[i].revents){
r.push_back(sockets[i]);
}
}
return r;
}
+63
View File
@@ -0,0 +1,63 @@
#pragma once
#include "messaging.hpp"
#include <zmq.h>
#include <string>
#define MAX_POLLERS 128
class ZMQContext : public Context {
private:
void * context = NULL;
public:
ZMQContext();
void * getRawContext() {return context;}
~ZMQContext();
};
class ZMQMessage : public Message {
private:
char * data;
size_t size;
public:
void init(size_t size);
void init(char *data, size_t size);
size_t getSize(){return size;}
char * getData(){return data;}
void close();
~ZMQMessage();
};
class ZMQSubSocket : public SubSocket {
private:
void * sock;
std::string full_endpoint;
public:
int connect(Context *context, std::string endpoint, std::string address, bool conflate=false);
void setTimeout(int timeout);
void * getRawSocket() {return sock;}
Message *receive(bool non_blocking=false);
~ZMQSubSocket();
};
class ZMQPubSocket : public PubSocket {
private:
void * sock;
std::string full_endpoint;
public:
int connect(Context *context, std::string endpoint);
int sendMessage(Message *message);
int send(char *data, size_t size);
~ZMQPubSocket();
};
class ZMQPoller : public Poller {
private:
std::vector<SubSocket*> sockets;
zmq_pollitem_t polls[MAX_POLLERS];
size_t num_polls = 0;
public:
void registerSocket(SubSocket *socket);
std::vector<SubSocket*> poll(int timeout);
~ZMQPoller(){};
};
+117
View File
@@ -0,0 +1,117 @@
#include "messaging.hpp"
#include "impl_zmq.hpp"
#include "impl_msgq.hpp"
Context * Context::create(){
Context * c;
if (std::getenv("ZMQ")){
c = new ZMQContext();
} else {
c = new MSGQContext();
}
return c;
}
SubSocket * SubSocket::create(){
SubSocket * s;
if (std::getenv("ZMQ")){
s = new ZMQSubSocket();
} else {
s = new MSGQSubSocket();
}
return s;
}
SubSocket * SubSocket::create(Context * context, std::string endpoint){
SubSocket *s = SubSocket::create();
int r = s->connect(context, endpoint, "127.0.0.1");
if (r == 0) {
return s;
} else {
delete s;
return NULL;
}
}
SubSocket * SubSocket::create(Context * context, std::string endpoint, std::string address){
SubSocket *s = SubSocket::create();
int r = s->connect(context, endpoint, address);
if (r == 0) {
return s;
} else {
delete s;
return NULL;
}
}
SubSocket * SubSocket::create(Context * context, std::string endpoint, std::string address, bool conflate){
SubSocket *s = SubSocket::create();
int r = s->connect(context, endpoint, address, conflate);
if (r == 0) {
return s;
} else {
delete s;
return NULL;
}
}
PubSocket * PubSocket::create(){
PubSocket * s;
if (std::getenv("ZMQ")){
s = new ZMQPubSocket();
} else {
s = new MSGQPubSocket();
}
return s;
}
PubSocket * PubSocket::create(Context * context, std::string endpoint){
PubSocket *s = PubSocket::create();
int r = s->connect(context, endpoint);
if (r == 0) {
return s;
} else {
delete s;
return NULL;
}
}
Poller * Poller::create(){
Poller * p;
if (std::getenv("ZMQ")){
p = new ZMQPoller();
} else {
p = new MSGQPoller();
}
return p;
}
Poller * Poller::create(std::vector<SubSocket*> sockets){
Poller * p = Poller::create();
for (auto s : sockets){
p->registerSocket(s);
}
return p;
}
extern "C" Context * messaging_context_create() {
return Context::create();
}
extern "C" SubSocket * messaging_subsocket_create(Context* context, const char* endpoint) {
return SubSocket::create(context, std::string(endpoint));
}
extern "C" PubSocket * messaging_pubsocket_create(Context* context, const char* endpoint) {
return PubSocket::create(context, std::string(endpoint));
}
extern "C" Poller * messaging_poller_create(SubSocket** sockets, int size) {
std::vector<SubSocket*> socketsVec(sockets, sockets + size);
return Poller::create(socketsVec);
}
+56
View File
@@ -0,0 +1,56 @@
#pragma once
#include <cstddef>
#include <vector>
#include <string>
#define MSG_MULTIPLE_PUBLISHERS 100
class Context {
public:
virtual void * getRawContext() = 0;
static Context * create();
virtual ~Context(){};
};
class Message {
public:
virtual void init(size_t size) = 0;
virtual void init(char * data, size_t size) = 0;
virtual void close() = 0;
virtual size_t getSize() = 0;
virtual char * getData() = 0;
virtual ~Message(){};
};
class SubSocket {
public:
virtual int connect(Context *context, std::string endpoint, std::string address, bool conflate=false) = 0;
virtual void setTimeout(int timeout) = 0;
virtual Message *receive(bool non_blocking=false) = 0;
virtual void * getRawSocket() = 0;
static SubSocket * create();
static SubSocket * create(Context * context, std::string endpoint);
static SubSocket * create(Context * context, std::string endpoint, std::string address);
static SubSocket * create(Context * context, std::string endpoint, std::string address, bool conflate);
virtual ~SubSocket(){};
};
class PubSocket {
public:
virtual int connect(Context *context, std::string endpoint) = 0;
virtual int sendMessage(Message *message) = 0;
virtual int send(char *data, size_t size) = 0;
static PubSocket * create();
static PubSocket * create(Context * context, std::string endpoint);
virtual ~PubSocket(){};
};
class Poller {
public:
virtual void registerSocket(SubSocket *socket) = 0;
virtual std::vector<SubSocket*> poll(int timeout) = 0;
static Poller * create();
static Poller * create(std::vector<SubSocket*> sockets);
virtual ~Poller(){};
};
+39
View File
@@ -0,0 +1,39 @@
# distutils: language = c++
#cython: language_level=3
from libcpp.string cimport string
from libcpp.vector cimport vector
from libcpp cimport bool
cdef extern from "messaging.hpp":
cdef cppclass Context:
@staticmethod
Context * create()
cdef cppclass Message:
void init(size_t)
void init(char *, size_t)
void close()
size_t getSize()
char *getData()
cdef cppclass SubSocket:
@staticmethod
SubSocket * create()
int connect(Context *, string, string, bool)
Message * receive(bool)
void setTimeout(int)
cdef cppclass PubSocket:
@staticmethod
PubSocket * create()
int connect(Context *, string)
int sendMessage(Message *)
int send(char *, size_t)
cdef cppclass Poller:
@staticmethod
Poller * create()
void registerSocket(SubSocket *)
vector[SubSocket*] poll(int) nogil
+151
View File
@@ -0,0 +1,151 @@
# distutils: language = c++
# cython: c_string_encoding=ascii, language_level=3
import sys
from libcpp.string cimport string
from libcpp cimport bool
from libc cimport errno
from messaging cimport Context as cppContext
from messaging cimport SubSocket as cppSubSocket
from messaging cimport PubSocket as cppPubSocket
from messaging cimport Poller as cppPoller
from messaging cimport Message as cppMessage
class MessagingError(Exception):
pass
class MultiplePublishersError(MessagingError):
pass
cdef class Context:
cdef cppContext * context
def __cinit__(self):
self.context = cppContext.create()
def term(self):
del self.context
self.context = NULL
def __dealloc__(self):
pass
# Deleting the context will hang if sockets are still active
# TODO: Figure out a way to make sure the context is closed last
# del self.context
cdef class Poller:
cdef cppPoller * poller
cdef list sub_sockets
def __cinit__(self):
self.sub_sockets = []
self.poller = cppPoller.create()
def __dealloc__(self):
del self.poller
def registerSocket(self, SubSocket socket):
self.sub_sockets.append(socket)
self.poller.registerSocket(socket.socket)
def poll(self, timeout):
sockets = []
cdef int t = timeout
with nogil:
result = self.poller.poll(t)
for s in result:
socket = SubSocket()
socket.setPtr(s)
sockets.append(socket)
return sockets
cdef class SubSocket:
cdef cppSubSocket * socket
cdef bool is_owner
def __cinit__(self):
self.socket = cppSubSocket.create()
self.is_owner = True
if self.socket == NULL:
raise MessagingError
def __dealloc__(self):
if self.is_owner:
del self.socket
cdef setPtr(self, cppSubSocket * ptr):
if self.is_owner:
del self.socket
self.is_owner = False
self.socket = ptr
def connect(self, Context context, string endpoint, string address=b"127.0.0.1", bool conflate=False):
r = self.socket.connect(context.context, endpoint, address, conflate)
if r != 0:
if errno.errno == errno.EADDRINUSE:
raise MultiplePublishersError
else:
raise MessagingError
def setTimeout(self, int timeout):
self.socket.setTimeout(timeout)
def receive(self, bool non_blocking=False):
msg = self.socket.receive(non_blocking)
if msg == NULL:
# If a blocking read returns no message check errno if SIGINT was caught in the C++ code
if errno.errno == errno.EINTR:
print("SIGINT received, exiting")
sys.exit(1)
return None
else:
sz = msg.getSize()
m = msg.getData()[:sz]
del msg
return m
cdef class PubSocket:
cdef cppPubSocket * socket
def __cinit__(self):
self.socket = cppPubSocket.create()
if self.socket == NULL:
raise MessagingError
def __dealloc__(self):
del self.socket
def connect(self, Context context, string endpoint):
r = self.socket.connect(context.context, endpoint)
if r != 0:
if errno.errno == errno.EADDRINUSE:
raise MultiplePublishersError
else:
raise MessagingError
def send(self, string data):
length = len(data)
r = self.socket.send(<char*>data.c_str(), length)
if r != length:
if errno.errno == errno.EADDRINUSE:
raise MultiplePublishersError
else:
raise MessagingError
+56
View File
@@ -0,0 +1,56 @@
import os
import subprocess
import sysconfig
from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module
from Cython.Build import cythonize
from Cython.Distutils import build_ext
def get_ext_filename_without_platform_suffix(filename):
name, ext = os.path.splitext(filename)
ext_suffix = sysconfig.get_config_var('EXT_SUFFIX')
if ext_suffix == ext:
return filename
ext_suffix = ext_suffix.replace(ext, '')
idx = name.find(ext_suffix)
if idx == -1:
return filename
else:
return name[:idx] + ext
class BuildExtWithoutPlatformSuffix(build_ext):
def get_ext_filename(self, ext_name):
filename = super().get_ext_filename(ext_name)
return get_ext_filename_without_platform_suffix(filename)
sourcefiles = ['messaging_pyx.pyx']
extra_compile_args = ["-std=c++11"]
libraries = ['zmq']
ARCH = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip() # pylint: disable=unexpected-keyword-arg
if ARCH == "aarch64":
extra_compile_args += ["-Wno-deprecated-register"]
libraries += ['gnustl_shared']
setup(name='CAN parser',
cmdclass={'build_ext': BuildExtWithoutPlatformSuffix},
ext_modules=cythonize(
Extension(
"messaging_pyx",
language="c++",
sources=sourcefiles,
extra_compile_args=extra_compile_args,
libraries=libraries,
extra_objects=[
os.path.join(os.path.dirname(os.path.realpath(__file__)), '../', 'libmessaging.a'),
]
)
),
nthreads=4,
)
+449
View File
@@ -0,0 +1,449 @@
#include <iostream>
#include <cassert>
#include <cerrno>
#include <cmath>
#include <cstring>
#include <cstdint>
#include <chrono>
#include <algorithm>
#include <cstdlib>
#include <csignal>
#include <random>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/syscall.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include "msgq.hpp"
void sigusr2_handler(int signal) {
assert(signal == SIGUSR2);
}
uint64_t msgq_get_uid(void){
std::random_device rd("/dev/urandom");
std::uniform_int_distribution<uint64_t> distribution(0,std::numeric_limits<uint32_t>::max());
uint64_t uid = distribution(rd) << 32 | syscall(SYS_gettid);
return uid;
}
int msgq_msg_init_size(msgq_msg_t * msg, size_t size){
msg->size = size;
msg->data = new(std::nothrow) char[size];
return (msg->data == NULL) ? -1 : 0;
}
int msgq_msg_init_data(msgq_msg_t * msg, char * data, size_t size) {
int r = msgq_msg_init_size(msg, size);
if (r == 0)
memcpy(msg->data, data, size);
return r;
}
int msgq_msg_close(msgq_msg_t * msg){
if (msg->size > 0)
delete[] msg->data;
msg->size = 0;
return 0;
}
void msgq_reset_reader(msgq_queue_t * q){
int id = q->reader_id;
q->read_valids[id]->store(true);
q->read_pointers[id]->store(*q->write_pointer);
}
void msgq_wait_for_subscriber(msgq_queue_t *q){
while (*q->num_readers == 0){
;
}
return;
}
int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size){
assert(size < 0xFFFFFFFF); // Buffer must be smaller than 2^32 bytes
std::signal(SIGUSR2, sigusr2_handler);
const char * prefix = "/dev/shm/";
char * full_path = new char[strlen(path) + strlen(prefix) + 1];
strcpy(full_path, prefix);
strcat(full_path, path);
auto fd = open(full_path, O_RDWR | O_CREAT, 0777);
delete[] full_path;
if (fd < 0)
return -1;
int rc = ftruncate(fd, size + sizeof(msgq_header_t));
if (rc < 0)
return -1;
char * mem = (char*)mmap(NULL, size + sizeof(msgq_header_t), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
close(fd);
if (mem == NULL)
return -1;
q->mmap_p = mem;
msgq_header_t *header = (msgq_header_t *)mem;
// Setup pointers to header segment
q->num_readers = reinterpret_cast<std::atomic<uint64_t>*>(&header->num_readers);
q->write_pointer = reinterpret_cast<std::atomic<uint64_t>*>(&header->write_pointer);
q->write_uid = reinterpret_cast<std::atomic<uint64_t>*>(&header->write_uid);
for (size_t i = 0; i < NUM_READERS; i++){
q->read_pointers[i] = reinterpret_cast<std::atomic<uint64_t>*>(&header->read_pointers[i]);
q->read_valids[i] = reinterpret_cast<std::atomic<uint64_t>*>(&header->read_valids[i]);
q->read_uids[i] = reinterpret_cast<std::atomic<uint64_t>*>(&header->read_uids[i]);
}
q->data = mem + sizeof(msgq_header_t);
q->size = size;
q->reader_id = -1;
q->endpoint = path;
q->read_conflate = false;
return 0;
}
void msgq_close_queue(msgq_queue_t *q){
if (q->mmap_p != NULL){
munmap(q->mmap_p, q->size + sizeof(msgq_header_t));
}
}
void msgq_init_publisher(msgq_queue_t * q) {
//std::cout << "Starting publisher" << std::endl;
uint64_t uid = msgq_get_uid();
*q->write_uid = uid;
*q->num_readers = 0;
for (size_t i = 0; i < NUM_READERS; i++){
*q->read_valids[i] = false;
*q->read_uids[i] = 0;
}
q->write_uid_local = uid;
}
static void thread_signal(uint32_t tid) {
#ifndef SYS_tkill
// TODO: this won't work for multithreaded programs
kill(tid, SIGUSR2);
#else
syscall(SYS_tkill, tid, SIGUSR2);
#endif
}
void msgq_init_subscriber(msgq_queue_t * q) {
assert(q != NULL);
assert(q->num_readers != NULL);
uint64_t uid = msgq_get_uid();
// Get reader id
while (true){
uint64_t cur_num_readers = *q->num_readers;
uint64_t new_num_readers = cur_num_readers + 1;
// No more slots available. Reset all subscribers to kick out inactive ones
if (new_num_readers > NUM_READERS){
std::cout << "Warning, evicting all subscribers!" << std::endl;
*q->num_readers = 0;
for (size_t i = 0; i < NUM_READERS; i++){
*q->read_valids[i] = false;
uint64_t old_uid = *q->read_uids[i];
*q->read_uids[i] = 0;
// Wake up reader in case they are in a poll
thread_signal(old_uid & 0xFFFFFFFF);
}
continue;
}
// Use atomic compare and swap to handle race condition
// where two subscribers start at the same time
if (std::atomic_compare_exchange_strong(q->num_readers,
&cur_num_readers,
new_num_readers)){
q->reader_id = cur_num_readers;
q->read_uid_local = uid;
// We start with read_valid = false,
// on the first read the read pointer will be synchronized with the write pointer
*q->read_valids[cur_num_readers] = false;
*q->read_pointers[cur_num_readers] = 0;
*q->read_uids[cur_num_readers] = uid;
break;
}
}
//std::cout << "New subscriber id: " << q->reader_id << " uid: " << q->read_uid_local << " " << q->endpoint << std::endl;
msgq_reset_reader(q);
}
int msgq_msg_send(msgq_msg_t * msg, msgq_queue_t *q){
// Die if we are no longer the active publisher
if (q->write_uid_local != *q->write_uid){
std::cout << "Killing old publisher: " << q->endpoint << std::endl;
errno = EADDRINUSE;
return -1;
}
uint64_t total_msg_size = ALIGN(msg->size + sizeof(int64_t));
// We need to fit at least three messages in the queue,
// then we can always safely access the last message
assert(3 * total_msg_size <= q->size);
uint64_t num_readers = *q->num_readers;
uint32_t write_cycles, write_pointer;
UNPACK64(write_cycles, write_pointer, *q->write_pointer);
char *p = q->data + write_pointer; // add base offset
// Check remaining space
// Always leave space for a wraparound tag for the next message, including alignment
int64_t remaining_space = q->size - write_pointer - total_msg_size - sizeof(int64_t);
if (remaining_space <= 0){
// Write -1 size tag indicating wraparound
*(int64_t*)p = -1;
// Invalidate all readers that are beyond the write pointer
// TODO: should we handle the case where a new reader shows up while this is running?
for (uint64_t i = 0; i < num_readers; i++){
uint64_t read_pointer = *q->read_pointers[i];
uint64_t read_cycles = read_pointer >> 32;
read_pointer &= 0xFFFFFFFF;
if ((read_pointer > write_pointer) && (read_cycles != write_cycles)) {
*q->read_valids[i] = false;
}
}
// Update global and local copies of write pointer and write_cycles
write_pointer = 0;
write_cycles = write_cycles + 1;
PACK64(*q->write_pointer, write_cycles, write_pointer);
// Set actual pointer to the beginning of the data segment
p = q->data;
}
// Invalidate readers that are in the area that will be written
uint64_t start = write_pointer;
uint64_t end = ALIGN(start + sizeof(int64_t) + msg->size);
for (uint64_t i = 0; i < num_readers; i++){
uint32_t read_cycles, read_pointer;
UNPACK64(read_cycles, read_pointer, *q->read_pointers[i]);
if ((read_pointer >= start) && (read_pointer < end) && (read_cycles != write_cycles)) {
*q->read_valids[i] = false;
}
}
// Write size tag
std::atomic<int64_t> *size_p = reinterpret_cast<std::atomic<int64_t>*>(p);
*size_p = msg->size;
// Copy data
memcpy(p + sizeof(int64_t), msg->data, msg->size);
__sync_synchronize();
// Update write pointer
uint32_t new_ptr = ALIGN(write_pointer + msg->size + sizeof(int64_t));
PACK64(*q->write_pointer, write_cycles, new_ptr);
// Notify readers
for (uint64_t i = 0; i < num_readers; i++){
uint64_t reader_uid = *q->read_uids[i];
thread_signal(reader_uid & 0xFFFFFFFF);
}
return msg->size;
}
int msgq_msg_ready(msgq_queue_t * q){
start:
int id = q->reader_id;
assert(id >= 0); // Make sure subscriber is initialized
if (q->read_uid_local != *q->read_uids[id]){
std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl;
msgq_init_subscriber(q);
goto start;
}
// Check valid
if (!*q->read_valids[id]){
msgq_reset_reader(q);
goto start;
}
uint32_t read_cycles, read_pointer;
UNPACK64(read_cycles, read_pointer, *q->read_pointers[id]);
uint32_t write_cycles, write_pointer;
UNPACK64(write_cycles, write_pointer, *q->write_pointer);
// Check if new message is available
return (read_pointer != write_pointer);
}
int msgq_msg_recv(msgq_msg_t * msg, msgq_queue_t * q){
start:
int id = q->reader_id;
assert(id >= 0); // Make sure subscriber is initialized
if (q->read_uid_local != *q->read_uids[id]){
std::cout << q->endpoint << ": Reader was evicted, reconnecting" << std::endl;
msgq_init_subscriber(q);
goto start;
}
// Check valid
if (!*q->read_valids[id]){
msgq_reset_reader(q);
goto start;
}
uint32_t read_cycles, read_pointer;
UNPACK64(read_cycles, read_pointer, *q->read_pointers[id]);
uint32_t write_cycles, write_pointer;
UNPACK64(write_cycles, write_pointer, *q->write_pointer);
char * p = q->data + read_pointer;
// Check if new message is available
if (read_pointer == write_pointer) {
msg->size = 0;
return 0;
}
// Read potential message size
std::atomic<int64_t> *size_p = reinterpret_cast<std::atomic<int64_t>*>(p);
std::int64_t size = *size_p;
// Check if the size that was read is valid
if (!*q->read_valids[id]){
msgq_reset_reader(q);
goto start;
}
// If size is -1 the buffer was full, and we need to wrap around
if (size == -1){
read_cycles++;
PACK64(*q->read_pointers[id], read_cycles, 0);
goto start;
}
// crashing is better than passing garbage data to the consumer
// the size will have weird value if it was overwritten by data accidentally
assert((uint64_t)size < q->size);
assert(size > 0);
uint32_t new_read_pointer = ALIGN(read_pointer + sizeof(std::int64_t) + size);
// If conflate is true, check if this is the latest message, else start over
if (q->read_conflate){
if (new_read_pointer != write_pointer){
// Update read pointer
PACK64(*q->read_pointers[id], read_cycles, new_read_pointer);
goto start;
}
}
// Copy message
if (msgq_msg_init_size(msg, size) < 0)
return -1;
__sync_synchronize();
memcpy(msg->data, p + sizeof(int64_t), size);
__sync_synchronize();
// Update read pointer
PACK64(*q->read_pointers[id], read_cycles, new_read_pointer);
// Check if the actual data that was copied is valid
if (!*q->read_valids[id]){
msgq_msg_close(msg);
msgq_reset_reader(q);
goto start;
}
return msg->size;
}
int msgq_poll(msgq_pollitem_t * items, size_t nitems, int timeout){
assert(timeout >= 0);
int num = 0;
// Check if messages ready
for (size_t i = 0; i < nitems; i++) {
items[i].revents = msgq_msg_ready(items[i].q);
if (items[i].revents) num++;
}
int ms = (timeout == -1) ? 100 : timeout;
struct timespec ts;
ts.tv_sec = ms / 1000;
ts.tv_nsec = (ms % 1000) * 1000 * 1000;
while (num == 0) {
int ret;
ret = nanosleep(&ts, &ts);
// Check if messages ready
for (size_t i = 0; i < nitems; i++) {
if (items[i].revents == 0 && msgq_msg_ready(items[i].q)){
num += 1;
items[i].revents = 1;
}
}
// exit if we had a timeout and the sleep finished
if (timeout != -1 && ret == 0){
break;
}
}
return num;
}
+66
View File
@@ -0,0 +1,66 @@
#pragma once
#include <cstdint>
#include <cstring>
#include <string>
#include <atomic>
#define DEFAULT_SEGMENT_SIZE (10 * 1024 * 1024)
#define NUM_READERS 8
#define ALIGN(n) ((n + (8 - 1)) & -8)
#define UNPACK64(higher, lower, input) do {uint64_t tmp = input; higher = tmp >> 32; lower = tmp & 0xFFFFFFFF;} while (0)
#define PACK64(output, higher, lower) output = ((uint64_t)higher << 32 ) | ((uint64_t)lower & 0xFFFFFFFF)
struct msgq_header_t {
uint64_t num_readers;
uint64_t write_pointer;
uint64_t write_uid;
uint64_t read_pointers[NUM_READERS];
uint64_t read_valids[NUM_READERS];
uint64_t read_uids[NUM_READERS];
};
struct msgq_queue_t {
std::atomic<uint64_t> *num_readers;
std::atomic<uint64_t> *write_pointer;
std::atomic<uint64_t> *write_uid;
std::atomic<uint64_t> *read_pointers[NUM_READERS];
std::atomic<uint64_t> *read_valids[NUM_READERS];
std::atomic<uint64_t> *read_uids[NUM_READERS];
char * mmap_p;
char * data;
size_t size;
int reader_id;
uint64_t read_uid_local;
uint64_t write_uid_local;
bool read_conflate;
std::string endpoint;
};
struct msgq_msg_t {
size_t size;
char * data;
};
struct msgq_pollitem_t {
msgq_queue_t *q;
int revents;
};
void msgq_wait_for_subscriber(msgq_queue_t *q);
void msgq_reset_reader(msgq_queue_t *q);
int msgq_msg_init_size(msgq_msg_t *msg, size_t size);
int msgq_msg_init_data(msgq_msg_t *msg, char * data, size_t size);
int msgq_msg_close(msgq_msg_t *msg);
int msgq_new_queue(msgq_queue_t * q, const char * path, size_t size);
void msgq_close_queue(msgq_queue_t *q);
void msgq_init_publisher(msgq_queue_t * q);
void msgq_init_subscriber(msgq_queue_t * q);
int msgq_msg_send(msgq_msg_t *msg, msgq_queue_t *q);
int msgq_msg_recv(msgq_msg_t *msg, msgq_queue_t *q);
int msgq_msg_ready(msgq_queue_t * q);
int msgq_poll(msgq_pollitem_t * items, size_t nitems, int timeout);
+56
View File
@@ -0,0 +1,56 @@
# MSGQ: A lock free single producer multi consumer message queue
[![Build Status](https://dev.azure.com/commaai/default/_apis/build/status/commaai.msgq?branchName=master)](https://dev.azure.com/commaai/default/_build/latest?definitionId=21&branchName=master)
## What is MSGQ?
MSGQ is a system to pass messages from a single producer to multiple consumers. All the consumers need to be able to receive all the messages. It is designed to be a high performance replacement for ZMQ-like SUB/PUB patterns. It uses a ring buffer in shared memory to efficiently read and write data. Each read requires a copy. Writing can be done without a copy, as long as the size of the data is known in advance.
## Storage
The storage for the queue consists of an area of metadata, and the actual buffer. The metadata contains:
1. A counter to the number of readers that are active
2. A pointer to the head of the queue for writing. From now on referred to as *write pointer*
3. A cycle counter for the writer. This counter is incremented when the writer wraps around
4. N pointers, pointing to the current read position for all the readers. From now on referred to as *read pointer*
5. N counters, counting the number of cycles for all the readers
6. N booleans, indicating validity for all the readers. From now on referred to as *validity flag*
The counter and the pointer are both 32 bit values, packed into 64 bit so they can be read and written atomically.
The data buffer is a ring buffer. All messages are prefixed by an 8 byte size field, followed by the data. A size of -1 indicates a wrap-around, and means the next message is stored at the beginning of the buffer.
## Writing
Writing involves the following steps:
1. Check if the area that is to be written overlaps with any of the read pointers, mark those readers as invalid by clearing the validity flag.
2. Write the message
3. Increase the write pointer by the size of the message
In case there is not enough space at the end of the buffer, a special empty message with a prefix of -1 is written. The cycle counter is incremented by one. In this case step 1 will check there are no read pointers pointing to the remainder of the buffer. Then another write cycle will start with the actual message.
There always needs to be 8 bytes of empty space at the end of the buffer. By doing this there is always space to write the -1.
## Reset reader
When the reader is lagging too much behind the read pointer becomes invalid and no longer points to the beginning of a valid message. To reset a reader to the current write pointer, the following steps are performed:
1. Set valid flag
2. Set read cycle counter to that of the writer
3. Set read pointer to write pointer
## Reading
Reading involves the following steps:
1. Read the size field at the current read pointer
2. Read the validity flag
3. Copy the data out of the buffer
4. Increase the read pointer by the size of the message
5. Check the validity flag again
Before starting the copy, the valid flag is checked. This is to prevent a race condition where the size prefix was invalid, and the read could read outside of the buffer. Make sure that step 1 and 2 are not reordered by your compiler or CPU.
If a writer overwrites the data while it's being copied out, the data will be invalid. Therefore the validity flag is also checked after reading it. The order of step 4 and 5 does not matter.
If at steps 2 or 5 the validity flag is not set, the reader is reset. Any data that was already read is discarded. After the reader is reset, the reading starts from the beginning.
If a message with size -1 is encountered, step 3 and 4 are replaced by increasing the cycle counter and setting the read pointer to the beginning of the buffer. After that another read is performed.
+395
View File
@@ -0,0 +1,395 @@
#include "catch2/catch.hpp"
#include "msgq.hpp"
TEST_CASE("ALIGN"){
REQUIRE(ALIGN(0) == 0);
REQUIRE(ALIGN(1) == 8);
REQUIRE(ALIGN(7) == 8);
REQUIRE(ALIGN(8) == 8);
REQUIRE(ALIGN(99999) == 100000);
}
TEST_CASE("msgq_msg_init_size"){
const size_t msg_size = 30;
msgq_msg_t msg;
msgq_msg_init_size(&msg, msg_size);
REQUIRE(msg.size == msg_size);
msgq_msg_close(&msg);
}
TEST_CASE("msgq_msg_init_data"){
const size_t msg_size = 30;
char * data = new char[msg_size];
for (size_t i = 0; i < msg_size; i++){
data[i] = i;
}
msgq_msg_t msg;
msgq_msg_init_data(&msg, data, msg_size);
REQUIRE(msg.size == msg_size);
REQUIRE(memcmp(msg.data, data, msg_size) == 0);
delete[] data;
msgq_msg_close(&msg);
}
TEST_CASE("msgq_init_subscriber"){
remove("/dev/shm/test_queue");
msgq_queue_t q;
msgq_new_queue(&q, "test_queue", 1024);
REQUIRE(*q.num_readers == 0);
q.reader_id = 1;
*q.read_valids[0] = false;
*q.read_pointers[0] = ((uint64_t)1 << 32);
*q.write_pointer = 255;
msgq_init_subscriber(&q);
REQUIRE(q.read_conflate == false);
REQUIRE(*q.read_valids[0] == true);
REQUIRE((*q.read_pointers[0] >> 32) == 0);
REQUIRE((*q.read_pointers[0] & 0xFFFFFFFF) == 255);
}
TEST_CASE("msgq_msg_send first message"){
remove("/dev/shm/test_queue");
msgq_queue_t q;
msgq_new_queue(&q, "test_queue", 1024);
msgq_init_publisher(&q);
REQUIRE(*q.write_pointer == 0);
size_t msg_size = 128;
SECTION("Aligned message size"){
}
SECTION("Unaligned message size"){
msg_size--;
}
char * data = new char[msg_size];
for (size_t i = 0; i < msg_size; i++){
data[i] = i;
}
msgq_msg_t msg;
msgq_msg_init_data(&msg, data, msg_size);
msgq_msg_send(&msg, &q);
REQUIRE(*(int64_t*)q.data == msg_size); // Check size tag
REQUIRE(*q.write_pointer == 128 + sizeof(int64_t));
REQUIRE(memcmp(q.data + sizeof(int64_t), data, msg_size) == 0);
delete[] data;
msgq_msg_close(&msg);
}
TEST_CASE("msgq_msg_send test wraparound"){
remove("/dev/shm/test_queue");
msgq_queue_t q;
msgq_new_queue(&q, "test_queue", 1024);
msgq_init_publisher(&q);
REQUIRE((*q.write_pointer & 0xFFFFFFFF) == 0);
REQUIRE((*q.write_pointer >> 32) == 0);
const size_t msg_size = 120;
msgq_msg_t msg;
msgq_msg_init_size(&msg, msg_size);
for (int i = 0; i < 8; i++) {
msgq_msg_send(&msg, &q);
}
// Check 8th message was written at the beginning
REQUIRE((*q.write_pointer & 0xFFFFFFFF) == msg_size + sizeof(int64_t));
// Check cycle count
REQUIRE((*q.write_pointer >> 32) == 1);
// Check wraparound tag
char * tag_location = q.data;
tag_location += 7 * (msg_size + sizeof(int64_t));
REQUIRE(*(int64_t*)tag_location == -1);
msgq_msg_close(&msg);
}
TEST_CASE("msgq_msg_recv test wraparound"){
remove("/dev/shm/test_queue");
msgq_queue_t q_pub, q_sub;
msgq_new_queue(&q_pub, "test_queue", 1024);
msgq_new_queue(&q_sub, "test_queue", 1024);
msgq_init_publisher(&q_pub);
msgq_init_subscriber(&q_sub);
REQUIRE((*q_pub.write_pointer >> 32) == 0);
REQUIRE((*q_sub.read_pointers[0] >> 32) == 0);
const size_t msg_size = 120;
msgq_msg_t msg1;
msgq_msg_init_size(&msg1, msg_size);
SECTION("Check cycle counter after reset") {
for (int i = 0; i < 8; i++) {
msgq_msg_send(&msg1, &q_pub);
}
msgq_msg_t msg2;
msgq_msg_recv(&msg2, &q_sub);
REQUIRE(msg2.size == 0); // Reader had to reset
msgq_msg_close(&msg2);
}
SECTION("Check cycle counter while keeping up with writer") {
for (int i = 0; i < 8; i++) {
msgq_msg_send(&msg1, &q_pub);
msgq_msg_t msg2;
msgq_msg_recv(&msg2, &q_sub);
REQUIRE(msg2.size > 0);
msgq_msg_close(&msg2);
}
}
REQUIRE((*q_sub.read_pointers[0] >> 32) == 1);
msgq_msg_close(&msg1);
}
TEST_CASE("msgq_msg_send test invalidation"){
remove("/dev/shm/test_queue");
msgq_queue_t q_pub, q_sub;
msgq_new_queue(&q_pub, "test_queue", 1024);
msgq_new_queue(&q_sub, "test_queue", 1024);
msgq_init_publisher(&q_pub);
msgq_init_subscriber(&q_sub);
*q_sub.write_pointer = (uint64_t)1 << 32;
REQUIRE(*q_sub.read_valids[0] == true);
SECTION("read pointer in tag"){
*q_sub.read_pointers[0] = 0;
}
SECTION("read pointer in data section"){
*q_sub.read_pointers[0] = 64;
}
SECTION("read pointer in wraparound section"){
*q_pub.write_pointer = ((uint64_t)1 << 32) | 1000; // Writer is one cycle ahead
*q_sub.read_pointers[0] = 1020;
}
msgq_msg_t msg;
msgq_msg_init_size(&msg, 128);
msgq_msg_send(&msg, &q_pub);
REQUIRE(*q_sub.read_valids[0] == false);
msgq_msg_close(&msg);
}
TEST_CASE("msgq_init_subscriber init 2 subscribers"){
remove("/dev/shm/test_queue");
msgq_queue_t q1, q2;
msgq_new_queue(&q1, "test_queue", 1024);
msgq_new_queue(&q2, "test_queue", 1024);
*q1.num_readers = 0;
REQUIRE(*q1.num_readers == 0);
REQUIRE(*q2.num_readers == 0);
msgq_init_subscriber(&q1);
REQUIRE(*q1.num_readers == 1);
REQUIRE(*q2.num_readers == 1);
REQUIRE(q1.reader_id == 0);
msgq_init_subscriber(&q2);
REQUIRE(*q1.num_readers == 2);
REQUIRE(*q2.num_readers == 2);
REQUIRE(q2.reader_id == 1);
}
TEST_CASE("Write 1 msg, read 1 msg", "[integration]"){
remove("/dev/shm/test_queue");
const size_t msg_size = 128;
msgq_queue_t writer, reader;
msgq_new_queue(&writer, "test_queue", 1024);
msgq_new_queue(&reader, "test_queue", 1024);
msgq_init_publisher(&writer);
msgq_init_subscriber(&reader);
// Build 128 byte message
msgq_msg_t outgoing_msg;
msgq_msg_init_size(&outgoing_msg, msg_size);
for (size_t i = 0; i < msg_size; i++){
outgoing_msg.data[i] = i;
}
REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size);
msgq_msg_t incoming_msg1;
REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size);
REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0);
// Verify that there are no more messages
msgq_msg_t incoming_msg2;
REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == 0);
msgq_msg_close(&outgoing_msg);
msgq_msg_close(&incoming_msg1);
msgq_msg_close(&incoming_msg2);
}
TEST_CASE("Write 2 msg, read 2 msg - conflate = false", "[integration]"){
remove("/dev/shm/test_queue");
const size_t msg_size = 128;
msgq_queue_t writer, reader;
msgq_new_queue(&writer, "test_queue", 1024);
msgq_new_queue(&reader, "test_queue", 1024);
msgq_init_publisher(&writer);
msgq_init_subscriber(&reader);
// Build 128 byte message
msgq_msg_t outgoing_msg;
msgq_msg_init_size(&outgoing_msg, msg_size);
for (size_t i = 0; i < msg_size; i++){
outgoing_msg.data[i] = i;
}
REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size);
REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size);
msgq_msg_t incoming_msg1;
REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size);
REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0);
msgq_msg_t incoming_msg2;
REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == msg_size);
REQUIRE(memcmp(incoming_msg2.data, outgoing_msg.data, msg_size) == 0);
msgq_msg_close(&outgoing_msg);
msgq_msg_close(&incoming_msg1);
msgq_msg_close(&incoming_msg2);
}
TEST_CASE("Write 2 msg, read 2 msg - conflate = true", "[integration]"){
remove("/dev/shm/test_queue");
const size_t msg_size = 128;
msgq_queue_t writer, reader;
msgq_new_queue(&writer, "test_queue", 1024);
msgq_new_queue(&reader, "test_queue", 1024);
msgq_init_publisher(&writer);
msgq_init_subscriber(&reader);
reader.read_conflate = true;
// Build 128 byte message
msgq_msg_t outgoing_msg;
msgq_msg_init_size(&outgoing_msg, msg_size);
for (size_t i = 0; i < msg_size; i++){
outgoing_msg.data[i] = i;
}
REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size);
REQUIRE(msgq_msg_send(&outgoing_msg, &writer) == msg_size);
msgq_msg_t incoming_msg1;
REQUIRE(msgq_msg_recv(&incoming_msg1, &reader) == msg_size);
REQUIRE(memcmp(incoming_msg1.data, outgoing_msg.data, msg_size) == 0);
// Verify that there are no more messages
msgq_msg_t incoming_msg2;
REQUIRE(msgq_msg_recv(&incoming_msg2, &reader) == 0);
msgq_msg_close(&outgoing_msg);
msgq_msg_close(&incoming_msg1);
msgq_msg_close(&incoming_msg2);
}
TEST_CASE("1 publisher, 1 slow subscriber", "[integration]"){
remove("/dev/shm/test_queue");
msgq_queue_t writer, reader;
msgq_new_queue(&writer, "test_queue", 1024);
msgq_new_queue(&reader, "test_queue", 1024);
msgq_init_publisher(&writer);
msgq_init_subscriber(&reader);
int n_received = 0;
int n_skipped = 0;
for (uint64_t i = 0; i < 1e5; i++) {
msgq_msg_t outgoing_msg;
msgq_msg_init_data(&outgoing_msg, (char*)&i, sizeof(uint64_t));
msgq_msg_send(&outgoing_msg, &writer);
msgq_msg_close(&outgoing_msg);
if (i % 10 == 0){
msgq_msg_t msg1;
msgq_msg_recv(&msg1, &reader);
if (msg1.size == 0){
n_skipped++;
} else {
n_received++;
}
msgq_msg_close(&msg1);
}
}
// TODO: verify these numbers by hand
REQUIRE(n_received == 8572);
REQUIRE(n_skipped == 1428);
}
TEST_CASE("1 publisher, 2 subscribers", "[integration]"){
remove("/dev/shm/test_queue");
msgq_queue_t writer, reader1, reader2;
msgq_new_queue(&writer, "test_queue", 1024);
msgq_new_queue(&reader1, "test_queue", 1024);
msgq_new_queue(&reader2, "test_queue", 1024);
msgq_init_publisher(&writer);
msgq_init_subscriber(&reader1);
msgq_init_subscriber(&reader2);
for (uint64_t i = 0; i < 1024 * 3; i++) {
msgq_msg_t outgoing_msg;
msgq_msg_init_data(&outgoing_msg, (char*)&i, sizeof(uint64_t));
msgq_msg_send(&outgoing_msg, &writer);
msgq_msg_t msg1, msg2;
msgq_msg_recv(&msg1, &reader1);
msgq_msg_recv(&msg2, &reader2);
REQUIRE(msg1.size == sizeof(uint64_t));
REQUIRE(msg2.size == sizeof(uint64_t));
REQUIRE(*(uint64_t*)msg1.data == i);
REQUIRE(*(uint64_t*)msg2.data == i);
msgq_msg_close(&outgoing_msg);
msgq_msg_close(&msg1);
msgq_msg_close(&msg2);
}
}
+14
View File
@@ -0,0 +1,14 @@
from messaging_pyx import Context, SubSocket, PubSocket # pylint: disable=no-name-in-module, import-error
if __name__ == "__main__":
c = Context()
pub_sock = PubSocket()
pub_sock.connect(c, "controlsState")
for i in range(int(1e10)):
print(i)
sub_sock = SubSocket()
sub_sock.connect(c, "controlsState")
pub_sock.send(b'a')
print(sub_sock.receive())
+2
View File
@@ -0,0 +1,2 @@
#define CATCH_CONFIG_MAIN
#include "catch2/catch.hpp"
+142
View File
@@ -0,0 +1,142 @@
import unittest
import time
import cereal.messaging as messaging
import concurrent.futures
def poller():
context = messaging.Context()
p = messaging.Poller()
sub = messaging.SubSocket()
sub.connect(context, 'controlsState')
p.registerSocket(sub)
socks = p.poll(10000)
r = [s.receive(non_blocking=True) for s in socks]
return r
class TestPoller(unittest.TestCase):
def test_poll_once(self):
context = messaging.Context()
pub = messaging.PubSocket()
pub.connect(context, 'controlsState')
with concurrent.futures.ThreadPoolExecutor() as e:
poll = e.submit(poller)
time.sleep(0.1) # Slow joiner syndrome
# Send message
pub.send("a")
# Wait for poll result
result = poll.result()
del pub
context.term()
self.assertEqual(result, [b"a"])
def test_poll_and_create_many_subscribers(self):
context = messaging.Context()
pub = messaging.PubSocket()
pub.connect(context, 'controlsState')
with concurrent.futures.ThreadPoolExecutor() as e:
poll = e.submit(poller)
time.sleep(0.1) # Slow joiner syndrome
c = messaging.Context()
for _ in range(10):
messaging.SubSocket().connect(c, 'controlsState')
time.sleep(0.1)
# Send message
pub.send("a")
# Wait for poll result
result = poll.result()
del pub
context.term()
self.assertEqual(result, [b"a"])
def test_multiple_publishers_exception(self):
context = messaging.Context()
with self.assertRaises(messaging.MultiplePublishersError):
pub1 = messaging.PubSocket()
pub1.connect(context, 'controlsState')
pub2 = messaging.PubSocket()
pub2.connect(context, 'controlsState')
pub1.send("a")
del pub1
del pub2
context.term()
def test_multiple_messages(self):
context = messaging.Context()
pub = messaging.PubSocket()
pub.connect(context, 'controlsState')
sub = messaging.SubSocket()
sub.connect(context, 'controlsState')
time.sleep(0.1) # Slow joiner
for i in range(100):
pub.send(str(i))
msg_seen = False
i = 0
while True:
r = sub.receive(non_blocking=True)
if r is not None:
self.assertEqual(str(i), r.decode('utf8'))
msg_seen = True
i += 1
if r is None and msg_seen: # ZMQ sometimes receives nothing on the first receive
break
del pub
del sub
context.term()
def test_conflate(self):
context = messaging.Context()
pub = messaging.PubSocket()
pub.connect(context, 'controlsState')
sub = messaging.SubSocket()
sub.connect(context, 'controlsState', conflate=True)
time.sleep(0.1) # Slow joiner
pub.send('a')
pub.send('b')
self.assertEqual(b'b', sub.receive())
del pub
del sub
context.term()
if __name__ == "__main__":
unittest.main()
@@ -25,7 +25,7 @@ encodeIdx: [8015, true, 20.]
liveTracks: [8016, true, 20.]
sendcan: [8017, true, 100.]
logMessage: [8018, true, 0.]
liveCalibration: [8019, true, 5.]
liveCalibration: [8019, true, 4., 4]
androidLog: [8020, true, 0.]
carState: [8021, true, 100., 10]
# 8022 is reserved for sshd
@@ -43,7 +43,6 @@ ubloxGnss: [8033, true, 10.]
clocks: [8034, true, 1., 1]
liveMpc: [8035, false, 20.]
liveLongitudinalMpc: [8036, false, 20.]
plusFrame: [8037, false, 0.]
navStatus: [8038, true, 0.]
gpsLocationTrimble: [8039, true, 0.]
trimbleGnss: [8041, true, 0.]
@@ -66,15 +65,17 @@ orbKeyFrame: [8059, true, 0.]
uiLayoutState: [8060, true, 0.]
frontEncodeIdx: [8061, true, 5.]
orbFeaturesSummary: [8062, true, 0.]
driverMonitoring: [8063, true, 5., 1]
driverState: [8063, true, 5., 1]
liveParameters: [8064, true, 10.]
liveMapData: [8065, true, 0.]
cameraOdometry: [8066, true, 5.]
cameraOdometry: [8066, true, 20., 5]
pathPlan: [8067, true, 20.]
kalmanOdometry: [8068, true, 0.]
thumbnail: [8069, true, 0.2, 1]
carEvents: [8070, true, 1., 1]
carParams: [8071, true, 0.02, 1]
frontFrame: [8072, true, 10.]
dMonitoringState: [8073, true, 5., 1]
testModel: [8040, false, 0.]
testLiveLocation: [8045, false, 0.]
+33
View File
@@ -0,0 +1,33 @@
#!/usr/bin/env python3
import os
import yaml
class Service():
def __init__(self, port, should_log, frequency, decimation=None):
self.port = port
self.should_log = should_log
self.frequency = frequency
self.decimation = decimation
service_list_path = os.path.join(os.path.dirname(__file__), "service_list.yaml")
service_list = {}
with open(service_list_path, "r") as f:
for k, v in yaml.safe_load(f).items():
decimation = None
if len(v) == 4:
decimation = v[3]
service_list[k] = Service(v[0], v[1], v[2], decimation)
if __name__ == "__main__":
print("/* THIS IS AN AUTOGENERATED FILE, PLEASE EDIT service_list.yaml */")
print("#ifndef __SERVICES_H")
print("#define __SERVICES_H")
print("struct service { int port; bool should_log; int frequency; int decimation; char name[0x100]; };")
print("static struct service services[] = {")
for k, v in service_list.items():
print(' { .name = "%s", .port = %d, .should_log = %s, .frequency = %d, .decimation = %d },' % (k, v.port, "true" if v.should_log else "false", v.frequency, -1 if v.decimation is None else v.decimation))
print("};")
print("#endif")
-11
View File
@@ -1,11 +0,0 @@
#!/bin/bash
pyflakes $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda")
RESULT=$?
if [ $RESULT -eq 0 ]; then
pylint $(find . -iname "*.py" | grep -vi "^\./pyextra.*" | grep -vi "^\./panda")
RESULT=$? & 3
fi
[ $RESULT -ne 0 ] && exit 1
exit 0
+1
View File
@@ -0,0 +1 @@
*.cpp
+6
View File
@@ -0,0 +1,6 @@
Import('env')
# parser
env.Command(['common_pyx.so'],
['common_pyx_setup.py', 'clock.pyx'],
"cd common && python3 common_pyx_setup.py build_ext --inplace")
+130
View File
@@ -0,0 +1,130 @@
import os
import binascii
import itertools
import re
import struct
import subprocess
import random
from cereal import log
NetworkType = log.ThermalData.NetworkType
ANDROID = os.path.isfile('/EON')
def getprop(key):
if not ANDROID:
return ""
return subprocess.check_output(["getprop", key], encoding='utf8').strip()
def get_imei(slot):
slot = str(slot)
if slot not in ("0", "1"):
raise ValueError("SIM slot must be 0 or 1")
ret = parse_service_call_string(service_call(["iphonesubinfo", "3" ,"i32", str(slot)]))
if not ret:
# allow non android to be identified differently
ret = "%015d" % random.randint(0, 1<<32)
return ret
def get_serial():
ret = getprop("ro.serialno")
if ret == "":
ret = "cccccccc"
return ret
def get_subscriber_info():
ret = parse_service_call_string(service_call(["iphonesubinfo", "7"]))
if ret is None or len(ret) < 8:
return ""
return ret
def reboot(reason=None):
if reason is None:
reason_args = ["null"]
else:
reason_args = ["s16", reason]
subprocess.check_output([
"service", "call", "power", "16", # IPowerManager.reboot
"i32", "0", # no confirmation,
*reason_args,
"i32", "1" # wait
])
def service_call(call):
if not ANDROID:
return None
ret = subprocess.check_output(["service", "call", *call], encoding='utf8').strip()
if 'Parcel' not in ret:
return None
return parse_service_call_bytes(ret)
def parse_service_call_unpack(r, fmt):
try:
return struct.unpack(fmt, r)[0]
except Exception:
return None
def parse_service_call_string(r):
try:
r = r[8:] # Cut off length field
r = r.decode('utf_16_be')
# All pairs of two characters seem to be swapped. Not sure why
result = ""
for a, b, in itertools.zip_longest(r[::2], r[1::2], fillvalue='\x00'):
result += b + a
result = result.replace('\x00', '')
return result
except Exception:
return None
def parse_service_call_bytes(ret):
try:
r = b""
for hex_part in re.findall(r'[ (]([0-9a-f]{8})', ret):
r += binascii.unhexlify(hex_part)
return r
except Exception:
return None
def get_network_type():
if not ANDROID:
return NetworkType.none
wifi_check = parse_service_call_string(service_call(["connectivity", "2"]))
if wifi_check is None:
return NetworkType.none
elif 'WIFI' in wifi_check:
return NetworkType.wifi
else:
cell_check = parse_service_call_unpack(service_call(['phone', '59']), ">q")
# from TelephonyManager.java
cell_networks = {
0: NetworkType.none,
1: NetworkType.cell2G,
2: NetworkType.cell2G,
3: NetworkType.cell3G,
4: NetworkType.cell2G,
5: NetworkType.cell3G,
6: NetworkType.cell3G,
7: NetworkType.cell3G,
8: NetworkType.cell3G,
9: NetworkType.cell3G,
10: NetworkType.cell3G,
11: NetworkType.cell2G,
12: NetworkType.cell3G,
13: NetworkType.cell4G,
14: NetworkType.cell4G,
15: NetworkType.cell3G,
16: NetworkType.cell2G,
17: NetworkType.cell3G,
18: NetworkType.cell4G,
19: NetworkType.cell4G
}
return cell_networks.get(cell_check, NetworkType.none)
+2 -2
View File
@@ -1,13 +1,13 @@
import jwt
import requests
from datetime import datetime, timedelta
from common.basedir import PERSIST
from selfdrive.version import version
class Api():
def __init__(self, dongle_id):
self.dongle_id = dongle_id
with open('/persist/comma/id_rsa') as f:
with open(PERSIST+'/comma/id_rsa') as f:
self.private_key = f.read()
def get(self, *args, **kwargs):
+99
View File
@@ -0,0 +1,99 @@
import os
import subprocess
import glob
import hashlib
import shutil
from common.basedir import BASEDIR
from selfdrive.swaglog import cloudlog
android_packages = ("tw.com.ainvest.outpack", "cn.dragonpilot.gpsservice", "com.autonavi.amapauto", "com.mixplorer", "com.tomtom.speedcams.android.map", "ai.comma.plus.offroad", "ai.comma.plus.frame")
def get_installed_apks():
dat = subprocess.check_output(["pm", "list", "packages", "-f"], encoding='utf8').strip().split("\n")
ret = {}
for x in dat:
if x.startswith("package:"):
v,k = x.split("package:")[1].split("=")
ret[k] = v
return ret
def install_apk(path):
# can only install from world readable path
install_path = "/sdcard/%s" % os.path.basename(path)
shutil.copyfile(path, install_path)
ret = subprocess.call(["pm", "install", "-r", install_path])
os.remove(install_path)
return ret == 0
def start_frame():
set_package_permissions()
system("am start -n ai.comma.plus.frame/.MainActivity")
def set_package_permissions():
pm_grant("ai.comma.plus.offroad", "android.permission.ACCESS_FINE_LOCATION")
pm_grant("ai.comma.plus.offroad", "android.permission.READ_PHONE_STATE")
appops_set("ai.comma.plus.offroad", "SU", "allow")
appops_set("ai.comma.plus.offroad", "WIFI_SCAN", "allow")
appops_set("ai.comma.plus.offroad", "READ_EXTERNAL_STORAGE", "allow")
appops_set("ai.comma.plus.offroad", "WRITE_EXTERNAL_STORAGE", "allow")
def appops_set(package, op, mode):
system(f"LD_LIBRARY_PATH= appops set {package} {op} {mode}")
def pm_grant(package, permission):
system(f"pm grant {package} {permission}")
def system(cmd):
try:
cloudlog.info("running %s" % cmd)
subprocess.check_output(cmd, stderr=subprocess.STDOUT, shell=True)
except subprocess.CalledProcessError as e:
cloudlog.event("running failed",
cmd=e.cmd,
output=e.output[-1024:],
returncode=e.returncode)
# *** external functions ***
def update_apks():
# install apks
installed = get_installed_apks()
install_apks = glob.glob(os.path.join(BASEDIR, "apk/*.apk"))
for apk in install_apks:
app = os.path.basename(apk)[:-4]
if app not in installed:
installed[app] = None
cloudlog.info("installed apks %s" % (str(installed), ))
for app in installed.keys():
apk_path = os.path.join(BASEDIR, "apk/"+app+".apk")
if not os.path.exists(apk_path):
continue
h1 = hashlib.sha1(open(apk_path, 'rb').read()).hexdigest()
h2 = None
if installed[app] is not None:
h2 = hashlib.sha1(open(installed[app], 'rb').read()).hexdigest()
cloudlog.info("comparing version of %s %s vs %s" % (app, h1, h2))
if h2 is None or h1 != h2:
cloudlog.info("installing %s" % app)
success = install_apk(apk_path)
if not success:
cloudlog.info("needing to uninstall %s" % app)
system("pm uninstall %s" % app)
success = install_apk(apk_path)
assert success
def pm_apply_packages(cmd):
for p in android_packages:
system("pm %s %s" % (cmd, p))
if __name__ == "__main__":
update_apks()
+7
View File
@@ -1,4 +1,11 @@
import os
BASEDIR = os.path.abspath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../"))
from common.android import ANDROID
if ANDROID:
PERSIST = "/persist"
PARAMS = "/data/params"
else:
PERSIST = os.path.join(BASEDIR, "persist")
PARAMS = os.path.join(BASEDIR, "persist", "params")
+15 -9
View File
@@ -1,16 +1,22 @@
from posix.time cimport clock_gettime, timespec, CLOCK_BOOTTIME, CLOCK_MONOTONIC_RAW
from posix.time cimport clock_gettime, timespec, CLOCK_MONOTONIC_RAW, clockid_t
cdef double readclock(int clock_id):
cdef timespec ts
cdef double current
IF UNAME_SYSNAME == "Darwin":
# Darwin doesn't have a CLOCK_BOOTTIME
CLOCK_BOOTTIME = CLOCK_MONOTONIC_RAW
ELSE:
from posix.time cimport CLOCK_BOOTTIME
clock_gettime(clock_id, &ts)
current = ts.tv_sec + (ts.tv_nsec / 1000000000.)
return current
cdef double readclock(clockid_t clock_id):
cdef timespec ts
cdef double current
clock_gettime(clock_id, &ts)
current = ts.tv_sec + (ts.tv_nsec / 1000000000.)
return current
def monotonic_time():
return readclock(CLOCK_MONOTONIC_RAW)
return readclock(CLOCK_MONOTONIC_RAW)
def sec_since_boot():
return readclock(CLOCK_BOOTTIME)
return readclock(CLOCK_BOOTTIME)
+20
View File
@@ -0,0 +1,20 @@
from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module
from Cython.Build import cythonize
from common.cython_hacks import BuildExtWithoutPlatformSuffix
sourcefiles = ['clock.pyx']
extra_compile_args = ["-std=c++11"]
setup(name='Common',
cmdclass={'build_ext': BuildExtWithoutPlatformSuffix},
ext_modules=cythonize(
Extension(
"common_pyx",
language="c++",
sources=sourcefiles,
extra_compile_args=extra_compile_args,
)
),
nthreads=4,
)
+6
View File
@@ -2,8 +2,14 @@ import os
import sys
import fcntl
import hashlib
import platform
from cffi import FFI
def suffix():
if platform.system() == "Darwin":
return ".dylib"
else:
return ".so"
def ffi_wrap(name, c_code, c_header, tmpdir="/tmp/ccache", cflags="", libraries=None):
if libraries is None:
+1
View File
@@ -0,0 +1 @@
simple_kalman_impl.c
-10
View File
@@ -1,10 +0,0 @@
all: simple_kalman_impl.so
simple_kalman_impl.so: simple_kalman_impl.pyx simple_kalman_impl.pxd simple_kalman_setup.py
python3 simple_kalman_setup.py build_ext --inplace
rm -rf build
rm simple_kalman_impl.c
.PHONY: clean
clean:
rm -f simple_kalman_impl.so
+6
View File
@@ -0,0 +1,6 @@
Import('env')
env.Command(['simple_kalman_impl.so'],
['simple_kalman_impl.pyx', 'simple_kalman_impl.pxd', 'simple_kalman_setup.py'],
"cd common/kalman && python3 simple_kalman_setup.py build_ext --inplace")
+1 -8
View File
@@ -1,10 +1,3 @@
# pylint: skip-file
import os
import subprocess
kalman_dir = os.path.dirname(os.path.abspath(__file__))
subprocess.check_call(["make", "simple_kalman_impl.so"], cwd=kalman_dir)
from .simple_kalman_impl import KF1D as KF1D
# Silence pyflakes
from common.kalman.simple_kalman_impl import KF1D as KF1D
assert KF1D
+1 -1
View File
@@ -1,4 +1,4 @@
from distutils.core import Extension, setup # pylint: disable=import-error,no-name-in-module
from distutils.core import Extension, setup
from Cython.Build import cythonize
+38 -22
View File
@@ -1,9 +1,11 @@
import io
import os
import sys
import copy
import json
import socket
import logging
import traceback
from threading import local
from collections import OrderedDict
from contextlib import contextmanager
@@ -78,28 +80,6 @@ class SwagLogger(logging.Logger):
self.log_local = local()
self.log_local.ctx = {}
def findCaller(self, stack_info=None):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
"""
# f = currentframe()
f = sys._getframe(3)
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
rv = "(unknown file)", 0, "(unknown function)"
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename in (logging._srcfile, _srcfile):
f = f.f_back
continue
rv = (co.co_filename, f.f_lineno, co.co_name)
break
return rv
def local_ctx(self):
try:
return self.log_local.ctx
@@ -140,6 +120,42 @@ class SwagLogger(logging.Logger):
else:
self.info(evt)
def findCaller(self, stack_info=False, stacklevel=1):
"""
Find the stack frame of the caller so that we can note the source
file name, line number and function name.
"""
f = sys._getframe(3)
#On some versions of IronPython, currentframe() returns None if
#IronPython isn't run with -X:Frames.
if f is not None:
f = f.f_back
orig_f = f
while f and stacklevel > 1:
f = f.f_back
stacklevel -= 1
if not f:
f = orig_f
rv = "(unknown file)", 0, "(unknown function)", None
while hasattr(f, "f_code"):
co = f.f_code
filename = os.path.normcase(co.co_filename)
if filename == _srcfile:
f = f.f_back
continue
sinfo = None
if stack_info:
sio = io.StringIO()
sio.write('Stack (most recent call last):\n')
traceback.print_stack(f, file=sio)
sinfo = sio.getvalue()
if sinfo[-1] == '\n':
sinfo = sinfo[:-1]
sio.close()
rv = (co.co_filename, f.f_lineno, co.co_name, sinfo)
break
return rv
if __name__ == "__main__":
log = SwagLogger()
+34 -8
View File
@@ -29,7 +29,7 @@ import fcntl
import tempfile
import threading
from enum import Enum
from common.basedir import PARAMS
def mkdirs_exists_ok(path):
try:
@@ -54,7 +54,9 @@ keys = {
"AthenadPid": [TxType.PERSISTENT],
"CalibrationParams": [TxType.PERSISTENT],
"CarParams": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarParamsCache": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CarVin": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"CommunityFeaturesToggle": [TxType.PERSISTENT],
"CompletedTrainingVersion": [TxType.PERSISTENT],
"ControlsParams": [TxType.PERSISTENT],
"DoUninstall": [TxType.CLEAR_ON_MANAGER_START],
@@ -65,22 +67,26 @@ keys = {
"GithubSshKeys": [TxType.PERSISTENT],
"HasAcceptedTerms": [TxType.PERSISTENT],
"HasCompletedSetup": [TxType.PERSISTENT],
"IsLdwEnabled": [TxType.PERSISTENT],
"IsGeofenceEnabled": [TxType.PERSISTENT],
"IsMetric": [TxType.PERSISTENT],
"IsOffroad": [TxType.CLEAR_ON_MANAGER_START],
"IsRHD": [TxType.PERSISTENT],
"IsUpdateAvailable": [TxType.PERSISTENT],
"IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START],
"IsUpdateAvailable": [TxType.CLEAR_ON_MANAGER_START],
"IsUploadRawEnabled": [TxType.PERSISTENT],
"IsUploadVideoOverCellularEnabled": [TxType.PERSISTENT],
"LastUpdateTime": [TxType.PERSISTENT],
"LimitSetSpeed": [TxType.PERSISTENT],
"LimitSetSpeedNeural": [TxType.PERSISTENT],
"LiveParameters": [TxType.PERSISTENT],
"LongitudinalControl": [TxType.PERSISTENT],
"OpenpilotEnabledToggle": [TxType.PERSISTENT],
"PandaFirmware": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"PandaFirmwareHex": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"PandaDongleId": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"Passive": [TxType.PERSISTENT],
"RecordFront": [TxType.PERSISTENT],
"ReleaseNotes": [TxType.PERSISTENT],
"SafetyModelLock": [TxType.PERSISTENT],
"ShouldDoUpdate": [TxType.CLEAR_ON_MANAGER_START],
"SpeedLimitOffset": [TxType.PERSISTENT],
"SubscriberInfo": [TxType.PERSISTENT],
@@ -89,9 +95,12 @@ keys = {
"UpdateAvailable": [TxType.CLEAR_ON_MANAGER_START],
"Version": [TxType.PERSISTENT],
"Offroad_ChargeDisabled": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"Offroad_TemperatureTooHigh": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_ConnectivityNeededPrompt": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_ConnectivityNeeded": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_ConnectivityNeededPrompt": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_TemperatureTooHigh": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_PandaFirmwareMismatch": [TxType.CLEAR_ON_MANAGER_START, TxType.CLEAR_ON_PANDA_DISCONNECT],
"Offroad_InvalidTime": [TxType.CLEAR_ON_MANAGER_START],
"Offroad_IsTakingSnapshot": [TxType.CLEAR_ON_MANAGER_START],
#dragonpilot config
"DragonEnableDashcam": [TxType.PERSISTENT],
"DragonEnableDriverSafetyCheck": [TxType.PERSISTENT],
@@ -104,6 +113,8 @@ keys = {
"DragonCachedModel": [TxType.PERSISTENT],
"DragonCachedFP": [TxType.PERSISTENT],
"DragonCachedVIN": [TxType.PERSISTENT],
"DragonCachedCarFW": [TxType.PERSISTENT],
"DragonCachedSource": [TxType.PERSISTENT],
"DragonAllowGas": [TxType.PERSISTENT],
"DragonToyotaStockDSU": [TxType.PERSISTENT],
"DragonLatCtrl": [TxType.PERSISTENT],
@@ -140,10 +151,20 @@ keys = {
"DragonUIBlinker": [TxType.PERSISTENT],
"DragonEnableDriverMonitoring": [TxType.PERSISTENT],
"DragonCarModel": [TxType.PERSISTENT],
"DragonCarVIN": [TxType.PERSISTENT],
"DragonCarVIN": [TxType.PERSISTENT], #deprecated
"DragonEnableSlowOnCurve": [TxType.PERSISTENT],
"DragonEnableLeadCarMovingAlert": [TxType.PERSISTENT],
"DragonToyotaSnGMod": [TxType.PERSISTENT],
"DragonEnableSRLearner": [TxType.PERSISTENT],
"DragonWazeMode": [TxType.PERSISTENT],
"DragonRunWaze": [TxType.PERSISTENT],
"DragonEnableAssistedLC": [TxType.PERSISTENT],
"DragonEnableAutoLC": [TxType.PERSISTENT],
"DragonAssistedLCMinMPH": [TxType.PERSISTENT],
"DragonAutoLCMinMPH": [TxType.PERSISTENT],
"DragonAutoLCDelay": [TxType.PERSISTENT],
"DragonBTG": [TxType.PERSISTENT],
"DragonBootHotspot": [TxType.PERSISTENT],
}
@@ -363,7 +384,7 @@ def write_db(params_path, key, value):
lock.release()
class Params():
def __init__(self, db='/data/params'):
def __init__(self, db=PARAMS):
self.db = db
# create the database if it doesn't exist...
@@ -371,6 +392,11 @@ class Params():
with self.transaction(write=True):
pass
def clear_all(self):
shutil.rmtree(self.db, ignore_errors=True)
with self.transaction(write=True):
pass
def transaction(self, write=False):
if write:
return DBWriter(self.db)
+1 -9
View File
@@ -6,20 +6,12 @@ import subprocess
import multiprocessing
from cffi import FFI
# Build and load cython module
import pyximport
installer = pyximport.install(inplace=True, build_dir='/tmp')
from common.clock import monotonic_time, sec_since_boot # pylint: disable=no-name-in-module, import-error
pyximport.uninstall(*installer)
assert monotonic_time
assert sec_since_boot
from common.common_pyx import sec_since_boot # pylint: disable=no-name-in-module, import-error
# time step for each process
DT_CTRL = 0.01 # controlsd
DT_PLAN = 0.05 # mpc
DT_MDL = 0.05 # model
DT_RDR = 0.05 # radar
DT_DMON = 0.1 # driver monitoring
DT_TRML = 0.5 # thermald and manager
+44 -9
View File
@@ -2,27 +2,62 @@ import os
import subprocess
from common.basedir import BASEDIR
class Spinner():
def __init__(self):
try:
self.spinner_proc = subprocess.Popen(["./spinner"],
stdin=subprocess.PIPE,
cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"),
close_fds=True)
except OSError:
self.spinner_proc = None
def __enter__(self):
self.spinner_proc = subprocess.Popen(["./spinner"],
stdin=subprocess.PIPE,
cwd=os.path.join(BASEDIR, "selfdrive", "ui", "spinner"),
close_fds=True)
return self
def update(self, spinner_text):
self.spinner_proc.stdin.write(spinner_text.encode('utf8') + b"\n")
self.spinner_proc.stdin.flush()
if self.spinner_proc is not None:
self.spinner_proc.stdin.write(spinner_text.encode('utf8') + b"\n")
try:
self.spinner_proc.stdin.flush()
except BrokenPipeError:
pass
def close(self):
if self.spinner_proc is not None:
try:
self.spinner_proc.stdin.close()
except BrokenPipeError:
pass
self.spinner_proc.terminate()
self.spinner_proc = None
def __del__(self):
self.close()
def __exit__(self, type, value, traceback):
self.spinner_proc.stdin.close()
self.spinner_proc.terminate()
self.close()
class FakeSpinner():
def __init__(self):
pass
def __enter__(self):
return self
def update(self, _):
pass
def __exit__(self, type, value, traceback):
pass
if __name__ == "__main__":
import time
with Spinner() as s:
s.update("Spinner text")
time.sleep(5.0)
print("gone")
time.sleep(5.0)
+10 -33
View File
@@ -44,6 +44,7 @@ def get_calib_from_vp(vp):
roll_calib = 0
return roll_calib, pitch_calib, yaw_calib
# aka 'extrinsic_matrix'
# road : x->forward, y -> left, z->up
def get_view_frame_from_road_frame(roll, pitch, yaw, height):
@@ -61,6 +62,13 @@ def vp_from_ke(m):
"""
return (m[0, 0]/m[2,0], m[1,0]/m[2,0])
def vp_from_rpy(rpy):
e = get_view_frame_from_road_frame(rpy[0], rpy[1], rpy[2], 1.22)
ke = np.dot(eon_intrinsics, e)
return vp_from_ke(ke)
def roll_from_ke(m):
# note: different from calibration.h/RollAnglefromKE: i think that one's just wrong
return np.arctan2(-(m[1, 0] - m[1, 1] * m[2, 0] / m[2, 1]),
@@ -123,37 +131,6 @@ def img_from_device(pt_device):
return pt_img.reshape(input_shape)[:,:2]
#TODO please use generic img transform below
def rotate_img(img, eulers, crop=None, intrinsics=eon_intrinsics):
import cv2 # pylint: disable=no-name-in-module, import-error
size = img.shape[:2]
rot = orient.rot_from_euler(eulers)
quadrangle = np.array([[0, 0],
[size[1]-1, 0],
[0, size[0]-1],
[size[1]-1, size[0]-1]], dtype=np.float32)
quadrangle_norm = np.hstack((normalize(quadrangle, intrinsics=intrinsics), np.ones((4,1))))
warped_quadrangle_full = np.einsum('ij, kj->ki', intrinsics.dot(rot), quadrangle_norm)
warped_quadrangle = np.column_stack((warped_quadrangle_full[:,0]/warped_quadrangle_full[:,2],
warped_quadrangle_full[:,1]/warped_quadrangle_full[:,2])).astype(np.float32)
if crop:
W_border = (size[1] - crop[0])//2
H_border = (size[0] - crop[1])//2
outside_crop = (((warped_quadrangle[:,0] < W_border) |
(warped_quadrangle[:,0] >= size[1] - W_border)) &
((warped_quadrangle[:,1] < H_border) |
(warped_quadrangle[:,1] >= size[0] - H_border)))
if not outside_crop.all():
raise ValueError("warped image not contained inside crop")
else:
H_border, W_border = 0, 0
M = cv2.getPerspectiveTransform(quadrangle, warped_quadrangle)
img_warped = cv2.warpPerspective(img, M, size[::-1])
return img_warped[H_border: size[0] - H_border,
W_border: size[1] - W_border]
def get_camera_frame_from_calib_frame(camera_frame_from_road_frame):
camera_frame_from_ground = camera_frame_from_road_frame[:, (0, 1, 3)]
calib_frame_from_ground = np.dot(eon_intrinsics,
@@ -183,7 +160,7 @@ def transform_img(base_img,
alpha=1.0,
beta=0,
blur=0):
import cv2 # pylint: disable=no-name-in-module, import-error
import cv2 # pylint: disable=import-error
cv2.setNumThreads(1)
if yuv:
@@ -241,7 +218,7 @@ def transform_img(base_img,
def yuv_crop(frame, output_size, center=None):
# output_size in camera coordinates so u,v
# center in array coordinates so row, column
import cv2 # pylint: disable=no-name-in-module, import-error
import cv2 # pylint: disable=import-error
rgb = cv2.cvtColor(frame, cv2.COLOR_YUV2RGB_I420)
if not center:
center = (rgb.shape[0]/2, rgb.shape[1]/2)
+1 -1
View File
@@ -31,7 +31,7 @@
# Android system locale, zh-TW = Traditional Chinese, zh-CN = Simplified Chinese
lang=en
lang=zh-CN
update_font=0
remove_old_font=0
+5 -5
View File
@@ -1,7 +1,7 @@
{
"ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-7a0117425bc4a6673958d265312994e124654a566228f3cec2f0f9bc8120a9ab.zip",
"ota_hash": "7a0117425bc4a6673958d265312994e124654a566228f3cec2f0f9bc8120a9ab",
"recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-3dc234d868c29a3739f6ca3bd47b1c2d3c570d9f478b6849a4fada129ee4af76.img",
"recovery_len": 15848748,
"recovery_hash": "3dc234d868c29a3739f6ca3bd47b1c2d3c570d9f478b6849a4fada129ee4af76"
"ota_url": "https://commadist.azureedge.net/neosupdate/ota-signed-efdf7de63b1aef63d68301e6175930991bf9a5927d16ec6fcc69287e2ee7ca4a.zip",
"ota_hash": "efdf7de63b1aef63d68301e6175930991bf9a5927d16ec6fcc69287e2ee7ca4a",
"recovery_url": "https://commadist.azureedge.net/neosupdate/recovery-97c27e6ed04ed6bb0608b845a2d4100912093f9380c3f2ba6b56bccd608e5f6e.img",
"recovery_len": 15861036,
"recovery_hash": "97c27e6ed04ed6bb0608b845a2d4100912093f9380c3f2ba6b56bccd608e5f6e"
}
+2 -4
View File
@@ -155,8 +155,6 @@ struct Updater {
TouchState touch;
int fb_w, fb_h;
EGLDisplay display;
EGLSurface surface;
FramebufferState *fb = NULL;
NVGcontext *vg = NULL;
@@ -198,7 +196,7 @@ struct Updater {
touch_init(&touch);
fb = framebuffer_init("updater", 0x00001000, false,
&display, &surface, &fb_w, &fb_h);
&fb_w, &fb_h);
assert(fb);
vg = nvgCreateGLES3(NVG_ANTIALIAS | NVG_STENCIL_STROKES | NVG_DEBUG);
@@ -708,7 +706,7 @@ struct Updater {
glDisable(GL_BLEND);
eglSwapBuffers(display, surface);
framebuffer_swap(fb);
assert(glGetError() == GL_NO_ERROR);
+46 -18
View File
@@ -6,26 +6,54 @@ export NUMEXPR_NUM_THREADS=1
export OPENBLAS_NUM_THREADS=1
export VECLIB_MAXIMUM_THREADS=1
if [ -z "$BASEDIR" ]; then
BASEDIR="/data/openpilot"
fi
if [ -z "$PASSIVE" ]; then
export PASSIVE="1"
fi
STAGING_ROOT="/data/safe_staging"
function launch {
# apply update
# if [ "$(git rev-parse HEAD)" != "$(git rev-parse @{u})" ]; then
# git reset --hard @{u} &&
# git clean -xdf &&
#
# # Touch all files on release2 after checkout to prevent rebuild
# BRANCH=$(git rev-parse --abbrev-ref HEAD)
# if [[ "$BRANCH" == "release2" ]]; then
# touch **
# fi
#
# exec "${BASH_SOURCE[0]}"
# fi
chmod 700 reset_update.sh
chmod 700 update_panda_firmware.sh
# Wifi scan
wpa_cli IFNAME=wlan0 SCAN
# Check to see if there's a valid overlay-based update available. Conditions
# are as follows:
#
# 1. The BASEDIR init file has to exist, with a newer modtime than anything in
# the BASEDIR Git repo. This checks for local development work or the user
# switching branches/forks, which should not be overwritten.
# 2. The FINALIZED consistent file has to exist, indicating there's an update
# that completed successfully and synced to disk.
if [ -f "${BASEDIR}/.overlay_init" ]; then
find ${BASEDIR}/.git -newer ${BASEDIR}/.overlay_init | grep -q '.' 2> /dev/null
if [ $? -eq 0 ]; then
echo "${BASEDIR} has been modified, skipping overlay update installation"
else
if [ -f "${STAGING_ROOT}/finalized/.overlay_consistent" ]; then
if [ ! -d /data/safe_staging/old_openpilot ]; then
echo "Valid overlay update found, installing"
LAUNCHER_LOCATION="${BASH_SOURCE[0]}"
mv $BASEDIR /data/safe_staging/old_openpilot
mv "${STAGING_ROOT}/finalized" $BASEDIR
# The mv changed our working directory to /data/safe_staging/old_openpilot
cd "${BASEDIR}"
echo "Restarting launch script ${LAUNCHER_LOCATION}"
exec "${LAUNCHER_LOCATION}"
else
echo "openpilot backup found, not updating"
# TODO: restore backup? This means the updater didn't start after swapping
fi
fi
fi
fi
# no cpu rationing for now
echo 0-3 > /dev/cpuset/background/cpus
@@ -37,23 +65,23 @@ function launch {
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
# Remove old NEOS update file
# TODO: move this code to the updater
if [ -d /data/neoupdate ]; then
rm -rf /data/neoupdate
fi
# Check for NEOS update
if [ $(< /VERSION) != "12" ]; then
if [ $(< /VERSION) != "14" ]; then
if [ -f "$DIR/scripts/continue.sh" ]; then
cp "$DIR/scripts/continue.sh" "/data/data/com.termux/files/continue.sh"
fi
git clean -xdf
"$DIR/installer/updater/updater" "file://$DIR/installer/updater/update.json"
fi
# handle pythonpath
ln -s /data/openpilot /data/pythonpath
ln -sfn $(pwd) /data/pythonpath
export PYTHONPATH="$PWD"
# start manager
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+11
View File
@@ -1,2 +1,13 @@
*.pyc
*.os
*.tmp
*.dylib
.*.swp
.DS_Store
can/*.so
can/build/
can/obj/
can/packer_pyx.cpp
can/parser_pyx.cpp
can/packer_impl.cpp
+25
View File
@@ -0,0 +1,25 @@
from ubuntu:16.04
RUN apt-get update && apt-get install -y libzmq3-dev clang wget git autoconf libtool curl make build-essential libssl-dev zlib1g-dev libbz2-dev libreadline-dev libsqlite3-dev llvm libncurses5-dev libncursesw5-dev xz-utils tk-dev libffi-dev liblzma-dev python-openssl
RUN curl -L https://github.com/pyenv/pyenv-installer/raw/master/bin/pyenv-installer | bash
ENV PATH="/root/.pyenv/bin:/root/.pyenv/shims:${PATH}"
RUN pyenv install 3.7.3
RUN pyenv global 3.7.3
RUN pyenv rehash
COPY requirements.txt /tmp/
RUN pip install -r /tmp/requirements.txt
ENV PYTHONPATH=/project
# TODO: Add tag to cereal
RUN git clone https://github.com/commaai/cereal.git /project/cereal
RUN /project/cereal/install_capnp.sh
WORKDIR /project
COPY SConstruct .
COPY . /project/opendbc
RUN scons -c && scons -j$(nproc)
+4 -1
View File
@@ -16,6 +16,9 @@ Wondering what's the DBC file format? [Here](http://www.socialledge.com/sjsu/ind
Use [panda](https://github.com/commaai/panda) to connect your car to a computer.
### How to use reverse engineered DBC
To create custom CAN simulations or send reverse engineered signals back to the car you can use [CANdevStudio](https://github.com/GENIVI/CANdevStudio) project.
### DBC file preprocessor
DBC files for different models of the same brand have a lot of overlap. Therefore, we wrote a preprocessor to create DBC files from a brand DBC file and a model specific DBC file. The source DBC files can be found in the generator folder. After changing one of the files run the generator.py script to regenerate the output files. These output files will be placed in the root of the opendbc repository and are suffixed by _generated.
@@ -42,7 +45,7 @@ For example:
SG_ VEHICLE_SPEED : 7|15@0+ (0.01,0) [0|250] "kph" PCM
```
- Signal's size: always use the smallest amount of bits possible. For example, let's say I'm reverse engineering the gas pedal position and I've determined that it's in a 3 bytes message. For 0% pedal position I read a message value of `0x00 0x00 0x00`, while for 100% of pedal position I read `0x64 0x00 0x00`: clearly, the gas pedal position is within the first byte of the message and I might be tempted to define the signal `GAS_POS` as:
- Signal size: always use the smallest amount of bits possible. For example, let's say I'm reverse engineering the gas pedal position and I've determined that it's in a 3 bytes message. For 0% pedal position I read a message value of `0x00 0x00 0x00`, while for 100% of pedal position I read `0x64 0x00 0x00`: clearly, the gas pedal position is within the first byte of the message and I might be tempted to define the signal `GAS_POS` as:
```
SG_ GAS_POS : 7|8@0+ (1,0) [0|100] "%" PCM
```
+57
View File
@@ -0,0 +1,57 @@
import os
import subprocess
zmq = 'zmq'
arch = subprocess.check_output(["uname", "-m"], encoding='utf8').rstrip()
cereal_dir = Dir('.')
cpppath = [
'#',
'#cereal',
"#cereal/messaging",
"#opendbc/can",
'/usr/lib/include',
]
AddOption('--test',
action='store_true',
help='build test files')
AddOption('--asan',
action='store_true',
help='turn on ASAN')
ccflags_asan = ["-fsanitize=address", "-fno-omit-frame-pointer"] if GetOption('asan') else []
ldflags_asan = ["-fsanitize=address"] if GetOption('asan') else []
env = Environment(
ENV=os.environ,
CC='clang',
CXX='clang++',
CCFLAGS=[
"-g",
"-fPIC",
"-O2",
"-Werror=implicit-function-declaration",
"-Werror=incompatible-pointer-types",
"-Werror=int-conversion",
"-Werror=return-type",
"-Werror=format-extra-args",
] + ccflags_asan,
LDFLAGS=ldflags_asan,
LINKFLAGS=ldflags_asan,
CFLAGS="-std=gnu11",
CXXFLAGS="-std=c++14",
CPPPATH=cpppath,
)
Export('env', 'zmq', 'arch')
cereal = [File('#cereal/libcereal.a')]
messaging = [File('#cereal/libmessaging.a')]
Export('cereal', 'messaging')
SConscript(['cereal/SConscript'])
SConscript(['opendbc/can/SConscript'])
+15 -5
View File
@@ -86,6 +86,13 @@ BO_ 420 VSA_STATUS: 8 VSA
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON
BO_ 427 STEER_MOTOR_TORQUE: 3 EPS
SG_ CONFIG_VALID : 7|1@0+ (1,0) [0|1] "" EON
SG_ MOTOR_TORQUE : 1|10@0+ (1,0) [0|256] "" EON
SG_ OUTPUT_DISABLED : 22|1@0+ (1,0) [0|1] "" EON
SG_ COUNTER : 21|2@0+ (1,0) [0|3] "" EON
SG_ CHECKSUM : 19|4@0+ (1,0) [0|15] "" EON
BO_ 432 STANDSTILL: 7 VSA
SG_ CONTROLLED_STANDSTILL : 0|1@0+ (1,0) [0|1] "" EON
SG_ WHEELS_MOVING : 12|1@0+ (1,0) [0|1] "" EON
@@ -164,7 +171,7 @@ BO_ 780 ACC_HUD: 8 ADAS
SG_ BOH : 38|1@0+ (1,0) [0|1] "" BDY
SG_ ACC_PROBLEM : 37|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_OFF : 36|1@0+ (1,0) [0|1] "" BDY
SG_ BOH_2 : 35|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_OFF_2 : 35|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] "" BDY
SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] "" BDY
SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] "" BDY
@@ -174,10 +181,12 @@ BO_ 780 ACC_HUD: 8 ADAS
SG_ BOH_4 : 42|1@0+ (1,0) [0|3] "" BDY
SG_ BOH_5 : 41|1@0+ (1,0) [0|3] "" BDY
SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] "" BDY
SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY
SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY
SG_ SET_ME_X01_2 : 55|1@0+ (1,0) [0|1] "" BDY
SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY
SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY
SG_ CHIME : 51|3@0+ (1,0) [0|1] "" BDY
SG_ SET_ME_X01 : 48|1@0+ (1,0) [0|1] "" BDY
SG_ ICONS : 63|2@0+ (1,0) [0|1] "" BDY
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY
SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" BDY
@@ -271,10 +280,11 @@ BO_ 342 STEERING_SENSORS: 6 EPS
SG_ CHECKSUM : 43|4@0+ (1,0) [0|3] "" EON
BO_ 399 STEER_STATUS: 7 EPS
SG_ STEER_TORQUE_SENSOR : 7|16@0- (1,0) [-31000|31000] "tbd" EON
SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON
SG_ STEER_TORQUE_SENSOR : 7|16@0- (-1,0) [-31000|31000] "tbd" EON
SG_ STEER_ANGLE_RATE : 23|16@0- (-0.1,0) [-31000|31000] "deg/s" EON
SG_ STEER_STATUS : 39|4@0+ (1,0) [0|15] "" EON
SG_ STEER_CONTROL_ACTIVE : 35|1@0+ (1,0) [0|1] "" EON
SG_ STEER_CONFIG_INDEX : 43|4@0+ (1,0) [0|15] "" EON
SG_ COUNTER : 53|2@0+ (1,0) [0|3] "" EON
SG_ CHECKSUM : 51|4@0+ (1,0) [0|3] "" EON
+14 -5
View File
@@ -86,6 +86,13 @@ BO_ 420 VSA_STATUS: 8 VSA
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" EON
SG_ CHECKSUM : 59|4@0+ (1,0) [0|15] "" EON
BO_ 427 STEER_MOTOR_TORQUE: 3 EPS
SG_ CONFIG_VALID : 7|1@0+ (1,0) [0|1] "" EON
SG_ MOTOR_TORQUE : 1|10@0+ (1,0) [0|256] "" EON
SG_ OUTPUT_DISABLED : 22|1@0+ (1,0) [0|1] "" EON
SG_ COUNTER : 21|2@0+ (1,0) [0|3] "" EON
SG_ CHECKSUM : 19|4@0+ (1,0) [0|15] "" EON
BO_ 432 STANDSTILL: 7 VSA
SG_ CONTROLLED_STANDSTILL : 0|1@0+ (1,0) [0|1] "" EON
SG_ WHEELS_MOVING : 12|1@0+ (1,0) [0|1] "" EON
@@ -164,7 +171,7 @@ BO_ 780 ACC_HUD: 8 ADAS
SG_ BOH : 38|1@0+ (1,0) [0|1] "" BDY
SG_ ACC_PROBLEM : 37|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_OFF : 36|1@0+ (1,0) [0|1] "" BDY
SG_ BOH_2 : 35|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_OFF_2 : 35|1@0+ (1,0) [0|1] "" BDY
SG_ FCM_PROBLEM : 34|1@0+ (1,0) [0|1] "" BDY
SG_ RADAR_OBSTRUCTED : 33|1@0+ (1,0) [0|1] "" BDY
SG_ ENABLE_MINI_CAR : 32|1@0+ (1,0) [0|1] "" BDY
@@ -174,10 +181,12 @@ BO_ 780 ACC_HUD: 8 ADAS
SG_ BOH_4 : 42|1@0+ (1,0) [0|3] "" BDY
SG_ BOH_5 : 41|1@0+ (1,0) [0|3] "" BDY
SG_ CRUISE_CONTROL_LABEL : 40|1@0+ (1,0) [0|3] "" BDY
SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY
SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY
SG_ SET_ME_X01_2 : 55|1@0+ (1,0) [0|1] "" BDY
SG_ IMPERIAL_UNIT : 54|1@0+ (1,0) [0|1] "" BDY
SG_ HUD_DISTANCE_3 : 52|1@0+ (1,0) [0|1] "" BDY
SG_ CHIME : 51|3@0+ (1,0) [0|1] "" BDY
SG_ SET_ME_X01 : 48|1@0+ (1,0) [0|1] "" BDY
SG_ ICONS : 63|2@0+ (1,0) [0|1] "" BDY
SG_ COUNTER : 61|2@0+ (1,0) [0|3] "" BDY
SG_ CHECKSUM : 59|4@0+ (1,0) [0|3] "" BDY
@@ -259,8 +268,8 @@ BO_ 392 GEARBOX: 6 XXX
SG_ GEAR : 36|5@0+ (1,0) [0|31] "" EON
BO_ 399 STEER_STATUS: 6 EPS
SG_ STEER_TORQUE_SENSOR : 7|12@0- (1,0) [-2047.5|2047.5] "tbd" EON
SG_ STEER_TORQUE_MOTOR : 23|16@0- (1,0) [-31000|31000] "tbd" EON
SG_ STEER_TORQUE_SENSOR : 7|12@0- (-1,0) [-2047.5|2047.5] "tbd" EON
SG_ STEER_ANGLE_RATE : 23|16@0- (-0.1,0) [-31000|31000] "deg/s" EON
SG_ STEER_STATUS : 35|4@0+ (1,0) [0|15] "" EON
SG_ STEER_CONTROL_ACTIVE : 36|1@0+ (1,0) [0|1] "" EON
SG_ COUNTER : 45|2@0+ (1,0) [0|3] "" EON
+19
View File
@@ -0,0 +1,19 @@
pr: none
pool:
vmImage: 'ubuntu-16.04'
steps:
- script: |
set -e
docker build -t opendbc .
displayName: 'Build'
- script: |
docker run opendbc bash -c "python -m unittest discover opendbc"
displayName: 'Unit tests'
- script: |
docker run opendbc bash -c "cd opendbc/can/tests/linter_python; PYTHONPATH=/ ./flake8_opendbc.sh"
docker run opendbc bash -c "cd opendbc/can/tests/linter_python; PYTHONPATH=/ ./pylint_opendbc.sh"
displayName: 'Python linter'
- script: |
docker run opendbc bash -c "cd opendbc/can/tests/; PYTHONPATH=/ ./test_generator.sh"
displayName: 'Generator test'
+27
View File
@@ -0,0 +1,27 @@
Import('env', 'cereal')
import os
from opendbc.can.process_dbc import process
dbcs = []
for x in sorted(os.listdir('../')):
if x.endswith(".dbc"):
def compile_dbc(target, source, env):
process(source[0].path, target[0].path)
in_fn = [os.path.join('../', x), 'dbc_template.cc']
out_fn = os.path.join('dbc_out', x.replace(".dbc", ".cc"))
dbc = env.Command(out_fn, in_fn, compile_dbc)
dbcs.append(dbc)
libdbc = env.SharedLibrary('libdbc', ["dbc.cc", "parser.cc", "packer.cc", "common.cc"]+dbcs, LIBS=["capnp", "kj"])
# packer
env.Command(['packer_pyx.so'],
[libdbc, 'packer_pyx.pyx', 'packer_pyx_setup.py'],
"cd opendbc/can && python3 packer_pyx_setup.py build_ext --inplace")
# parser
env.Command(['parser_pyx.so'],
[libdbc, cereal, 'parser_pyx_setup.py', 'parser_pyx.pyx', 'common.pxd'],
"cd opendbc/can && python3 parser_pyx_setup.py build_ext --inplace")
+2
View File
@@ -0,0 +1,2 @@
from opendbc.can.parser_pyx import CANDefine # pylint: disable=no-name-in-module, import-error
assert CANDefine
+165
View File
@@ -0,0 +1,165 @@
#include "common.h"
unsigned int honda_checksum(unsigned int address, uint64_t d, int l) {
d >>= ((8-l)*8); // remove padding
d >>= 4; // remove checksum
int s = 0;
while (address) { s += (address & 0xF); address >>= 4; }
while (d) { s += (d & 0xF); d >>= 4; }
s = 8-s;
s &= 0xF;
return s;
}
unsigned int toyota_checksum(unsigned int address, uint64_t d, int l) {
d >>= ((8-l)*8); // remove padding
d >>= 8; // remove checksum
unsigned int s = l;
while (address) { s += address & 0xff; address >>= 8; }
while (d) { s += d & 0xff; d >>= 8; }
return s & 0xFF;
}
// Static lookup table for fast computation of CRC8 poly 0x2F, aka 8H2F/AUTOSAR
uint8_t crc8_lut_8h2f[256];
void gen_crc_lookup_table(uint8_t poly, uint8_t crc_lut[]) {
uint8_t crc;
int i, j;
for (i = 0; i < 256; i++) {
crc = i;
for (j = 0; j < 8; j++) {
if ((crc & 0x80) != 0)
crc = (uint8_t)((crc << 1) ^ poly);
else
crc <<= 1;
}
crc_lut[i] = crc;
}
}
void init_crc_lookup_tables() {
// At init time, set up static lookup tables for fast CRC computation.
gen_crc_lookup_table(0x2F, crc8_lut_8h2f); // CRC-8 8H2F/AUTOSAR for Volkswagen
}
unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l) {
// Volkswagen uses standard CRC8 8H2F/AUTOSAR, but they compute it with
// a magic variable padding byte tacked onto the end of the payload.
// https://www.autosar.org/fileadmin/user_upload/standards/classic/4-3/AUTOSAR_SWS_CRCLibrary.pdf
uint8_t *dat = (uint8_t *)&d;
uint8_t crc = 0xFF; // Standard init value for CRC8 8H2F/AUTOSAR
// CRC the payload first, skipping over the first byte where the CRC lives.
for (int i = 1; i < l; i++) {
crc ^= dat[i];
crc = crc8_lut_8h2f[crc];
}
// Look up and apply the magic final CRC padding byte, which permutes by CAN
// address, and additionally (for SOME addresses) by the message counter.
uint8_t counter = dat[1] & 0x0F;
switch(address) {
case 0x86: // LWI_01 Steering Angle
crc ^= (uint8_t[]){0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86}[counter];
break;
case 0x9F: // EPS_01 Electric Power Steering
crc ^= (uint8_t[]){0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5,0xF5}[counter];
break;
case 0xAD: // Getriebe_11 Automatic Gearbox
crc ^= (uint8_t[]){0x3F,0x69,0x39,0xDC,0x94,0xF9,0x14,0x64,0xD8,0x6A,0x34,0xCE,0xA2,0x55,0xB5,0x2C}[counter];
break;
case 0xFD: // ESP_21 Electronic Stability Program
crc ^= (uint8_t[]){0xB4,0xEF,0xF8,0x49,0x1E,0xE5,0xC2,0xC0,0x97,0x19,0x3C,0xC9,0xF1,0x98,0xD6,0x61}[counter];
break;
case 0x106: // ESP_05 Electronic Stability Program
crc ^= (uint8_t[]){0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07,0x07}[counter];
break;
case 0x117: // ACC_10 Automatic Cruise Control
crc ^= (uint8_t[]){0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC,0xAC}[counter];
break;
case 0x122: // ACC_06 Automatic Cruise Control
crc ^= (uint8_t[]){0x37,0x7D,0xF3,0xA9,0x18,0x46,0x6D,0x4D,0x3D,0x71,0x92,0x9C,0xE5,0x32,0x10,0xB9}[counter];
break;
case 0x126: // HCA_01 Heading Control Assist
crc ^= (uint8_t[]){0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA,0xDA}[counter];
break;
case 0x12B: // GRA_ACC_01 Steering wheel controls for ACC
crc ^= (uint8_t[]){0x6A,0x38,0xB4,0x27,0x22,0xEF,0xE1,0xBB,0xF8,0x80,0x84,0x49,0xC7,0x9E,0x1E,0x2B}[counter];
break;
case 0x187: // EV_Gearshift "Gear" selection data for EVs with no gearbox
crc ^= (uint8_t[]){0x7F,0xED,0x17,0xC2,0x7C,0xEB,0x44,0x21,0x01,0xFA,0xDB,0x15,0x4A,0x6B,0x23,0x05}[counter];
break;
case 0x30C: // ACC_02 Automatic Cruise Control
crc ^= (uint8_t[]){0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F,0x0F}[counter];
break;
case 0x3C0: // Klemmen_Status_01 ignition and starting status
crc ^= (uint8_t[]){0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3,0xC3}[counter];
break;
case 0x65D: // ESP_20 Electronic Stability Program
crc ^= (uint8_t[]){0xAC,0xB3,0xAB,0xEB,0x7A,0xE1,0x3B,0xF7,0x73,0xBA,0x7C,0x9E,0x06,0x5F,0x02,0xD9}[counter];
break;
default: // As-yet undefined CAN message, CRC check expected to fail
printf("Attempt to CRC check undefined Volkswagen message 0x%02X\n", address);
crc ^= (uint8_t[]){0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}[counter];
break;
}
crc = crc8_lut_8h2f[crc];
return crc ^ 0xFF; // Return after standard final XOR for CRC8 8H2F/AUTOSAR
}
unsigned int pedal_checksum(uint64_t d, int l) {
uint8_t crc = 0xFF;
uint8_t poly = 0xD5; // standard crc8
d >>= ((8-l)*8); // remove padding
d >>= 8; // remove checksum
uint8_t *dat = (uint8_t *)&d;
int i, j;
for (i = 0; i < l - 1; i++) {
crc ^= dat[i];
for (j = 0; j < 8; j++) {
if ((crc & 0x80) != 0) {
crc = (uint8_t)((crc << 1) ^ poly);
}
else {
crc <<= 1;
}
}
}
return crc;
}
uint64_t read_u64_be(const uint8_t* v) {
return (((uint64_t)v[0] << 56)
| ((uint64_t)v[1] << 48)
| ((uint64_t)v[2] << 40)
| ((uint64_t)v[3] << 32)
| ((uint64_t)v[4] << 24)
| ((uint64_t)v[5] << 16)
| ((uint64_t)v[6] << 8)
| (uint64_t)v[7]);
}
uint64_t read_u64_le(const uint8_t* v) {
return ((uint64_t)v[0]
| ((uint64_t)v[1] << 8)
| ((uint64_t)v[2] << 16)
| ((uint64_t)v[3] << 24)
| ((uint64_t)v[4] << 32)
| ((uint64_t)v[5] << 40)
| ((uint64_t)v[6] << 48)
| ((uint64_t)v[7] << 56));
}
+70
View File
@@ -0,0 +1,70 @@
#pragma once
#include <vector>
#include <map>
#include <unordered_map>
#include "common_dbc.h"
#include <capnp/serialize.h>
#include "cereal/gen/cpp/log.capnp.h"
#define MAX_BAD_COUNTER 5
// Helper functions
unsigned int honda_checksum(unsigned int address, uint64_t d, int l);
unsigned int toyota_checksum(unsigned int address, uint64_t d, int l);
void init_crc_lookup_tables();
unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l);
unsigned int pedal_checksum(uint64_t d, int l);
uint64_t read_u64_be(const uint8_t* v);
uint64_t read_u64_le(const uint8_t* v);
class MessageState {
public:
uint32_t address;
unsigned int size;
std::vector<Signal> parse_sigs;
std::vector<double> vals;
uint16_t ts;
uint64_t seen;
uint64_t check_threshold;
uint8_t counter;
uint8_t counter_fail;
bool parse(uint64_t sec, uint16_t ts_, uint8_t * dat);
bool update_counter_generic(int64_t v, int cnt_size);
};
class CANParser {
private:
const int bus;
const DBC *dbc = NULL;
std::unordered_map<uint32_t, MessageState> message_states;
public:
bool can_valid = false;
uint64_t last_sec = 0;
CANParser(int abus, const std::string& dbc_name,
const std::vector<MessageParseOptions> &options,
const std::vector<SignalParseOptions> &sigoptions);
void UpdateCans(uint64_t sec, const capnp::List<cereal::CanData>::Reader& cans);
void UpdateValid(uint64_t sec);
void update_string(std::string data, bool sendcan);
std::vector<SignalValue> query_latest();
};
class CANPacker {
private:
const DBC *dbc = NULL;
std::map<std::pair<uint32_t, std::string>, Signal> signal_lookup;
std::map<uint32_t, Msg> message_lookup;
public:
CANPacker(const std::string& dbc_name);
uint64_t pack(uint32_t address, const std::vector<SignalPackValue> &signals, int counter);
};
+82
View File
@@ -0,0 +1,82 @@
# distutils: language = c++
#cython: language_level=3
from libc.stdint cimport uint32_t, uint64_t, uint16_t
from libcpp.vector cimport vector
from libcpp.map cimport map
from libcpp.string cimport string
from libcpp.unordered_set cimport unordered_set
from libcpp cimport bool
cdef extern from "common_dbc.h":
ctypedef enum SignalType:
DEFAULT,
HONDA_CHECKSUM,
HONDA_COUNTER,
TOYOTA_CHECKSUM,
PEDAL_CHECKSUM,
PEDAL_COUNTER,
VOLKSWAGEN_CHECKSUM,
VOLKSWAGEN_COUNTER
cdef struct Signal:
const char* name
int b1, b2, bo
bool is_signed
double factor, offset
SignalType type
cdef struct Msg:
const char* name
uint32_t address
unsigned int size
size_t num_sigs
const Signal *sigs
cdef struct Val:
const char* name
uint32_t address
const char* def_val
const Signal *sigs
cdef struct DBC:
const char* name
size_t num_msgs
const Msg *msgs
const Val *vals
size_t num_vals
cdef struct SignalParseOptions:
uint32_t address
const char* name
double default_value
cdef struct MessageParseOptions:
uint32_t address
int check_frequency
cdef struct SignalValue:
uint32_t address
uint16_t ts
const char* name
double value
cdef struct SignalPackValue:
const char * name
double value
cdef extern from "common.h":
cdef const DBC* dbc_lookup(const string);
cdef cppclass CANParser:
bool can_valid
CANParser(int, string, vector[MessageParseOptions], vector[SignalParseOptions])
void update_string(string, bool)
vector[SignalValue] query_latest()
cdef cppclass CANPacker:
CANPacker(string)
uint64_t pack(uint32_t, vector[SignalPackValue], int counter)
@@ -1,5 +1,4 @@
#ifndef SELFDRIVE_CAN_COMMON_H
#define SELFDRIVE_CAN_COMMON_H
#pragma once
#include <cstddef>
#include <cstdint>
@@ -7,19 +6,11 @@
#define ARRAYSIZE(x) (sizeof(x)/sizeof(x[0]))
unsigned int honda_checksum(unsigned int address, uint64_t d, int l);
unsigned int toyota_checksum(unsigned int address, uint64_t d, int l);
unsigned int pedal_checksum(unsigned int address, uint64_t d, int l);
void init_crc_lookup_tables();
unsigned int volkswagen_crc(unsigned int address, uint64_t d, int l);
struct SignalPackValue {
const char* name;
double value;
};
struct SignalParseOptions {
uint32_t address;
const char* name;
@@ -38,7 +29,6 @@ struct SignalValue {
double value;
};
enum SignalType {
DEFAULT,
HONDA_CHECKSUM,
@@ -90,5 +80,3 @@ void dbc_register(const DBC* dbc);
static void __attribute__((constructor)) do_dbc_init_ ## dbc(void) { \
dbc_register(&dbc); \
}
#endif
+1 -2
View File
@@ -1,7 +1,6 @@
#include <string>
#include <vector>
#include "common.h"
#include "common_dbc.h"
namespace {
+1 -2
View File
@@ -257,7 +257,6 @@ class dbc():
if __name__ == "__main__":
from opendbc import DBC_PATH
import numpy as np
dbc_test = dbc(os.path.join(DBC_PATH, 'toyota_prius_2017_pt_generated.dbc'))
msg = ('STEER_ANGLE_SENSOR', {'STEER_ANGLE': -6.0, 'STEER_RATE': 4, 'STEER_FRACTION': -0.2})
@@ -267,7 +266,7 @@ if __name__ == "__main__":
dbc_test = dbc(os.path.join(DBC_PATH, 'hyundai_santa_fe_2019_ccan.dbc'))
decoded = dbc_test.decode((0x2b0, 0, "\xfa\xfe\x00\x07\x12"))
assert np.isclose(decoded[1]['SAS_Angle'], -26.2)
assert abs(decoded[1]['SAS_Angle'] - (-26.2)) < 0.001
msg = ('SAS11', {'SAS_Stat': 7.0, 'MsgCount': 0.0, 'SAS_Angle': -26.200000000000003, 'SAS_Speed': 0.0, 'CheckSum': 0.0})
encoded = dbc_test.encode(*msg)

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