mirror of
https://github.com/dragonpilot/dragonpilot.git
synced 2026-06-20 05:22:03 +08:00
Compare commits
972 Commits
0.8.12
...
v0.7.3-zht
| Author | SHA1 | Date | |
|---|---|---|---|
| 8eb90c980e | |||
| f5f4685cd1 | |||
| e5c8966eee | |||
| 9284e3fe0a | |||
| 6a627cee16 | |||
| 9181036983 | |||
| 862e6a5ce6 | |||
| d8f72be9f2 | |||
| 2e95809645 | |||
| 4c6705d667 | |||
| c41e6592af | |||
| c7cdaf8e76 | |||
| 2aaa5319e8 | |||
| be1165df5a | |||
| ae193f20ca | |||
| 6961fc82ac | |||
| ad46fd4ea7 | |||
| f61abf1609 | |||
| fe5a3de1b9 | |||
| aafa2c07dd | |||
| 89b7f6e7b4 | |||
| 481cd579d2 | |||
| 785791333f | |||
| 0d398a01b5 | |||
| 8410828fca | |||
| 350f5400fa | |||
| f9aeb650ac | |||
| 4a3df5afbb | |||
| 1a96011b0b | |||
| 64009c5c17 | |||
| 0addeb9bf8 | |||
| fd427f629f | |||
| 31fa240594 | |||
| 1e8d701d82 | |||
| 594198b4c9 | |||
| 659356220a | |||
| 0b537d6b5d | |||
| bb11d3596c | |||
| 970192698f | |||
| 42725594aa | |||
| 17fdc09b9b | |||
| da73baeb69 | |||
| 9d8d1adb48 | |||
| 895f9b74bd | |||
| b3923c04a3 | |||
| 224c2b57ba | |||
| 9ff054527c | |||
| 74dbd89e3e | |||
| 13fb670ba0 | |||
| 7ef8d4cc6d | |||
| 5738bb5896 | |||
| 2cb7b644e3 | |||
| e75b619ae2 | |||
| 9a8e595bcb | |||
| 1a48e6e625 | |||
| a382a28fda | |||
| 9ca8f9a047 | |||
| 89dfdd961f | |||
| 9a7dbd0201 | |||
| d04f4ffa31 | |||
| 3e2a9e8136 | |||
| 725947813f | |||
| e594bd740e | |||
| 5cd69cb553 | |||
| e1380aa34a | |||
| fb1a9ca010 | |||
| 1f1ecd595d | |||
| 14e89f4b5c | |||
| 4c37e7a399 | |||
| 2eeb228895 | |||
| dfa6cbee83 | |||
| 97f1811159 | |||
| 87a694ebcb | |||
| 43c07122e2 | |||
| 684b70d40b | |||
| ecb3136cb7 | |||
| 72c815acef | |||
| f5a2358cf5 | |||
| 06bfe01802 | |||
| b160847119 | |||
| 50ecefc689 | |||
| 322cbf930d | |||
| 236e261f64 | |||
| d6f6aa0049 | |||
| f188c6188f | |||
| adc4f36962 | |||
| 129a450fc3 | |||
| 794d0c06e7 | |||
| 02136e7ef3 | |||
| 599510e7dc | |||
| 9d945bded8 | |||
| 2ebed15fcf | |||
| b993595e81 | |||
| 6fec46efb0 | |||
| 59e91b8774 | |||
| fcc8ab650f | |||
| f47eb76c43 | |||
| 87b36e8dd8 | |||
| b11f2770d6 | |||
| 5dd8ddd14f | |||
| 227a616db9 | |||
| ba77eccaf1 | |||
| b539f65a78 | |||
| 8ed17d2934 | |||
| 65ad81d805 | |||
| 97ee7bc139 | |||
| 6216c00a88 | |||
| f4aa4ab456 | |||
| b4e991d714 | |||
| 2260169379 | |||
| 27c2d13cb2 | |||
| 5a1b15cfad | |||
| 7001278d0e | |||
| 028b852eea | |||
| a6a54b7196 | |||
| f93e76e360 | |||
| 178db47eb9 | |||
| fb9373f5c9 | |||
| 8a0c5fbb77 | |||
| feff825283 | |||
| 78d7dedbde | |||
| 6ff353469c | |||
| 4959f95dbd | |||
| bd1ce8d003 | |||
| 2bf3489e96 | |||
| 542fef8a5a | |||
| 5af951b240 | |||
| 1b7e77c344 | |||
| f74a810456 | |||
| 5ff77e4500 | |||
| 17cdb7e476 | |||
| b98bbcd72f | |||
| 30446d0c74 | |||
| 4da1d8bf9d | |||
| 800a4a137c | |||
| d170a9a78a | |||
| c9bb9a9929 | |||
| 3e8f177745 | |||
| fc88fa63c2 | |||
| d8e166f7d9 | |||
| 78b7dc0606 | |||
| 53f369d68c | |||
| 9bfb70bf0c | |||
| e70b8e80ba | |||
| 10aa84a2a4 | |||
| 65adf79be6 | |||
| c79b166009 | |||
| 574518f163 | |||
| 8d2c063345 | |||
| ea93808331 | |||
| 34ddbd59ba | |||
| b06266f922 | |||
| 16bcfbd359 | |||
| 33d7a6d045 | |||
| 266fa89ade | |||
| f52ea2b035 | |||
| 8ff951e64c | |||
| f04279a147 | |||
| 4b28d659bb | |||
| 5db0c82411 | |||
| 115e5c346d | |||
| eac595fc85 | |||
| 5bf6471944 | |||
| f76785b521 | |||
| 00e065dc49 | |||
| ed03d69604 | |||
| 4ce1507068 | |||
| a334a1353d | |||
| 68670e0c48 | |||
| c4ccb435c6 | |||
| f4e9e339f2 | |||
| cb72090236 | |||
| c7e52af67d | |||
| 26d6163bb0 | |||
| c293bc4a36 | |||
| 0edc838459 | |||
| c375fcc8c6 | |||
| 57bb12e61e | |||
| b2e5aac1f3 | |||
| af25dcccfd | |||
| cb3af07e47 | |||
| 9add4a7217 | |||
| 2742fab6aa | |||
| e14c6757d8 | |||
| 0be06a3fec | |||
| 667f4abccb | |||
| b0fcfe4069 | |||
| 4576e32f43 | |||
| 599458f768 | |||
| 2069ee8ee6 | |||
| f9b8ee8cfa | |||
| 9062391a9c | |||
| 6f7bf752cd | |||
| 2cc099bcec | |||
| 450e6001a7 | |||
| 113a6fbfdf | |||
| 92c4111bdd | |||
| 79733afb64 | |||
| 2c11113671 | |||
| c4fe51dc57 | |||
| 5e341385cb | |||
| 53b466b496 | |||
| 4adf4d138e | |||
| 995af1de45 | |||
| 399cdf4e4a | |||
| 22c1f205e1 | |||
| 8a816ea8e1 | |||
| f14a1b4793 | |||
| cb7fd242f7 | |||
| b2c0070a7b | |||
| 4861cc2987 | |||
| a2d6b0241f | |||
| 39d4ad99a7 | |||
| 9c6d6cec92 | |||
| 70e315f14a | |||
| 0bfac4b8b3 | |||
| dc8d7e3939 | |||
| fec227373b | |||
| 53f3688e4a | |||
| 9ec47b48bd | |||
| d44e8b5d3b | |||
| 48edf7f7d7 | |||
| cf0e7d4a92 | |||
| aed49074dc | |||
| 70df20f749 | |||
| 8698cc0c66 | |||
| 9e1db5ee4a | |||
| b7e0f4cca4 | |||
| c9a3e8f8bc | |||
| bd4f39dae9 | |||
| 45399cc201 | |||
| c065bc1a01 | |||
| df40837f48 | |||
| fd930c7333 | |||
| 8db3fa8caf | |||
| aba77b1163 | |||
| 4097231dcb | |||
| 23661b80ad | |||
| a70d9abccc | |||
| 56742acbd4 | |||
| 72ba044226 | |||
| 63cee44949 | |||
| 8a2e191168 | |||
| b1e698ee82 | |||
| c6f324d407 | |||
| 23250ba37f | |||
| aa89df14b8 | |||
| 969c3c1e05 | |||
| d804adb00d | |||
| ba6a71b32c | |||
| 1447a3b458 | |||
| c29f876f36 | |||
| 0dc120f4d8 | |||
| e8aee5615a | |||
| d060fc0ef4 | |||
| 8db70980fa | |||
| 91bbd7c28f | |||
| df432c5e2e | |||
| 02d6549fa7 | |||
| 0302835853 | |||
| 5581835f79 | |||
| 0ff5da9fc1 | |||
| 7030de2a82 | |||
| d9200c3549 | |||
| 4065e9360c | |||
| 44d726bc8b | |||
| 0d02fbe2ec | |||
| 2c4fb49eb6 | |||
| 33386b6365 | |||
| f7a90f17d3 | |||
| 8fd9ff49f4 | |||
| bebff76873 | |||
| d5c85bf88a | |||
| 5a2bc4f616 | |||
| 50d8771c29 | |||
| fa476b0cad | |||
| fd839b7614 | |||
| 33393412f8 | |||
| 2a1e4c8ca1 | |||
| bfd61871d4 | |||
| 45bb3350e1 | |||
| 8ab6b4313b | |||
| cc2890a7f3 | |||
| e97324ef79 | |||
| 853c1c24fb | |||
| 30f17dd1a5 | |||
| fd200f42e3 | |||
| 7b4602907e | |||
| 6291d6c31a | |||
| 1ab7150b57 | |||
| be9e6fa698 | |||
| 4b5a9a13fb | |||
| d21b783199 | |||
| d8056f4e83 | |||
| e450d8a4fb | |||
| b02c6aff8d | |||
| 07c8465c2b | |||
| 52e9e4ee62 | |||
| 8b3aa6f561 | |||
| 973bdc4318 | |||
| 1d38e040c9 | |||
| aa58f52db3 | |||
| ff26ef1c12 | |||
| 62fbb6302a | |||
| 3d60864d47 | |||
| be1376ecd2 | |||
| 594044fd91 | |||
| 38a9cf9489 | |||
| 5a6d6609f4 | |||
| 676cc12afa | |||
| a7602eae5e | |||
| adf8e823b9 | |||
| bd47359811 | |||
| 5a205d0195 | |||
| 9636661da4 | |||
| 5e1e75ef80 | |||
| 071457dc9e | |||
| 524920fafe | |||
| 530a56e398 | |||
| dc77d4a88e | |||
| e72cb1abe1 | |||
| 32d820bb6d | |||
| f1e26b346f | |||
| 6c1fa5dc3a | |||
| 7b8bd9e3ff | |||
| 00ec08868a | |||
| 4323f755fd | |||
| b8557616dd | |||
| 02eafeafeb | |||
| 3a006aa99e | |||
| e8084fd9dd | |||
| e5281a98fa | |||
| 722aea251a | |||
| 99fdd691a3 | |||
| b5e026e44b | |||
| c6c10d67ae | |||
| 037727cd62 | |||
| d22759f0c8 | |||
| 22b5eb0e06 | |||
| 236a05f2ad | |||
| 8ef944eceb | |||
| 01e62f49dc | |||
| 632ee00a94 | |||
| 5c4701d035 | |||
| 38ce7dae51 | |||
| 7d8ba56cda | |||
| 9c7e8aa391 | |||
| ca1903a3c0 | |||
| d20b63c909 | |||
| ef4b2d32d2 | |||
| d86555d52f | |||
| f875296a4a | |||
| fbb5860e9f | |||
| 2074e530e0 | |||
| 7a04ebe2da | |||
| d1923f7dc6 | |||
| f8677eb260 | |||
| 03589f71e5 | |||
| b47ca2543e | |||
| d4ae6d93d6 | |||
| 5a8bff7f56 | |||
| 701bdf0b4a | |||
| 43814ab9aa | |||
| c1c40321b6 | |||
| f165fed722 | |||
| 145319bcd3 | |||
| c7b9d28232 | |||
| 0568abd542 | |||
| 2e73e55e97 | |||
| ce67df2e3c | |||
| 2e0dc8cdc0 | |||
| de8cabf0f0 | |||
| a18b37863c | |||
| 18a4819add | |||
| 26b063f60f | |||
| 0ebdd0731f | |||
| 6573a67742 | |||
| 32adcf1591 | |||
| 7b7be6975a | |||
| 51570f7ff8 | |||
| 377038642c | |||
| 986e4c6f79 | |||
| bfa05df92f | |||
| dc76fb165e | |||
| 7219bd535a | |||
| 4168703dc5 | |||
| 951b5c695a | |||
| 01542c4a19 | |||
| e487aaba64 | |||
| b88362d508 | |||
| 2463873b14 | |||
| 39d527fa5b | |||
| 7bfdd09dc1 | |||
| 3c1f1fb9a1 | |||
| bdf0964615 | |||
| 8a392c7c2e | |||
| da8706ec07 | |||
| c60744f903 | |||
| 066d88e754 | |||
| 35bf4794b1 | |||
| 70b7f21c8d | |||
| 472f9ed7b8 | |||
| 36924194ad | |||
| 99149ebfb1 | |||
| 2fc7817831 | |||
| cb25bbd96a | |||
| 67d3494b30 | |||
| 881178d542 | |||
| 0042b3d64e | |||
| cd87c50753 | |||
| 51c1801f22 | |||
| 35666b24f3 | |||
| 259e6ecf49 | |||
| ebf7f3bd8a | |||
| eb3cd1efc5 | |||
| f4a979d316 | |||
| 284fe1f2b1 | |||
| f65c9b478a | |||
| c5a7eeea99 | |||
| 86d781f893 | |||
| baf9ab37c2 | |||
| 82160eb2e4 | |||
| f4546ba8d4 | |||
| 2509a1e753 | |||
| 71886e2be6 | |||
| 10d3b8aa90 | |||
| 0441cf139c | |||
| 4eb316c291 | |||
| a75abd788b | |||
| 436640c108 | |||
| 11d6583b62 | |||
| a71307229f | |||
| b318162e6a | |||
| 3826cf23d2 | |||
| 8a6dfb05ab | |||
| d3becbacdd | |||
| 7700b6aa59 | |||
| 634ee8746a | |||
| 8a2b649f22 | |||
| a5c9f571ce | |||
| cd00c32dbc | |||
| f5113edc50 | |||
| a65f57fac5 | |||
| 995cd1aa65 | |||
| dd9e649296 | |||
| 5e7cb5de3c | |||
| afb5d372fd | |||
| ee28ef1ae4 | |||
| e7b2a98fe3 | |||
| 6813559bbe | |||
| 33926ee432 | |||
| 04fd1f4e6c | |||
| ebfd786af0 | |||
| 9c7ae433ec | |||
| 10cd4c0bd2 | |||
| 7e8618dc9d | |||
| c68503d8a1 | |||
| 14b0c9427d | |||
| 44fc1767fd | |||
| 296daec59a | |||
| 97ed349d04 | |||
| 9a1ceeb0e8 | |||
| 9affab1f27 | |||
| 8934720785 | |||
| af1d476c50 | |||
| b14f39b2c8 | |||
| 4b806911ad | |||
| 69780971aa | |||
| 2f49572d72 | |||
| 0105342caf | |||
| 8c442ec989 | |||
| c29f96069e | |||
| 781c392a22 | |||
| 23f142bcf0 | |||
| 4f0061d71c | |||
| fd86f04e82 | |||
| 95aca22809 | |||
| f5a9a08863 | |||
| df85e66a6d | |||
| 49eec4cab3 | |||
| f2648fd12f | |||
| d50811859a | |||
| c1f03ce883 | |||
| 7ce952e165 | |||
| d1e95be073 | |||
| 04a7dd2633 | |||
| 6168ce1ef9 | |||
| 466dce4090 | |||
| 836a836f0d | |||
| 227578ef15 | |||
| 50d5e988e8 | |||
| 29d10aed97 | |||
| f5a7e06770 | |||
| c2d2780772 | |||
| f6322f0262 | |||
| 6045192107 | |||
| b617372907 | |||
| 67a595e321 | |||
| 91be9e9fa9 | |||
| e1509808ac | |||
| 49c488a79e | |||
| c21334cb95 | |||
| 2dc8bd5655 | |||
| 34b85671d1 | |||
| be5366787b | |||
| 4ac4dd57e9 | |||
| 3b66e6a9c4 | |||
| cfe34284a4 | |||
| d45a88d5cd | |||
| eebf70fd59 | |||
| 80e24f2051 | |||
| be2bf61420 | |||
| d7a5fb0c65 | |||
| 80a8817048 | |||
| 4151d1526e | |||
| 55dad14711 | |||
| 6f47f3c4d6 | |||
| 0de789a7cb | |||
| 38ab273163 | |||
| 0f571e8a4e | |||
| 234ddbebaf | |||
| 6f6c96735a | |||
| 9567d75d1c | |||
| 691bb95a77 | |||
| bb182edec0 | |||
| ac45050c4a | |||
| 6d76ef3ef0 | |||
| 4365be9056 | |||
| fd731f1f27 | |||
| b5c5e04d4b | |||
| f61add3913 | |||
| 8af6ddcd8b | |||
| 9050903cee | |||
| a5e2f3cc22 | |||
| 85bc608675 | |||
| fa8e44d0b2 | |||
| 651f994d6a | |||
| 2ccdc68ca9 | |||
| 9c8a03ecfb | |||
| 66cac800cb | |||
| 24ca97d828 | |||
| 751aa5cf7e | |||
| e05df8f0fc | |||
| 5c059504ed | |||
| c187ea5986 | |||
| ec691a586a | |||
| 9833c901e6 | |||
| f738ce6ec9 | |||
| 194081b0f1 | |||
| dea170368e | |||
| 5af0f2748c | |||
| 88558aa7a5 | |||
| 29d25df7a6 | |||
| bb535e797e | |||
| ca0fd6fe8a | |||
| b01aa70635 | |||
| 7d86e2adef | |||
| 05fa8a5eda | |||
| 151e45c9cd | |||
| db4ef15bed | |||
| 33ff1c9783 | |||
| 6365dbb34d | |||
| 854e662c57 | |||
| c7c29cac6f | |||
| bd5db31b6a | |||
| 20e8d61f0c | |||
| f6d402c1e7 | |||
| 77460d8e7f | |||
| 96041f0dbe | |||
| c1cf70fd3a | |||
| b2ef7ff80c | |||
| 01319c0251 | |||
| 9fc0107636 | |||
| 0e249e2bed | |||
| e3a19a2458 | |||
| d2a0782e1b | |||
| aa14e182af | |||
| 001f45b3a9 | |||
| 472f55faa8 | |||
| 4315386cfe | |||
| 0a3a86637b | |||
| 00caf953fa | |||
| 03d8cf087b | |||
| 7fd9e33cb4 | |||
| 1b09ac739e | |||
| 48c0937081 | |||
| 982b635653 | |||
| 252c0fd86d | |||
| f4e4ae6508 | |||
| 3712ca6273 | |||
| cc203dc17e | |||
| 4c5ad29782 | |||
| 2765a7fadc | |||
| 3d9596716b | |||
| c66b57daff | |||
| be9736c796 | |||
| 8f8879eaac | |||
| 59686c07db | |||
| 8ec9cdf607 | |||
| c3f6af77ee | |||
| 652e1955b0 | |||
| 4bed6f6bfc | |||
| 611172df48 | |||
| 7eb487ae30 | |||
| b6a00be9f1 | |||
| 4969ff7fbb | |||
| 66c08fb446 | |||
| 868078fe36 | |||
| 043ed96294 | |||
| dcc18e4e7c | |||
| 7b9a314093 | |||
| bc8b6e7e6f | |||
| 4221d3b985 | |||
| 05a3af4c39 | |||
| 62d499219a | |||
| 73d345cd24 | |||
| 37d788449e | |||
| bb9e4cb7c2 | |||
| 2b746aa134 | |||
| 9a03511d2a | |||
| 9865597b4a | |||
| b0c7a50b06 | |||
| 6c167f5ef9 | |||
| 31c65fa5e8 | |||
| a60dbb32df | |||
| c18067d705 | |||
| a5dc451697 | |||
| 0ac693c74c | |||
| 321271c510 | |||
| cdfb4101be | |||
| 0dc8b03f07 | |||
| f25ee81a81 | |||
| 504f43ea4b | |||
| d0deb8d9d2 | |||
| 5772b681d0 | |||
| d232f16e07 | |||
| 2675651ca8 | |||
| 5f394317b5 | |||
| 5b296967eb | |||
| aea6d53eaf | |||
| e0cbd452a0 | |||
| 6d8174e89f | |||
| f4946a9e9d | |||
| 4c3b24fcda | |||
| fd79368f3b | |||
| d2cfd239d5 | |||
| fb3e0969cc | |||
| 2861467183 | |||
| d478d6a931 | |||
| dc77655e2a | |||
| 15ebf13cf1 | |||
| 71e9076e50 | |||
| f5d88c5813 | |||
| 639a914846 | |||
| cff8a98850 | |||
| 999d157c75 | |||
| 9f414becd1 | |||
| 043d2e9f36 | |||
| 3f78957ccc | |||
| 8bcb9331fd | |||
| af3234f1d7 | |||
| e2ff61da9b | |||
| 634de04d23 | |||
| 80e87ee0ae | |||
| bcb3f6077c | |||
| b69089883f | |||
| 2474cd56cc | |||
| 87679a75b8 | |||
| c6c41f1a29 | |||
| cf62e14547 | |||
| 261428ec98 | |||
| 5d57078474 | |||
| 11229fc9c0 | |||
| 1727b59882 | |||
| 5ecacfd879 | |||
| 0ecaf72ed4 | |||
| 2f6e0a59fd | |||
| 3300143b1b | |||
| e95ae50ab5 | |||
| b745bf1e5a | |||
| 902413200a | |||
| ce57ac073b | |||
| 8451eebe96 | |||
| 91bf49bdd4 | |||
| 017cbbfa51 | |||
| 4f8b6f7b84 | |||
| 8773fbf7d9 | |||
| 8d4ff30c60 | |||
| cb47382c9d | |||
| c60e002440 | |||
| d727aea5ad | |||
| be2ba93ca0 | |||
| 48425a1fc1 | |||
| 851a5b2f44 | |||
| 84c8790192 | |||
| 25681a31e5 | |||
| 0a208866ce | |||
| 0c26ac0da7 | |||
| c9270bfa2f | |||
| 0a7d2f4343 | |||
| dc6107dac3 | |||
| 5eacdcee9d | |||
| 978839a861 | |||
| fbc243aa94 | |||
| 2d40ccfc16 | |||
| 194d4d7f71 | |||
| 1b06be660b | |||
| 5b596aec6f | |||
| 8d5403b26a | |||
| 09533fee0c | |||
| 1150937f33 | |||
| 94d9ea0863 | |||
| 6ee6161d23 | |||
| 4e16a1454d | |||
| 3ad47fb1d0 | |||
| 6bad4f56f7 | |||
| d0bdd513cd | |||
| 54b920eb79 | |||
| c041b0068c | |||
| e453e79bc8 | |||
| d4bf69422c | |||
| e9c2249a81 | |||
| b02e848395 | |||
| ed9d5615ba | |||
| 8264fd8b93 | |||
| 532e7710f3 | |||
| 62bd6cee67 | |||
| 63fa61ecd7 | |||
| e8af5d6364 | |||
| 386ec39885 | |||
| 39808e3627 | |||
| 2a99c660c3 | |||
| ff717ae03e | |||
| 15cb2f05c7 | |||
| 8bb3420b92 | |||
| 6365c3b17c | |||
| 3595162d1a | |||
| 8e97f70b92 | |||
| 8dd8f08d10 | |||
| a9a35894ad | |||
| 8d637c8e33 | |||
| c3a1a438d8 | |||
| 9f75a6b5a6 | |||
| 99da7077ab | |||
| 221e383f11 | |||
| 3d941253a5 | |||
| 0d41146fa8 | |||
| 6b09953b09 | |||
| 255c58f6ba | |||
| 3fed5bfaf3 | |||
| 7f04682b4c | |||
| 3543d4948c | |||
| 33b1bb50c1 | |||
| a6545b1604 | |||
| 42093dadd1 | |||
| 18eee85ff1 | |||
| 2db4cb0e8c | |||
| 26d0b8d4ee | |||
| 323660961f | |||
| 88966b488a | |||
| 41fc9c55a0 | |||
| 8c2b3d5e37 | |||
| 22fc7e9dae | |||
| 9f53e446d9 | |||
| 938b1aa189 | |||
| 7e0ba31ceb | |||
| fe46b24be5 | |||
| a9e94ef9bb | |||
| c9db3ef937 | |||
| 9a3dc91b35 | |||
| f362771af3 | |||
| 7251ea4ac6 | |||
| c5e71d2f37 | |||
| 61ce864e28 | |||
| 36d0a70b69 | |||
| 20a2007d10 | |||
| 64701acb68 | |||
| 17922bd096 | |||
| f85055a19c | |||
| 28ebecdbc5 | |||
| 5eda5fc81b | |||
| 7bc86efee9 | |||
| d60e071fa9 | |||
| b70289ce15 | |||
| 71e65750d1 | |||
| be8cc7c15f | |||
| 589abe5519 | |||
| be622c7932 | |||
| 2ce741275b | |||
| 8cb09e1329 | |||
| 17f21c5b6f | |||
| 0992311f83 | |||
| a42fea2041 | |||
| 4aaf4f437b | |||
| 610bb58845 | |||
| 4c77b9162e | |||
| cd096d1c2e | |||
| 11a7b2d9bf | |||
| 7fa09edc03 | |||
| 13ae651f46 | |||
| c345bb1d8f | |||
| a2b00731cb | |||
| d36b78e273 | |||
| 6ab7c27d9b | |||
| a90c3bc8be | |||
| 8b3c922cf0 | |||
| d460e0e735 | |||
| a52b947ce2 | |||
| c75137b262 | |||
| 6fd3f9bad8 | |||
| 00c48f0ba3 | |||
| f78b6fdd17 | |||
| 7c537ee201 | |||
| e2d77db22a | |||
| bf5e361b26 | |||
| a7ad4488b9 | |||
| f7fbcfe59d | |||
| 1efed2ed00 | |||
| 15c43ad722 | |||
| 5fcbfcc359 | |||
| 672d80735f | |||
| 2f5e35035d | |||
| 1aafc5b0ef | |||
| 9f66b533e2 | |||
| 65a8f13d98 | |||
| 9a4eb3e0b0 | |||
| 3148499f69 | |||
| dca99bea38 | |||
| 392cf59937 | |||
| 0bf4dbc3b0 | |||
| 0a94454812 | |||
| 2a698bf73e | |||
| 64e6706a0b | |||
| 18e80ea755 | |||
| af7e33bae8 | |||
| 484fa1ac63 | |||
| 603af161fd | |||
| 42906ef1ae | |||
| c9a9d8bd97 | |||
| 91f0b5c6cd | |||
| e0eccb87b5 | |||
| 5b8976af61 | |||
| a7cf5c2cbb | |||
| 5fe6367d08 | |||
| 99ba8c8cc8 | |||
| 88213d0cfd | |||
| 66f2a6fe01 | |||
| 365f3bd4dc | |||
| a85488fbb8 | |||
| c5933c9d8d | |||
| de0ea4820c | |||
| 26e60a6b4b | |||
| e7d4197a08 | |||
| 0db8d26c12 | |||
| 26c583b5c4 | |||
| 181dba4514 | |||
| 5f5698900c | |||
| 1d0dc50f98 | |||
| 2890a4ede8 | |||
| 882eaf15bf | |||
| 6fba167ef9 | |||
| 65b8466f22 | |||
| 9c3ec2fd2d | |||
| a1d96b4d8a | |||
| 57bca3c658 | |||
| 40422ea5d6 | |||
| 7017f8ebf0 | |||
| 19660515b5 | |||
| d1fe6a9667 | |||
| c227f977e6 | |||
| b9cf00f4ce | |||
| d192b4fa8f | |||
| f760fa00ae | |||
| 83cbf29588 | |||
| 022b058bc5 | |||
| f789be8485 | |||
| 8310b01530 | |||
| d2f755286c | |||
| 8fbcaf423e | |||
| 6ff384ba3f | |||
| 9e2be16440 | |||
| 5dfc758d33 | |||
| 14894b4b66 | |||
| fdccc48bf7 | |||
| 8e491aaf58 | |||
| c46d931f40 | |||
| 6c3468b02f | |||
| d398ba2c62 | |||
| 8e346aa668 | |||
| 989f3c5ecc | |||
| 5806c90a3e | |||
| 2c081208eb | |||
| ef64a1bf5f | |||
| 278ce557da | |||
| 5ff4ff176b | |||
| 87b02db857 | |||
| c0929d6954 | |||
| 8ca37f5d44 | |||
| f43e347fbf | |||
| 32003bd048 | |||
| a326b4b4cd | |||
| bf1368b4cf | |||
| c3d5b9d62e | |||
| d5916b92d5 | |||
| 91dd484c27 | |||
| bfaf9e6f66 | |||
| 30eb131980 | |||
| 24d0084938 | |||
| a7cadcc390 | |||
| 8cfdc1cbc2 | |||
| 88dd52414f | |||
| 0b21c835a4 | |||
| 81f3709a9f | |||
| f6214eb932 | |||
| de3e265b36 | |||
| 3239f78e69 | |||
| d27257bbbb | |||
| 4631a7e81f | |||
| 53f2722a3d | |||
| 0d62ee7598 | |||
| 1efeded724 | |||
| 29aaade7ab | |||
| f7f91aec22 | |||
| 1d4c811611 | |||
| 421fe728f1 | |||
| 9683bccaf6 | |||
| 666826198f | |||
| fcbb07b1a0 | |||
| 9e067e91ee | |||
| c675c28356 | |||
| f2f7e8d516 | |||
| 8237b60749 | |||
| 7405041b42 | |||
| 4bc57a9792 | |||
| 851d6f1b96 | |||
| 4eeaaf1b08 | |||
| 243f10d5fb | |||
| 837809774b | |||
| 2100e46b60 | |||
| c7f9c1bd69 | |||
| 574fabf9ca | |||
| 00def2849c | |||
| 9df9019c1e | |||
| c818b6ada3 | |||
| be750af7ff | |||
| f8752fbe2c | |||
| fbbfcc5a74 | |||
| 67ccfb11c7 | |||
| 31d9f18fca | |||
| 02b6a7a82b | |||
| 3103b9bfea | |||
| fb470830ed | |||
| a988911e05 | |||
| 9abe003d1d | |||
| 81477e857a | |||
| 67669174f0 | |||
| e0d7ce9e57 | |||
| ec975a36cd | |||
| 65ca70c731 | |||
| 3dffd9a942 | |||
| 547c9eaad0 | |||
| 40c70cc865 | |||
| 112c02991d | |||
| bdc16ce545 | |||
| 5c041d3b78 | |||
| 97949b12b3 | |||
| fabf747d74 | |||
| 41b7ba1092 | |||
| f86b42cd81 | |||
| 3d0859dc39 | |||
| 1ad1340b58 | |||
| 05231722e5 |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
+11
@@ -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
|
||||
@@ -91,6 +91,14 @@ struct CarEvent @0x9b1657f34caf3ad3 {
|
||||
carUnrecognized @66;
|
||||
radarCommIssue @67;
|
||||
driverMonitorLowAcc @68;
|
||||
# dragonpilot
|
||||
manualSteeringRequired @69;
|
||||
manualSteeringRequiredBlinkersOn @70;
|
||||
leadCarMoving @71;
|
||||
leadCarDetected @72;
|
||||
preAutoLaneChangeLeft @73;
|
||||
preAutoLaneChangeRight @74;
|
||||
autoLaneChange @75;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -293,6 +293,8 @@ struct ThermalData {
|
||||
memUsedPercent @19 :Int8;
|
||||
cpuPerc @20 :Int8;
|
||||
|
||||
ipAddr @24 :Text; # dragonpilot
|
||||
|
||||
enum ThermalStatus {
|
||||
green @0; # all processes run
|
||||
yellow @1; # critical processes run (kill uploader), engage still allowed
|
||||
@@ -765,6 +767,8 @@ struct PathPlan {
|
||||
desire @17 :Desire;
|
||||
laneChangeState @18 :LaneChangeState;
|
||||
laneChangeDirection @19 :LaneChangeDirection;
|
||||
# dragonpilot
|
||||
autoLCAllowed @20 :Bool;
|
||||
|
||||
enum Desire {
|
||||
none @0;
|
||||
|
||||
+1
-1
@@ -6,7 +6,7 @@ import shutil
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.swaglog import cloudlog
|
||||
|
||||
android_packages = ("ai.comma.plus.offroad", "ai.comma.plus.frame")
|
||||
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")
|
||||
|
||||
@@ -103,6 +103,72 @@ keys = {
|
||||
"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],
|
||||
"DragonEnableAutoShutdown": [TxType.PERSISTENT],
|
||||
"DragonAutoShutdownAt": [TxType.PERSISTENT],
|
||||
"DragonEnableSteeringOnSignal": [TxType.PERSISTENT],
|
||||
"DragonEnableLogger": [TxType.PERSISTENT],
|
||||
"DragonEnableUploader": [TxType.PERSISTENT],
|
||||
"DragonNoctuaMode": [TxType.PERSISTENT],
|
||||
"DragonCacheCar": [TxType.PERSISTENT],
|
||||
"DragonCachedModel": [TxType.PERSISTENT],
|
||||
"DragonCachedFP": [TxType.PERSISTENT],
|
||||
"DragonCachedVIN": [TxType.PERSISTENT],
|
||||
"DragonCachedCarFW": [TxType.PERSISTENT],
|
||||
"DragonCachedSource": [TxType.PERSISTENT],
|
||||
"DragonAllowGas": [TxType.PERSISTENT],
|
||||
"DragonToyotaStockDSU": [TxType.PERSISTENT],
|
||||
"DragonLatCtrl": [TxType.PERSISTENT],
|
||||
"DragonUISpeed": [TxType.PERSISTENT],
|
||||
"DragonUIEvent": [TxType.PERSISTENT],
|
||||
"DragonUIMaxSpeed": [TxType.PERSISTENT],
|
||||
"DragonUIFace": [TxType.PERSISTENT],
|
||||
"DragonUIDev": [TxType.PERSISTENT],
|
||||
"DragonUIDevMini": [TxType.PERSISTENT],
|
||||
"DragonEnableTomTom": [TxType.PERSISTENT],
|
||||
"DragonBootTomTom": [TxType.PERSISTENT],
|
||||
"DragonRunTomTom": [TxType.PERSISTENT],
|
||||
"DragonEnableAutonavi": [TxType.PERSISTENT],
|
||||
"DragonBootAutonavi": [TxType.PERSISTENT],
|
||||
"DragonRunAutonavi": [TxType.PERSISTENT],
|
||||
"DragonEnableAegis": [TxType.PERSISTENT],
|
||||
"DragonBootAegis": [TxType.PERSISTENT],
|
||||
"DragonRunAegis": [TxType.PERSISTENT],
|
||||
"DragonEnableMixplorer": [TxType.PERSISTENT],
|
||||
"DragonRunMixplorer": [TxType.PERSISTENT],
|
||||
"DragonSteeringMonitorTimer": [TxType.PERSISTENT],
|
||||
"DragonCameraOffset": [TxType.PERSISTENT],
|
||||
"DragonUIVolumeBoost": [TxType.PERSISTENT],
|
||||
"DragonGreyPandaMode": [TxType.PERSISTENT],
|
||||
"DragonDrivingUI": [TxType.PERSISTENT],
|
||||
"DragonDisplaySteeringLimitAlert": [TxType.PERSISTENT],
|
||||
"DragonChargingCtrl": [TxType.PERSISTENT],
|
||||
"DragonCharging": [TxType.PERSISTENT],
|
||||
"DragonDisCharging": [TxType.PERSISTENT],
|
||||
"DragonToyotaLaneDepartureWarning": [TxType.PERSISTENT],
|
||||
"DragonUILane": [TxType.PERSISTENT],
|
||||
"DragonUILead": [TxType.PERSISTENT],
|
||||
"DragonUIPath": [TxType.PERSISTENT],
|
||||
"DragonUIBlinker": [TxType.PERSISTENT],
|
||||
"DragonUIDMView": [TxType.PERSISTENT],
|
||||
"DragonEnableDriverMonitoring": [TxType.PERSISTENT],
|
||||
"DragonCarModel": [TxType.PERSISTENT],
|
||||
"DragonEnableSlowOnCurve": [TxType.PERSISTENT],
|
||||
"DragonEnableLeadCarMovingAlert": [TxType.PERSISTENT],
|
||||
"DragonToyotaSnGMod": [TxType.PERSISTENT],
|
||||
"DragonEnableSRLearner": [TxType.PERSISTENT],
|
||||
"DragonWazeMode": [TxType.PERSISTENT],
|
||||
"DragonRunWaze": [TxType.PERSISTENT],
|
||||
"DragonEnableAutoLC": [TxType.PERSISTENT],
|
||||
"DragonAssistedLCMinMPH": [TxType.PERSISTENT],
|
||||
"DragonAutoLCMinMPH": [TxType.PERSISTENT],
|
||||
"DragonAutoLCDelay": [TxType.PERSISTENT],
|
||||
"DragonBTG": [TxType.PERSISTENT],
|
||||
"DragonBootHotspot": [TxType.PERSISTENT],
|
||||
"DragonAccelProfile": [TxType.PERSISTENT],
|
||||
"DragonLastModified": [TxType.PERSISTENT],
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2019-, Rick Lan, dragonpilot community, and a number of other of contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,92 @@
|
||||
This Font Software is licensed under the SIL Open Font License,
|
||||
Version 1.1.
|
||||
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font
|
||||
creation efforts of academic and linguistic communities, and to
|
||||
provide a free and open framework in which fonts may be shared and
|
||||
improved in partnership with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply to
|
||||
any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software
|
||||
components as distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to,
|
||||
deleting, or substituting -- in part or in whole -- any of the
|
||||
components of the Original Version, by changing formats or by porting
|
||||
the Font Software to a new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed,
|
||||
modify, redistribute, and sell modified and unmodified copies of the
|
||||
Font Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components, in
|
||||
Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the
|
||||
corresponding Copyright Holder. This restriction only applies to the
|
||||
primary font name as presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created using
|
||||
the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,372 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
NOTE: this is the newer (L) version of the system font configuration,
|
||||
supporting richer weight selection. Some apps will expect the older
|
||||
version, so please keep system_fonts.xml and fallback_fonts.xml in sync
|
||||
with any changes, even though framework will only read this file.
|
||||
|
||||
All fonts withohut names are added to the default list. Fonts are chosen
|
||||
based on a match: full BCP-47 language tag including script, then just
|
||||
language, and finally order (the first font containing the glyph).
|
||||
|
||||
Order of appearance is also the tiebreaker for weight matching. This is
|
||||
the reason why the 900 weights of Roboto precede the 700 weights - we
|
||||
prefer the former when an 800 weight is requested. Since bold spans
|
||||
effectively add 300 to the weight, this ensures that 900 is the bold
|
||||
paired with the 500 weight, ensuring adequate contrast.
|
||||
-->
|
||||
<familyset version="22">
|
||||
<!-- first font is default -->
|
||||
<family name="sans-serif">
|
||||
<font weight="100" style="normal">Roboto-Thin.ttf</font>
|
||||
<font weight="100" style="italic">Roboto-ThinItalic.ttf</font>
|
||||
<font weight="300" style="normal">Roboto-Light.ttf</font>
|
||||
<font weight="300" style="italic">Roboto-LightItalic.ttf</font>
|
||||
<font weight="400" style="normal">Roboto-Regular.ttf</font>
|
||||
<font weight="400" style="italic">Roboto-Italic.ttf</font>
|
||||
<font weight="500" style="normal">Roboto-Medium.ttf</font>
|
||||
<font weight="500" style="italic">Roboto-MediumItalic.ttf</font>
|
||||
<font weight="900" style="normal">Roboto-Black.ttf</font>
|
||||
<font weight="900" style="italic">Roboto-BlackItalic.ttf</font>
|
||||
<font weight="700" style="normal">Roboto-Bold.ttf</font>
|
||||
<font weight="700" style="italic">Roboto-BoldItalic.ttf</font>
|
||||
</family>
|
||||
|
||||
<!-- Note that aliases must come after the fonts they reference. -->
|
||||
<alias name="sans-serif-thin" to="sans-serif" weight="100" />
|
||||
<alias name="sans-serif-light" to="sans-serif" weight="300" />
|
||||
<alias name="sans-serif-medium" to="sans-serif" weight="500" />
|
||||
<alias name="sans-serif-black" to="sans-serif" weight="900" />
|
||||
<alias name="arial" to="sans-serif" />
|
||||
<alias name="helvetica" to="sans-serif" />
|
||||
<alias name="tahoma" to="sans-serif" />
|
||||
<alias name="verdana" to="sans-serif" />
|
||||
|
||||
<family name="sans-serif-condensed">
|
||||
<font weight="300" style="normal">RobotoCondensed-Light.ttf</font>
|
||||
<font weight="300" style="italic">RobotoCondensed-LightItalic.ttf</font>
|
||||
<font weight="400" style="normal">RobotoCondensed-Regular.ttf</font>
|
||||
<font weight="400" style="italic">RobotoCondensed-Italic.ttf</font>
|
||||
<font weight="700" style="normal">RobotoCondensed-Bold.ttf</font>
|
||||
<font weight="700" style="italic">RobotoCondensed-BoldItalic.ttf</font>
|
||||
</family>
|
||||
<alias name="sans-serif-condensed-light" to="sans-serif-condensed" weight="300" />
|
||||
|
||||
<family name="serif">
|
||||
<font weight="400" style="normal">NotoSerif-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSerif-Bold.ttf</font>
|
||||
<font weight="400" style="italic">NotoSerif-Italic.ttf</font>
|
||||
<font weight="700" style="italic">NotoSerif-BoldItalic.ttf</font>
|
||||
</family>
|
||||
<alias name="times" to="serif" />
|
||||
<alias name="times new roman" to="serif" />
|
||||
<alias name="palatino" to="serif" />
|
||||
<alias name="georgia" to="serif" />
|
||||
<alias name="baskerville" to="serif" />
|
||||
<alias name="goudy" to="serif" />
|
||||
<alias name="fantasy" to="serif" />
|
||||
<alias name="ITC Stone Serif" to="serif" />
|
||||
|
||||
<family name="monospace">
|
||||
<font weight="400" style="normal">DroidSansMono.ttf</font>
|
||||
</family>
|
||||
<alias name="sans-serif-monospace" to="monospace" />
|
||||
<alias name="monaco" to="monospace" />
|
||||
|
||||
<family name="serif-monospace">
|
||||
<font weight="400" style="normal">CutiveMono.ttf</font>
|
||||
</family>
|
||||
<alias name="courier" to="serif-monospace" />
|
||||
<alias name="courier new" to="serif-monospace" />
|
||||
|
||||
<family name="casual">
|
||||
<font weight="400" style="normal">ComingSoon.ttf</font>
|
||||
</family>
|
||||
|
||||
<family name="cursive">
|
||||
<font weight="400" style="normal">DancingScript-Regular.ttf</font>
|
||||
<font weight="700" style="normal">DancingScript-Bold.ttf</font>
|
||||
</family>
|
||||
|
||||
<family name="sans-serif-smallcaps">
|
||||
<font weight="400" style="normal">CarroisGothicSC-Regular.ttf</font>
|
||||
</family>
|
||||
|
||||
<!-- fallback fonts -->
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoNaskhArabic-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoNaskhArabic-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoNaskhArabicUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoNaskhArabicUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansEthiopic-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansEthiopic-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansHebrew-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansHebrew-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansThai-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansThai-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansThaiUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansThaiUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansArmenian-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansArmenian-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansGeorgian-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansGeorgian-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansDevanagari-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansDevanagari-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansDevanagariUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansDevanagariUI-Bold.ttf</font>
|
||||
</family>
|
||||
<!-- Gujarati should come after Devanagari -->
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansGujarati-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansGujarati-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansGujaratiUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansGujaratiUI-Bold.ttf</font>
|
||||
</family>
|
||||
<!-- Gurmukhi should come after Devanagari -->
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansGurmukhi-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansGurmukhi-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansGurmukhiUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansGurmukhiUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansTamil-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansTamil-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansTamilUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansTamilUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansMalayalam-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansMalayalam-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansMalayalamUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansMalayalamUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansBengali-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansBengali-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansBengaliUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansBengaliUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansTelugu-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansTelugu-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansTeluguUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansTeluguUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansKannada-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansKannada-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansKannadaUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansKannadaUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansOriya-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansOriya-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansOriyaUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansOriyaUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSinhala-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansSinhala-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansKhmer-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansKhmer-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansKhmerUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansKhmerUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansLao-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansLao-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansLaoUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansLaoUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="elegant">
|
||||
<font weight="400" style="normal">NotoSansMyanmar-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansMyanmar-Bold.ttf</font>
|
||||
</family>
|
||||
<family variant="compact">
|
||||
<font weight="400" style="normal">NotoSansMyanmarUI-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansMyanmarUI-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansThaana-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansThaana-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansCham-Regular.ttf</font>
|
||||
<font weight="700" style="normal">NotoSansCham-Bold.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansBalinese-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansBamum-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansBatak-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansBuginese-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansBuhid-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansCanadianAboriginal-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansCherokee-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansCoptic-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansGlagolitic-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansHanunoo-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansJavanese-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansKayahLi-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansLepcha-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansLimbu-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansLisu-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansMandaic-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansMeeteiMayek-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansNewTaiLue-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansNKo-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansOlChiki-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansRejang-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSaurashtra-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSundanese-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSylotiNagri-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSyriacEstrangela-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTagbanwa-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTaiTham-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTaiViet-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTibetan-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTifinagh-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansVai-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansYi-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansSymbols-Regular-Subsetted.ttf</font>
|
||||
</family>
|
||||
<family lang="ja">
|
||||
<font weight="400" style="normal">NotoSansJP-Regular.otf</font>
|
||||
</family>
|
||||
<family lang="ko">
|
||||
<font weight="400" style="normal">NotoSansKR-Regular.otf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NanumGothic.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoColorEmoji.ttf</font>
|
||||
</family>
|
||||
<family lang="zh-Hans">
|
||||
<font weight="400" style="normal">NotoSansCJKtc-Regular.otf</font>
|
||||
<font weight="500" style="normal">NotoSansCJKtc-Medium.otf</font>
|
||||
<font weight="700" style="normal">NotoSansCJKtc-Bold.otf</font>
|
||||
</family>
|
||||
<family lang="zh-Hant">
|
||||
<font weight="400" style="normal">NotoSansCJKtc-Regular.otf</font>
|
||||
<font weight="500" style="normal">NotoSansCJKtc-Medium.otf</font>
|
||||
<font weight="700" style="normal">NotoSansCJKtc-Bold.otf</font>
|
||||
</family>
|
||||
<family lang="ja">
|
||||
<font weight="400" style="normal">MTLmr3m.ttf</font>
|
||||
</family>
|
||||
<!--
|
||||
Tai Le and Mongolian are intentionally kept last, to make sure they don't override
|
||||
the East Asian punctuation for Chinese.
|
||||
-->
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansTaiLe-Regular.ttf</font>
|
||||
</family>
|
||||
<family>
|
||||
<font weight="400" style="normal">NotoSansMongolian-Regular.ttf</font>
|
||||
</family>
|
||||
</familyset>
|
||||
Executable
+71
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
###############################################################################
|
||||
# The MIT License
|
||||
#
|
||||
# Copyright (c) 2019-, Rick Lan, dragonpilot community, and a number of other of contributors.
|
||||
#
|
||||
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
# of this software and associated documentation files (the "Software"), to deal
|
||||
# in the Software without restriction, including without limitation the rights
|
||||
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
# copies of the Software, and to permit persons to whom the Software is
|
||||
# furnished to do so, subject to the following conditions:
|
||||
#
|
||||
# The above copyright notice and this permission notice shall be included in
|
||||
# all copies or substantial portions of the Software.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
# THE SOFTWARE.
|
||||
#
|
||||
# Noto is a trademark of Google Inc. Noto fonts are open source.
|
||||
# All Noto fonts are published under the SIL Open Font License,
|
||||
# Version 1.1. Language data and some sample texts are from the Unicode CLDR project.
|
||||
#
|
||||
###############################################################################
|
||||
|
||||
|
||||
# Android system locale, zh-TW = Traditional Chinese, zh-CN = Simplified Chinese
|
||||
lang=zh-TW
|
||||
|
||||
update_font=0
|
||||
remove_old_font=0
|
||||
|
||||
# check regular font
|
||||
if [ ! -f "/system/fonts/NotoSansCJKtc-Regular.otf" ]; then
|
||||
update_font=1
|
||||
fi
|
||||
|
||||
# check miui font
|
||||
if ls /system/fonts/Miui*.ttf 1> /dev/null 2>&1; then
|
||||
remove_old_font=1
|
||||
fi
|
||||
|
||||
if [ $update_font -eq "1" ] || [ $remove_old_font -eq "1" ]; then
|
||||
# sleep 3 secs in case, make sure the /system is re-mountable
|
||||
sleep 3
|
||||
mount -o remount,rw /system
|
||||
if [ $update_font -eq "1" ]; then
|
||||
# install font
|
||||
cp -rf /data/openpilot/dragonpilot/chinese-fonts/NotoSansCJKtc-* /system/fonts/
|
||||
# install font mapping
|
||||
cp -rf /data/openpilot/dragonpilot/chinese-fonts/fonts.xml /system/etc/fonts.xml
|
||||
# change permissions
|
||||
chmod 644 /system/etc/fonts.xml
|
||||
chmod 644 /system/fonts/NotoSansCJKtc-*
|
||||
fi
|
||||
# remove miui font
|
||||
if [ $remove_old_font -eq "1" ]; then
|
||||
rm -fr /system/fonts/Miui*.ttf
|
||||
fi
|
||||
mount -o remount,r /system
|
||||
# change system locale
|
||||
fi
|
||||
|
||||
setprop persist.sys.locale $lang
|
||||
setprop persist.sys.local $lang
|
||||
@@ -31,9 +31,9 @@ FRAMEBUFFER_LIBS = -lutils -lgui -lEGL
|
||||
.PHONY: all
|
||||
all: updater
|
||||
|
||||
OBJS = opensans_regular.ttf.o \
|
||||
opensans_semibold.ttf.o \
|
||||
opensans_bold.ttf.o \
|
||||
OBJS = NotoSansCJKtc-Regular.otf.o \
|
||||
NotoSansCJKtc-Medium.otf.o \
|
||||
NotoSansCJKtc-Bold.otf.o \
|
||||
../../selfdrive/common/touch.o \
|
||||
../../selfdrive/common/framebuffer.o \
|
||||
$(PHONELIBS)/json11/json11.o \
|
||||
@@ -52,15 +52,15 @@ updater: updater.o $(OBJS)
|
||||
-lcutils -lm -llog
|
||||
strip updater
|
||||
|
||||
opensans_regular.ttf.o: ../../selfdrive/assets/fonts/opensans_regular.ttf
|
||||
NotoSansCJKtc-Regular.otf.o: ../../selfdrive/assets/fonts/NotoSansCJKtc-Regular.otf
|
||||
@echo "[ bin2o ] $@"
|
||||
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
|
||||
|
||||
opensans_bold.ttf.o: ../../selfdrive/assets/fonts/opensans_bold.ttf
|
||||
NotoSansCJKtc-Bold.otf.o: ../../selfdrive/assets/fonts/NotoSansCJKtc-Bold.otf
|
||||
@echo "[ bin2o ] $@"
|
||||
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
|
||||
|
||||
opensans_semibold.ttf.o: ../../selfdrive/assets/fonts/opensans_semibold.ttf
|
||||
NotoSansCJKtc-Medium.otf.o: ../../selfdrive/assets/fonts/NotoSansCJKtc-Medium.otf
|
||||
@echo "[ bin2o ] $@"
|
||||
cd '$(dir $<)' && ld -r -b binary '$(notdir $<)' -o '$(abspath $@)'
|
||||
|
||||
|
||||
Binary file not shown.
@@ -43,12 +43,12 @@ const char *manifest_url = MANIFEST_URL_EON;
|
||||
|
||||
#define UPDATE_DIR "/data/neoupdate"
|
||||
|
||||
extern const uint8_t bin_opensans_regular[] asm("_binary_opensans_regular_ttf_start");
|
||||
extern const uint8_t bin_opensans_regular_end[] asm("_binary_opensans_regular_ttf_end");
|
||||
extern const uint8_t bin_opensans_semibold[] asm("_binary_opensans_semibold_ttf_start");
|
||||
extern const uint8_t bin_opensans_semibold_end[] asm("_binary_opensans_semibold_ttf_end");
|
||||
extern const uint8_t bin_opensans_bold[] asm("_binary_opensans_bold_ttf_start");
|
||||
extern const uint8_t bin_opensans_bold_end[] asm("_binary_opensans_bold_ttf_end");
|
||||
extern const uint8_t bin_opensans_regular[] asm("_binary_NotoSansCJKtc_Regular_otf_start");
|
||||
extern const uint8_t bin_opensans_regular_end[] asm("_binary_NotoSansCJKtc_Regular_otf_end");
|
||||
extern const uint8_t bin_opensans_semibold[] asm("_binary_NotoSansCJKtc_Medium_otf_start");
|
||||
extern const uint8_t bin_opensans_semibold_end[] asm("_binary_NotoSansCJKtc_Medium_otf_end");
|
||||
extern const uint8_t bin_opensans_bold[] asm("_binary_NotoSansCJKtc_Bold_otf_start");
|
||||
extern const uint8_t bin_opensans_bold_end[] asm("_binary_NotoSansCJKtc_Bold_otf_end");
|
||||
|
||||
namespace {
|
||||
|
||||
@@ -322,18 +322,18 @@ struct Updater {
|
||||
std::string stage_download(std::string url, std::string hash, std::string name) {
|
||||
std::string out_fn = UPDATE_DIR "/" + util::base_name(url);
|
||||
|
||||
set_progress("Downloading " + name + "...");
|
||||
set_progress("下載 " + name + " 中...");
|
||||
bool r = download_file(url, out_fn);
|
||||
if (!r) {
|
||||
set_error("failed to download " + name);
|
||||
set_error("無法下載 " + name);
|
||||
return "";
|
||||
}
|
||||
|
||||
set_progress("Verifying " + name + "...");
|
||||
set_progress("驗證 " + name + " 中...");
|
||||
std::string fn_hash = sha256_file(out_fn);
|
||||
printf("got %s hash: %s\n", name.c_str(), hash.c_str());
|
||||
printf("得到 %s hash: %s\n", name.c_str(), hash.c_str());
|
||||
if (fn_hash != hash) {
|
||||
set_error(name + " was corrupt");
|
||||
set_error(name + " 已損壞");
|
||||
unlink(out_fn.c_str());
|
||||
return "";
|
||||
}
|
||||
@@ -357,7 +357,7 @@ struct Updater {
|
||||
}
|
||||
|
||||
if (!check_space()) {
|
||||
set_error("2GB of free space required to update");
|
||||
set_error("您需要至少 2GB 的空間進行升級");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -365,7 +365,7 @@ struct Updater {
|
||||
|
||||
const int EON = (access("/EON", F_OK) != -1);
|
||||
|
||||
set_progress("Finding latest version...");
|
||||
set_progress("尋找最新的版本...");
|
||||
std::string manifest_s;
|
||||
if (EON) {
|
||||
manifest_s = download_string(curl, manifest_url);
|
||||
@@ -374,12 +374,12 @@ struct Updater {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
printf("manifest: %s\n", manifest_s.c_str());
|
||||
printf("宣示說明: %s\n", manifest_s.c_str());
|
||||
|
||||
std::string err;
|
||||
auto manifest = json11::Json::parse(manifest_s, err);
|
||||
if (manifest.is_null() || !err.empty()) {
|
||||
set_error("failed to load update manifest");
|
||||
set_error("無法載入新的宣示說明");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -394,7 +394,7 @@ struct Updater {
|
||||
// std::string installer_hash = manifest["installer_hash"].string_value();
|
||||
|
||||
if (ota_url.empty() || ota_hash.empty()) {
|
||||
set_error("invalid update manifest");
|
||||
set_error("錯誤的宣示說明");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -406,12 +406,12 @@ struct Updater {
|
||||
|
||||
std::string recovery_fn;
|
||||
if (recovery_url.empty() || recovery_hash.empty() || recovery_len == 0) {
|
||||
set_progress("Skipping recovery flash...");
|
||||
set_progress("跳過 recovery 更新...");
|
||||
} else {
|
||||
// only download the recovery if it differs from what's flashed
|
||||
set_progress("Checking recovery...");
|
||||
set_progress("檢查 recovery...");
|
||||
std::string existing_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
|
||||
printf("existing recovery hash: %s\n", existing_recovery_hash.c_str());
|
||||
printf("目前 recovery 的 hash: %s\n", existing_recovery_hash.c_str());
|
||||
|
||||
if (existing_recovery_hash != recovery_hash) {
|
||||
recovery_fn = stage_download(recovery_url, recovery_hash, "recovery");
|
||||
@@ -441,18 +441,18 @@ struct Updater {
|
||||
|
||||
if (!recovery_fn.empty()) {
|
||||
// flash recovery
|
||||
set_progress("Flashing recovery...");
|
||||
set_progress("刷新 recovery...");
|
||||
|
||||
FILE *flash_file = fopen(recovery_fn.c_str(), "rb");
|
||||
if (!flash_file) {
|
||||
set_error("failed to flash recovery");
|
||||
set_error("刷新 recovery 失敗");
|
||||
return;
|
||||
}
|
||||
|
||||
FILE *recovery_dev = fopen(RECOVERY_DEV, "w+b");
|
||||
if (!recovery_dev) {
|
||||
fclose(flash_file);
|
||||
set_error("failed to flash recovery");
|
||||
set_error("刷新 recovery 失敗");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -467,7 +467,7 @@ struct Updater {
|
||||
if (bytes_read != bytes_written) {
|
||||
fclose(recovery_dev);
|
||||
fclose(flash_file);
|
||||
set_error("failed to flash recovery: write failed");
|
||||
set_error("刷新 recovery 失敗: 無法寫入");
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -475,12 +475,12 @@ struct Updater {
|
||||
fclose(recovery_dev);
|
||||
fclose(flash_file);
|
||||
|
||||
set_progress("Verifying flash...");
|
||||
set_progress("驗證新的 recovery...");
|
||||
std::string new_recovery_hash = sha256_file(RECOVERY_DEV, recovery_len);
|
||||
printf("new recovery hash: %s\n", new_recovery_hash.c_str());
|
||||
printf("新的 recovery hash: %s\n", new_recovery_hash.c_str());
|
||||
|
||||
if (new_recovery_hash != recovery_hash) {
|
||||
set_error("recovery flash corrupted");
|
||||
set_error("刷新 recovery 失敗");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -489,13 +489,13 @@ struct Updater {
|
||||
// write arguments to recovery
|
||||
FILE *cmd_file = fopen(RECOVERY_COMMAND, "wb");
|
||||
if (!cmd_file) {
|
||||
set_error("failed to reboot into recovery");
|
||||
set_error("無法重啟至 recovery");
|
||||
return;
|
||||
}
|
||||
fprintf(cmd_file, "--update_package=%s\n", ota_fn.c_str());
|
||||
fclose(cmd_file);
|
||||
|
||||
set_progress("Rebooting");
|
||||
set_progress("重新啟動");
|
||||
|
||||
// remove the continue.sh so we come back into the setup.
|
||||
// maybe we should go directly into the installer, but what if we don't come back with internet? :/
|
||||
@@ -562,9 +562,9 @@ struct Updater {
|
||||
}
|
||||
|
||||
void draw_battery_screen() {
|
||||
low_battery_title = "Low Battery";
|
||||
low_battery_text = "Please connect EON to your charger. Update will continue once EON battery reaches 35%.";
|
||||
low_battery_context = "Current battery charge: " + battery_cap_text + "%";
|
||||
low_battery_title = "電量過低";
|
||||
low_battery_text = "請將您的 EON 充電。當電量達到 35% 時系統將會繼續更新。";
|
||||
low_battery_context = "目前的電量為: " + battery_cap_text + "%";
|
||||
|
||||
nvgFillColor(vg, nvgRGBA(255,255,255,255));
|
||||
nvgTextAlign(vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
|
||||
@@ -601,7 +601,7 @@ struct Updater {
|
||||
int powerprompt_y = 312;
|
||||
nvgFontFace(vg, "opensans_regular");
|
||||
nvgFontSize(vg, 64.0f);
|
||||
nvgText(vg, fb_w/2, 740, "Ensure EON is connected to power.", NULL);
|
||||
nvgText(vg, fb_w/2, 740, "請確保您的 EON 已接上充電器。", NULL);
|
||||
|
||||
NVGpaint paint = nvgBoxGradient(
|
||||
vg, progress_x + 1, progress_y + 1,
|
||||
@@ -635,10 +635,10 @@ struct Updater {
|
||||
|
||||
switch (state) {
|
||||
case CONFIRMATION:
|
||||
draw_ack_screen("An update to NEOS is required.",
|
||||
"Your device will now be reset and upgraded. You may want to connect to wifi as download is around 1 GB. Existing data on device should not be lost.",
|
||||
"Continue",
|
||||
"Connect to WiFi");
|
||||
draw_ack_screen("NEOS 需要更新。",
|
||||
"您的設備將在點擊繼續後開始更新。\n更新檔約為 1GB 我們建議您先連接至無線網路。\n設備上現有的檔案不會丟失。",
|
||||
"繼續",
|
||||
"連線至無線網路");
|
||||
break;
|
||||
case LOW_BATTERY:
|
||||
draw_battery_screen();
|
||||
@@ -647,7 +647,7 @@ struct Updater {
|
||||
draw_progress_screen();
|
||||
break;
|
||||
case ERROR:
|
||||
draw_ack_screen("There was an error", (error_text).c_str(), NULL, "Reboot");
|
||||
draw_ack_screen("發生錯誤", (error_text).c_str(), NULL, "重新啟動");
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
/usr/bin/sh /data/openpilot/dragonpilot/chinese-fonts/installer.sh &
|
||||
export PASSIVE="0"
|
||||
exec ./launch_chffrplus.sh
|
||||
|
||||
|
||||
@@ -373,7 +373,7 @@ BO_ 705 GAS_PEDAL: 8 XXX
|
||||
SG_ GAS_PEDAL : 55|8@0+ (0.005,0) [0|1] "" XXX
|
||||
|
||||
BO_ 608 STEER_TORQUE_SENSOR: 8 XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (0.77,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_EPS : 47|16@0- (1.30,0) [-20000|20000] "" XXX
|
||||
SG_ STEER_TORQUE_DRIVER : 15|16@0- (1,0) [-32768|32767] "" XXX
|
||||
SG_ STEER_OVERRIDE : 0|1@0+ (1,0) [0|1] "" XXX
|
||||
SG_ CHECKSUM : 63|8@0+ (1,0) [0|255] "" XXX
|
||||
|
||||
@@ -125,7 +125,7 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > HONDA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= HONDA_GAS_INTERCEPTOR_THRESHOLD)) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
@@ -135,7 +135,7 @@ static int honda_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if (addr == 0x17C) {
|
||||
int gas = GET_BYTE(to_push, 0);
|
||||
if (gas && !honda_gas_prev) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
honda_gas_prev = gas;
|
||||
}
|
||||
@@ -194,8 +194,9 @@ static int honda_tx_hook(CAN_FIFOMailBox_TypeDef *to_send) {
|
||||
|
||||
// disallow actuator commands if gas or brake (with vehicle moving) are pressed
|
||||
// and the the latching controls_allowed flag is True
|
||||
int pedal_pressed = honda_gas_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) ||
|
||||
(honda_brake_pressed_prev && honda_moving);
|
||||
//int pedal_pressed = honda_gas_prev || (gas_interceptor_prev > HONDA_GAS_INTERCEPTOR_THRESHOLD) ||
|
||||
// (honda_brake_pressed_prev && honda_moving);
|
||||
int pedal_pressed = honda_brake_pressed_prev && honda_moving;
|
||||
bool current_controls_allowed = controls_allowed && !(pedal_pressed);
|
||||
|
||||
// BRAKE: safety check
|
||||
|
||||
@@ -4,8 +4,8 @@ const int TOYOTA_MAX_TORQUE = 1500; // max torque cmd allowed ever
|
||||
// rate based torque limit + stay within actually applied
|
||||
// packet is sent at 100hz, so this limit is 1000/sec
|
||||
const int TOYOTA_MAX_RATE_UP = 10; // ramp up slow
|
||||
const int TOYOTA_MAX_RATE_DOWN = 25; // ramp down fast
|
||||
const int TOYOTA_MAX_TORQUE_ERROR = 350; // max torque cmd in excess of torque motor
|
||||
const int TOYOTA_MAX_RATE_DOWN = 44; // ramp down fast
|
||||
const int TOYOTA_MAX_TORQUE_ERROR = 500; // max torque cmd in excess of torque motor
|
||||
|
||||
// real time torque limit to prevent controls spamming
|
||||
// the real time limit is 1500/sec
|
||||
@@ -13,7 +13,7 @@ const int TOYOTA_MAX_RT_DELTA = 375; // max delta torque allowed for real t
|
||||
const uint32_t TOYOTA_RT_INTERVAL = 250000; // 250ms between real time checks
|
||||
|
||||
// longitudinal limits
|
||||
const int TOYOTA_MAX_ACCEL = 1500; // 1.5 m/s2
|
||||
const int TOYOTA_MAX_ACCEL = 4000; // 1.5 m/s2
|
||||
const int TOYOTA_MIN_ACCEL = -3000; // 3.0 m/s2
|
||||
|
||||
const int TOYOTA_GAS_INTERCEPTOR_THRESHOLD = 475; // ratio between offset and gain from dbc file
|
||||
@@ -85,7 +85,7 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
// 5th bit is CRUISE_ACTIVE
|
||||
int cruise_engaged = GET_BYTE(to_push, 0) & 0x20;
|
||||
if (!cruise_engaged) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
if (cruise_engaged && !toyota_cruise_engaged_last) {
|
||||
controls_allowed = 1;
|
||||
@@ -99,7 +99,7 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
int gas_interceptor = GET_INTERCEPTOR(to_push);
|
||||
if ((gas_interceptor > TOYOTA_GAS_INTERCEPTOR_THRESHOLD) &&
|
||||
(gas_interceptor_prev <= TOYOTA_GAS_INTERCEPTOR_THRESHOLD)) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
gas_interceptor_prev = gas_interceptor;
|
||||
}
|
||||
@@ -108,7 +108,7 @@ static int toyota_rx_hook(CAN_FIFOMailBox_TypeDef *to_push) {
|
||||
if (addr == 0x2C1) {
|
||||
int gas = GET_BYTE(to_push, 6) & 0xFF;
|
||||
if ((gas > 0) && (toyota_gas_prev == 0) && !gas_interceptor_detected) {
|
||||
controls_allowed = 0;
|
||||
controls_allowed = 1;
|
||||
}
|
||||
toyota_gas_prev = gas;
|
||||
}
|
||||
|
||||
+1643
-710
File diff suppressed because it is too large
Load Diff
+1775
-142
File diff suppressed because it is too large
Load Diff
Executable
+6
@@ -0,0 +1,6 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
|
||||
export HOME=/data/data/com.termux/files/home
|
||||
export PATH=/usr/local/bin:/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/sbin:/data/data/com.termux/files/usr/bin/applets:/bin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin:/data/data/com.termux/files/usr/bin/git
|
||||
cd /data/openpilot && git reset --hard @{u} && git clean -xdf && git pull && reboot
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 28 KiB |
@@ -1,5 +1,11 @@
|
||||
Import('env', 'common', 'messaging')
|
||||
|
||||
# dragonpilot - Add read DragonBTG value
|
||||
if FindFile('DragonBTG', '/data/params/d') != None:
|
||||
with open('/data/params/d/DragonBTG') as f:
|
||||
if (int(f.read())) == 1:
|
||||
env.Append(CCFLAGS='-DDragonBTG')
|
||||
|
||||
env.Program('boardd.cc', LIBS=['usb-1.0', common, messaging, 'pthread', 'zmq', 'capnp', 'kj'])
|
||||
env.Library('libcan_list_to_can_capnp', ['can_list_to_can_capnp.cc'])
|
||||
|
||||
|
||||
@@ -84,6 +84,7 @@ void pigeon_init();
|
||||
void *pigeon_thread(void *crap);
|
||||
|
||||
void *safety_setter_thread(void *s) {
|
||||
#ifndef DragonBTG
|
||||
// diagnostic only is the default, needed for VIN query
|
||||
pthread_mutex_lock(&usb_lock);
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::ELM327), 0, NULL, 0, TIMEOUT);
|
||||
@@ -109,6 +110,7 @@ void *safety_setter_thread(void *s) {
|
||||
pthread_mutex_lock(&usb_lock);
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
|
||||
pthread_mutex_unlock(&usb_lock);
|
||||
#endif
|
||||
|
||||
char *value;
|
||||
size_t value_sz = 0;
|
||||
@@ -372,13 +374,14 @@ void can_health(PubSocket *publisher) {
|
||||
}
|
||||
|
||||
voltage_f = VOLTAGE_K * (health.voltage / 1000.0) + (1.0 - VOLTAGE_K) * voltage_f; // LPF
|
||||
|
||||
#ifndef DragonBTG
|
||||
// Make sure CAN buses are live: safety_setter_thread does not work if Panda CAN are silent and there is only one other CAN node
|
||||
if (health.safety_model == (uint8_t)(cereal::CarParams::SafetyModel::SILENT)) {
|
||||
pthread_mutex_lock(&usb_lock);
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
|
||||
pthread_mutex_unlock(&usb_lock);
|
||||
}
|
||||
#endif
|
||||
|
||||
bool ignition = ((health.ignition_line != 0) || (health.ignition_can != 0));
|
||||
|
||||
@@ -416,12 +419,14 @@ void can_health(PubSocket *publisher) {
|
||||
libusb_control_transfer(dev_handle, 0xc0, 0xe7, 1, 0, NULL, 0, TIMEOUT);
|
||||
pthread_mutex_unlock(&usb_lock);
|
||||
}
|
||||
#ifndef DragonBTG
|
||||
// set safety mode to NO_OUTPUT when car is off. ELM327 is an alternative if we want to leverage athenad/connect
|
||||
if (!ignition && (health.safety_model != (uint8_t)(cereal::CarParams::SafetyModel::NO_OUTPUT))) {
|
||||
pthread_mutex_lock(&usb_lock);
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdc, (uint16_t)(cereal::CarParams::SafetyModel::NO_OUTPUT), 0, NULL, 0, TIMEOUT);
|
||||
pthread_mutex_unlock(&usb_lock);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// clear VIN, CarParams, and set new safety on car start
|
||||
@@ -841,6 +846,11 @@ void *pigeon_thread(void *crap) {
|
||||
if (pigeon_needs_init) {
|
||||
pigeon_needs_init = false;
|
||||
pigeon_init();
|
||||
#ifdef DragonBTG
|
||||
pthread_mutex_lock(&usb_lock);
|
||||
libusb_control_transfer(dev_handle, 0x40, 0xdc, 2, 100, NULL, 0, TIMEOUT);
|
||||
pthread_mutex_unlock(&usb_lock);
|
||||
#endif
|
||||
}
|
||||
int alen = 0;
|
||||
while (alen < 0xfc0) {
|
||||
@@ -875,6 +885,9 @@ void *pigeon_thread(void *crap) {
|
||||
int main() {
|
||||
int err;
|
||||
LOGW("starting boardd");
|
||||
#ifdef DragonBTG
|
||||
LOGW("boardd is running in DragonBTG mode");
|
||||
#endif
|
||||
|
||||
// set process priority
|
||||
err = set_realtime_priority(4);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import os
|
||||
from common.params import Params
|
||||
from common.params import Params, put_nonblocking
|
||||
from common.basedir import BASEDIR
|
||||
from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_known_cars
|
||||
from selfdrive.car.vin import get_vin, VIN_UNKNOWN
|
||||
@@ -7,6 +7,10 @@ from selfdrive.car.fw_versions import get_fw_versions, match_fw_to_car
|
||||
from selfdrive.swaglog import cloudlog
|
||||
import cereal.messaging as messaging
|
||||
from selfdrive.car import gen_empty_fingerprint
|
||||
import pickle
|
||||
import requests
|
||||
import threading
|
||||
import selfdrive.crash as crash
|
||||
|
||||
from cereal import car
|
||||
|
||||
@@ -63,6 +67,45 @@ def only_toyota_left(candidate_cars):
|
||||
|
||||
# **** for use live only ****
|
||||
def fingerprint(logcan, sendcan, has_relay):
|
||||
params = Params()
|
||||
dragon_cache_car = params.get("DragonCacheCar", encoding='utf8')
|
||||
dragon_car_fingerprint = None
|
||||
dragon_finger = None
|
||||
dragon_vin = VIN_UNKNOWN
|
||||
dragon_car_fw = []
|
||||
dragon_source = car.CarParams.FingerprintSource.can
|
||||
|
||||
dragon_has_cache = False
|
||||
try:
|
||||
if dragon_cache_car == "1":
|
||||
cached_source = params.get("DragonCachedSource")
|
||||
|
||||
dragon_source = car.CarParams.FingerprintSource.can if cached_source == b'' else pickle.loads(cached_source)
|
||||
|
||||
cached_finger = params.get("DragonCachedFP")
|
||||
cached_model = params.get("DragonCachedModel")
|
||||
if cached_finger != "" and cached_model != "":
|
||||
dragon_car_fingerprint = pickle.loads(cached_model)
|
||||
dragon_finger = pickle.loads(cached_finger)
|
||||
|
||||
# car_fw and vin are only available if relay is used.
|
||||
if dragon_source == car.CarParams.FingerprintSource.fw:
|
||||
# load car_fw
|
||||
cached_car_fw = params.get("DragonCachedCarFW")
|
||||
if cached_car_fw != "":
|
||||
dragon_car_fw = pickle.loads(cached_car_fw)
|
||||
|
||||
# load vin
|
||||
cached_vin = params.get("DragonCachedVIN")
|
||||
if cached_vin != "":
|
||||
dragon_vin = pickle.loads(cached_vin)
|
||||
|
||||
# set relay to false if cache is right
|
||||
has_relay = False
|
||||
dragon_has_cache = True
|
||||
except EOFError as e:
|
||||
pass # dragon_has_cache = False
|
||||
|
||||
if has_relay:
|
||||
# Vin query only reliably works thorugh OBDII
|
||||
bus = 1
|
||||
@@ -92,6 +135,10 @@ def fingerprint(logcan, sendcan, has_relay):
|
||||
car_fingerprint = None
|
||||
done = False
|
||||
|
||||
# dp, skip loop if cach is on
|
||||
if dragon_has_cache:
|
||||
done = True
|
||||
|
||||
while not done:
|
||||
a = messaging.get_one_can(logcan)
|
||||
|
||||
@@ -126,12 +173,34 @@ def fingerprint(logcan, sendcan, has_relay):
|
||||
|
||||
frame += 1
|
||||
|
||||
source = car.CarParams.FingerprintSource.can
|
||||
if dragon_has_cache:
|
||||
car_fingerprint = dragon_car_fingerprint
|
||||
finger = dragon_finger
|
||||
vin = dragon_vin
|
||||
car_fw = dragon_car_fw
|
||||
source = dragon_source
|
||||
|
||||
# If FW query returns exactly 1 candidate, use it
|
||||
if len(fw_candidates) == 1:
|
||||
car_fingerprint = list(fw_candidates)[0]
|
||||
source = car.CarParams.FingerprintSource.fw
|
||||
else:
|
||||
source = car.CarParams.FingerprintSource.can
|
||||
|
||||
# If FW query returns exactly 1 candidate, use it
|
||||
if len(fw_candidates) == 1:
|
||||
car_fingerprint = list(fw_candidates)[0]
|
||||
source = car.CarParams.FingerprintSource.fw
|
||||
|
||||
# dp, store values if cache is off
|
||||
put_nonblocking("DragonCachedModel", pickle.dumps(car_fingerprint))
|
||||
put_nonblocking("DragonCachedFP", pickle.dumps(finger))
|
||||
put_nonblocking("DragonCachedVIN", pickle.dumps(vin))
|
||||
put_nonblocking("DragonCachedCarFW", pickle.dumps(car_fw))
|
||||
put_nonblocking("DragonCachedSource", pickle.dumps(source))
|
||||
# these are for display only
|
||||
put_nonblocking("DragonCarModel", car_fingerprint)
|
||||
|
||||
fixed_fingerprint = os.environ.get('FINGERPRINT', "")
|
||||
if len(fixed_fingerprint):
|
||||
car_fingerprint = fixed_fingerprint
|
||||
source = car.CarParams.FingerprintSource.fixed
|
||||
|
||||
fixed_fingerprint = os.environ.get('FINGERPRINT', "")
|
||||
if len(fixed_fingerprint):
|
||||
@@ -141,14 +210,40 @@ def fingerprint(logcan, sendcan, has_relay):
|
||||
cloudlog.warning("fingerprinted %s", car_fingerprint)
|
||||
return car_fingerprint, finger, vin, car_fw, source
|
||||
|
||||
def is_online(timeout=5):
|
||||
try:
|
||||
requests.get("https://sentry.io", timeout=timeout)
|
||||
return True
|
||||
except:
|
||||
return False
|
||||
|
||||
def log_fingerprinted(candidate):
|
||||
while True:
|
||||
crash.capture_warning("fingerprinted %s" % candidate)
|
||||
break
|
||||
|
||||
def log_unmatched_fingerprint(fingerprints, fw):
|
||||
while True:
|
||||
crash.capture_warning("car doesn't match any fingerprints: %s" % fingerprints)
|
||||
crash.capture_warning("car doesn't match any fw: %s" % fw)
|
||||
break
|
||||
|
||||
def get_car(logcan, sendcan, has_relay=False):
|
||||
candidate, fingerprints, vin, car_fw, source = fingerprint(logcan, sendcan, has_relay)
|
||||
|
||||
if candidate is None:
|
||||
if is_online():
|
||||
y = threading.Thread(target=log_unmatched_fingerprint, args=(fingerprints,car_fw,))
|
||||
y.start()
|
||||
|
||||
cloudlog.warning("car doesn't match any fingerprints: %r", fingerprints)
|
||||
cloudlog.warning("car doesn't match any fw: %s" % car_fw)
|
||||
candidate = "mock"
|
||||
|
||||
if is_online():
|
||||
x = threading.Thread(target=log_fingerprinted, args=(candidate,))
|
||||
x.start()
|
||||
|
||||
CarInterface, CarController = interfaces[candidate]
|
||||
car_params = CarInterface.get_params(candidate, fingerprints, has_relay, car_fw)
|
||||
car_params.carVin = vin
|
||||
|
||||
@@ -7,6 +7,9 @@ from selfdrive.car import create_gas_command
|
||||
from selfdrive.car.honda import hondacan
|
||||
from selfdrive.car.honda.values import CruiseButtons, CAR, VISUAL_HUD
|
||||
from opendbc.can.packer import CANPacker
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
|
||||
@@ -72,7 +75,7 @@ def process_hud_alert(hud_alert):
|
||||
|
||||
HUDData = namedtuple("HUDData",
|
||||
["pcm_accel", "v_cruise", "car",
|
||||
"lanes", "fcw", "acc_alert", "steer_required"])
|
||||
"lanes", "fcw", "acc_alert", "steer_required", "dashed_lanes"])
|
||||
|
||||
|
||||
class CarController():
|
||||
@@ -90,9 +93,22 @@ class CarController():
|
||||
print("EPS FW MODIFIED!")
|
||||
self.eps_modified = True
|
||||
|
||||
# dragonpilot
|
||||
self.turning_signal_timer = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
def update(self, enabled, CS, frame, actuators, \
|
||||
pcm_speed, pcm_override, pcm_cancel_cmd, pcm_accel, \
|
||||
hud_v_cruise, hud_show_lanes, hud_show_car, hud_alert):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
if frame % 500 == 0:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
|
||||
# *** apply brake hysteresis ***
|
||||
brake, self.braking, self.brake_steady = actuator_hystereses(actuators.brake, self.braking, self.brake_steady, CS.v_ego, CS.CP.carFingerprint)
|
||||
@@ -122,7 +138,7 @@ class CarController():
|
||||
fcw_display, steer_required, acc_alert = process_hud_alert(hud_alert)
|
||||
|
||||
hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_car,
|
||||
hud_lanes, fcw_display, acc_alert, steer_required)
|
||||
hud_lanes, fcw_display, acc_alert, steer_required, CS.lkMode)
|
||||
|
||||
# **** process the car messages ****
|
||||
|
||||
@@ -150,11 +166,28 @@ class CarController():
|
||||
elif apply_steer < -0xA00:
|
||||
apply_steer = (apply_steer + 0xA00) / 2 - 0xA00
|
||||
|
||||
lkas_active = enabled and not CS.steer_not_allowed
|
||||
lkas_active = enabled and not CS.steer_not_allowed and CS.lkMode
|
||||
|
||||
# Send CAN commands.
|
||||
can_sends = []
|
||||
|
||||
# dragonpilot
|
||||
if enabled:
|
||||
if self.dragon_enable_steering_on_signal:
|
||||
if CS.left_blinker_on == 0 and CS.right_blinker_on == 0:
|
||||
self.turning_signal_timer = 0
|
||||
else:
|
||||
self.turning_signal_timer = 100
|
||||
|
||||
if self.turning_signal_timer > 0:
|
||||
self.turning_signal_timer -= 1
|
||||
lkas_active = False
|
||||
else:
|
||||
self.turning_signal_timer = 0
|
||||
|
||||
if not self.dragon_lat_ctrl:
|
||||
lkas_active = False
|
||||
|
||||
# Send steering command.
|
||||
idx = frame % 4
|
||||
can_sends.append(hondacan.create_steering_control(self.packer, apply_steer,
|
||||
|
||||
@@ -146,6 +146,8 @@ def get_can_signals(CP):
|
||||
signals.append(("INTERCEPTOR_GAS2", "GAS_SENSOR", 0))
|
||||
checks.append(("GAS_SENSOR", 50))
|
||||
|
||||
checks = []
|
||||
|
||||
return signals, checks
|
||||
|
||||
|
||||
@@ -195,6 +197,9 @@ class CarState(CarStateBase):
|
||||
self.cruise_mode = 0
|
||||
self.stopped = 0
|
||||
|
||||
# dragonpilot
|
||||
self.lkMode = True
|
||||
|
||||
def update(self, cp, cp_cam):
|
||||
|
||||
# car params
|
||||
@@ -257,6 +262,13 @@ class CarState(CarStateBase):
|
||||
self.angle_steers = cp.vl["STEERING_SENSORS"]['STEER_ANGLE']
|
||||
self.angle_steers_rate = cp.vl["STEERING_SENSORS"]['STEER_ANGLE_RATE']
|
||||
|
||||
# when user presses LKAS button on steering wheel
|
||||
if self.cruise_setting == 1:
|
||||
if cp.vl["SCM_BUTTONS"]["CRUISE_SETTING"] == 0:
|
||||
if self.lkMode:
|
||||
self.lkMode = False
|
||||
else:
|
||||
self.lkMode = True
|
||||
self.cruise_setting = cp.vl["SCM_BUTTONS"]['CRUISE_SETTING']
|
||||
self.cruise_buttons = cp.vl["SCM_BUTTONS"]['CRUISE_BUTTONS']
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ def create_ui_commands(packer, pcm_speed, hud, car_fingerprint, is_metric, idx,
|
||||
'STEERING_REQUIRED': hud.steer_required,
|
||||
'SOLID_LANES': hud.lanes,
|
||||
'BEEP': 0,
|
||||
'DASHED_LANES': hud.dashed_lanes,
|
||||
}
|
||||
commands.append(packer.make_can_msg('LKAS_HUD', bus_lkas, lkas_hud_values, idx))
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import numpy as np
|
||||
from cereal import car
|
||||
from common.numpy_fast import clip, interp
|
||||
from common.realtime import DT_CTRL
|
||||
from common.realtime import DT_CTRL, sec_since_boot
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.controls.lib.drive_helpers import create_event, EventTypes as ET, get_events
|
||||
@@ -12,6 +12,9 @@ from selfdrive.car.honda.values import CruiseButtons, CAR, HONDA_BOSCH, Ecu, ECU
|
||||
from selfdrive.car import STD_CARGO_KG, CivicParams, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint
|
||||
from selfdrive.controls.lib.planner import _A_CRUISE_MAX_V_FOLLOWING
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
A_ACC_MAX = max(_A_CRUISE_MAX_V_FOLLOWING)
|
||||
|
||||
@@ -98,6 +101,13 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
self.compute_gb = compute_gb_honda
|
||||
|
||||
# dragonpilot
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_allow_gas = False
|
||||
self.ts_last_check = 0.
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
@staticmethod
|
||||
def calc_accel_override(a_ego, a_target, v_ego, v_target):
|
||||
|
||||
@@ -376,6 +386,17 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else True
|
||||
self.dragon_allow_gas = True if params.get("DragonAllowGas", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
self.ts_last_check = ts
|
||||
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
@@ -490,7 +511,11 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# events
|
||||
events = []
|
||||
if self.CS.steer_error:
|
||||
if not self.CS.lkMode or not self.dragon_lat_ctrl:
|
||||
events.append(create_event('manualSteeringRequired', [ET.WARNING]))
|
||||
elif self.CS.lkMode and (self.CS.left_blinker_on or self.CS.right_blinker_on) and self.dragon_enable_steering_on_signal:
|
||||
events.append(create_event('manualSteeringRequiredBlinkersOn', [ET.WARNING]))
|
||||
elif self.CS.steer_error:
|
||||
events.append(create_event('steerUnavailable', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE, ET.PERMANENT]))
|
||||
elif self.CS.steer_warning:
|
||||
events.append(create_event('steerTempUnavailable', [ET.WARNING]))
|
||||
@@ -516,21 +541,26 @@ class CarInterface(CarInterfaceBase):
|
||||
if self.CP.enableCruise and ret.vEgo < self.CP.minEnableSpeed:
|
||||
events.append(create_event('speedTooLow', [ET.NO_ENTRY]))
|
||||
|
||||
# disable on pedals rising edge or when brake is pressed and speed isn't zero
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
# DragonAllowGas
|
||||
if not self.dragon_allow_gas:
|
||||
# disable on pedals rising edge or when brake is pressed and speed isn't zero
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
else:
|
||||
if ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
# it can happen that car cruise disables while comma system is enabled: need to
|
||||
# keep braking if needed or if the speed is very low
|
||||
if self.CP.enableCruise and not ret.cruiseState.enabled and (c.actuators.brake <= 0. or not self.CP.openpilotLongitudinalControl):
|
||||
# non loud alert if cruise disbales below 25mph as expected (+ a little margin)
|
||||
if ret.vEgo < self.CP.minEnableSpeed + 2.:
|
||||
events.append(create_event('speedTooLow', [ET.IMMEDIATE_DISABLE]))
|
||||
else:
|
||||
# events.append(create_event('speedTooLow', [ET.IMMEDIATE_DISABLE]))
|
||||
# else:
|
||||
events.append(create_event("cruiseDisabled", [ET.IMMEDIATE_DISABLE]))
|
||||
if self.CS.CP.minEnableSpeed > 0 and ret.vEgo < 0.001:
|
||||
events.append(create_event('manualRestart', [ET.WARNING]))
|
||||
|
||||
@@ -51,6 +51,13 @@ FINGERPRINTS = {
|
||||
}],
|
||||
CAR.ACCORDH: [{
|
||||
148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 387: 8, 388: 8, 399: 7, 419: 8, 420: 8, 427: 3, 432: 7, 441: 5, 450: 8, 464: 8, 477: 8, 479: 8, 495: 8, 525: 8, 545: 6, 662: 4, 773: 7, 777: 8, 780: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 927: 8, 929: 8, 1302: 8, 1600: 5, 1601: 8, 1652: 8
|
||||
},
|
||||
{
|
||||
148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 387: 8, 388: 8, 399: 7, 419: 8, 420: 8, 427: 3, 432: 7, 441: 5, 450: 8, 464: 8, 477: 8, 479: 8, 495: 8, 525: 8, 545: 6, 662: 4, 773: 7, 777: 8, 780: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 927: 8, 929: 8, 1302: 8, 1416: 5, 1600: 5, 1601: 8, 1652: 8
|
||||
},
|
||||
{
|
||||
# Honda Inspire Hybrid
|
||||
148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 387: 8, 388: 8, 399: 7, 408: 6, 419: 8, 420: 8, 427: 3, 432: 7, 441: 5, 450: 8, 464: 8, 475: 8, 477: 8, 479: 8, 481: 8, 495: 8, 525: 8, 545: 6, 662: 4, 773: 7, 777: 8, 780: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 927: 8, 929: 8, 1302: 8, 1416: 5, 1600: 5, 1601: 8, 1652: 8
|
||||
}],
|
||||
CAR.ACURA_ILX: [{
|
||||
57: 3, 145: 8, 228: 5, 304: 8, 316: 8, 342: 6, 344: 8, 380: 8, 398: 3, 399: 7, 419: 8, 420: 8, 422: 8, 428: 8, 432: 7, 464: 8, 476: 4, 490: 8, 506: 8, 512: 6, 513: 6, 542: 7, 545: 4, 597: 8, 660: 8, 773: 7, 777: 8, 780: 8, 800: 8, 804: 8, 808: 8, 819: 7, 821: 5, 829: 5, 882: 2, 884: 7, 887: 8, 888: 8, 892: 8, 923: 2, 929: 4, 983: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1030: 5, 1034: 5, 1036: 8, 1039: 8, 1057: 5, 1064: 7, 1108: 8, 1365: 5,
|
||||
@@ -66,6 +73,10 @@ FINGERPRINTS = {
|
||||
# 2017 Civic Hatchback EX, 2019 Civic Sedan Touring Canadian, and 2018 Civic Hatchback Executive Premium 1.0L CVT European
|
||||
57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 427: 3, 428: 8, 432: 7, 441: 5, 450: 8, 460: 3, 464: 8, 470: 2, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 506: 8, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 892: 8, 927: 8, 929: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1108: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1625: 5, 1629: 5, 1633: 8,
|
||||
},
|
||||
# Manual CIVIC from AlexNoop
|
||||
{
|
||||
57: 3, 148: 8, 228: 5, 274: 3, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 420: 8, 427: 3, 428: 8, 432: 7, 441: 5, 450: 8, 460: 3, 464: 8, 470: 2, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 506: 8, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 829: 5, 862: 8, 884: 8, 891: 8, 892: 8, 927: 8, 929: 8, 985: 3, 1024: 5, 1029: 8, 1036: 8, 1108: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1625: 5, 1633: 8,
|
||||
},
|
||||
# 2017 Civic Hatchback LX
|
||||
{
|
||||
57: 3, 148: 8, 228: 5, 304: 8, 330: 8, 344: 8, 380: 8, 399: 7, 401: 8, 420: 8, 423: 2, 427: 3, 428: 8, 432: 7, 441: 5, 450: 8, 464: 8, 470: 2, 476: 7, 477: 8, 479: 8, 490: 8, 493: 5, 495: 8, 506: 8, 545: 6, 597: 8, 662: 4, 773: 7, 777: 8, 780: 8, 795: 8, 800: 8, 804: 8, 806: 8, 808: 8, 815: 8, 825: 4, 829: 5, 846: 8, 862: 8, 881: 8, 882: 4, 884: 8, 888: 8, 891: 8, 892: 8, 918: 7, 927: 8, 929: 8, 983: 8, 985: 3, 1024: 5, 1027: 5, 1029: 8, 1036: 8, 1039: 8, 1064: 7, 1092: 1, 1108: 8, 1125: 8, 1127: 2, 1296: 8, 1302: 8, 1322: 5, 1361: 5, 1365: 5, 1424: 5, 1600: 5, 1601: 8, 1633: 8
|
||||
@@ -96,6 +107,10 @@ FINGERPRINTS = {
|
||||
}],
|
||||
CAR.ODYSSEY_CHN: [{
|
||||
57: 3, 145: 8, 316: 8, 342: 6, 344: 8, 380: 8, 398: 3, 399: 7, 401: 8, 404: 4, 411: 5, 420: 8, 422: 8, 423: 2, 426: 8, 432: 7, 450: 8, 464: 8, 490: 8, 506: 8, 507: 1, 512: 6, 513: 6, 597: 8, 610: 8, 611: 8, 612: 8, 617: 8, 660: 8, 661: 4, 773: 7, 780: 8, 804: 8, 808: 8, 829: 5, 862: 8, 884: 7, 892: 8, 923: 2, 929: 8, 1030: 5, 1137: 8, 1302: 8, 1348: 5, 1361: 5, 1365: 5, 1600: 5, 1601: 8, 1639: 8
|
||||
},
|
||||
# Odyssey from Shell
|
||||
{
|
||||
57: 3, 145: 8, 316: 8, 342: 6, 344: 8, 380: 8, 398: 3, 399: 7, 401: 8, 408: 6, 411: 5, 415: 6, 420: 8, 422: 8, 423: 2, 426: 8, 432: 7, 450: 8, 464: 8, 490: 8, 507: 1, 597: 8, 610: 8, 611: 8, 612: 8, 617: 8, 660: 8, 661: 4, 773: 7, 804: 8, 808: 8, 884: 7, 892: 8, 923: 2, 929: 8, 1030: 5, 1137: 8, 1302: 8, 1348: 5, 1361: 5, 1365: 5, 1639: 8
|
||||
}],
|
||||
# 2017 Pilot Touring AND 2016 Pilot EX-L w/ Added Comma Pedal Support (512L & 513L)
|
||||
CAR.PILOT: [{
|
||||
@@ -296,6 +311,7 @@ FW_VERSIONS = {
|
||||
b'37805-5AN-LJ20\x00\x00',
|
||||
b'37805-5AZ-E850\x00\x00',
|
||||
b'37805-5BB-L640\x00\x00',
|
||||
b'37805-5AN-E410\x00\x00', # AlexNoop's Manual CIVIC_BOSCH
|
||||
],
|
||||
(Ecu.unknown, 0x18da1ef1, None): [
|
||||
b'28101-5CG-A920\x00\x00',
|
||||
|
||||
@@ -2,7 +2,9 @@ from selfdrive.car import apply_std_steer_torque_limits
|
||||
from selfdrive.car.hyundai.hyundaican import create_lkas11, create_clu11
|
||||
from selfdrive.car.hyundai.values import Buttons, SteerLimitParams
|
||||
from opendbc.can.packer import CANPacker
|
||||
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
class CarController():
|
||||
def __init__(self, dbc_name, car_fingerprint):
|
||||
@@ -14,7 +16,21 @@ class CarController():
|
||||
self.packer = CANPacker(dbc_name)
|
||||
self.steer_rate_limited = False
|
||||
|
||||
def update(self, enabled, CS, actuators, pcm_cancel_cmd, hud_alert):
|
||||
# dragonpilot
|
||||
self.turning_signal_timer = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, hud_alert):
|
||||
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
if frame % 500 == 0:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
|
||||
### Steering Torque
|
||||
new_steer = actuators.steer * SteerLimitParams.STEER_MAX
|
||||
@@ -30,6 +46,23 @@ class CarController():
|
||||
|
||||
can_sends = []
|
||||
|
||||
# dragonpilot
|
||||
if enabled:
|
||||
if self.dragon_enable_steering_on_signal:
|
||||
if CS.left_blinker_on == 0 and CS.right_blinker_on == 0:
|
||||
self.turning_signal_timer = 0
|
||||
else:
|
||||
self.turning_signal_timer = 100
|
||||
|
||||
if self.turning_signal_timer > 0:
|
||||
self.turning_signal_timer -= 1
|
||||
steer_req = 0
|
||||
else:
|
||||
self.turning_signal_timer = 0
|
||||
|
||||
if not self.dragon_lat_ctrl:
|
||||
steer_req = 0
|
||||
|
||||
self.lkas11_cnt = self.cnt % 0x10
|
||||
self.clu11_cnt = self.cnt % 0x10
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python3
|
||||
from cereal import car
|
||||
from common.realtime import sec_since_boot
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.controls.lib.drive_helpers import EventTypes as ET, create_event
|
||||
from selfdrive.controls.lib.vehicle_model import VehicleModel
|
||||
@@ -7,6 +8,9 @@ from selfdrive.car.hyundai.carstate import CarState, get_can_parser, get_camera_
|
||||
from selfdrive.car.hyundai.values import Ecu, ECU_FINGERPRINT, CAR, get_hud_alerts, FEATURES, FINGERPRINTS
|
||||
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
GearShifter = car.CarState.GearShifter
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
@@ -33,6 +37,14 @@ class CarInterface(CarInterfaceBase):
|
||||
if CarController is not None:
|
||||
self.CC = CarController(self.cp.dbc_name, CP.carFingerprint)
|
||||
|
||||
# dragonpilot
|
||||
self.frame = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_allow_gas = False
|
||||
self.ts_last_check = 0.
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
@staticmethod
|
||||
def compute_gb(accel, speed):
|
||||
return float(accel) / 3.0
|
||||
@@ -150,6 +162,17 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else True
|
||||
self.dragon_allow_gas = True if params.get("DragonAllowGas", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
self.ts_last_check = ts
|
||||
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
@@ -245,7 +268,11 @@ class CarInterface(CarInterfaceBase):
|
||||
events.append(create_event('wrongCarMode', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
if ret.gearShifter == GearShifter.reverse:
|
||||
events.append(create_event('reverseGear', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
if self.CS.steer_error:
|
||||
if not self.dragon_lat_ctrl:
|
||||
events.append(create_event('manualSteeringRequired', [ET.WARNING]))
|
||||
elif (self.CS.left_blinker_on or self.CS.right_blinker_on) and self.dragon_enable_steering_on_signal:
|
||||
events.append(create_event('manualSteeringRequiredBlinkersOn', [ET.WARNING]))
|
||||
elif self.CS.steer_error:
|
||||
events.append(create_event('steerTempUnavailable', [ET.NO_ENTRY, ET.WARNING]))
|
||||
|
||||
if ret.cruiseState.enabled and not self.cruise_enabled_prev:
|
||||
@@ -253,13 +280,17 @@ class CarInterface(CarInterfaceBase):
|
||||
elif not ret.cruiseState.enabled:
|
||||
events.append(create_event('pcmDisable', [ET.USER_DISABLE]))
|
||||
|
||||
# disable on pedals rising edge or when brake is pressed and speed isn't zero
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgoRaw > 0.1)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
# DragonAllowGas
|
||||
if not self.dragon_allow_gas:
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgoRaw > 0.1)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
else:
|
||||
if ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.1):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
if self.low_speed_alert:
|
||||
events.append(create_event('belowSteerSpeed', [ET.WARNING]))
|
||||
@@ -276,7 +307,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
hud_alert = get_hud_alerts(c.hudControl.visualAlert)
|
||||
|
||||
can_sends = self.CC.update(c.enabled, self.CS, c.actuators,
|
||||
can_sends = self.CC.update(c.enabled, self.CS, self.frame, c.actuators,
|
||||
c.cruiseControl.cancel, hud_alert)
|
||||
|
||||
self.frame += 1
|
||||
return can_sends
|
||||
|
||||
@@ -3,7 +3,9 @@ from selfdrive.car import apply_std_steer_torque_limits
|
||||
from selfdrive.car.subaru import subarucan
|
||||
from selfdrive.car.subaru.values import DBC
|
||||
from opendbc.can.packer import CANPacker
|
||||
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
class CarControllerParams():
|
||||
def __init__(self, car_fingerprint):
|
||||
@@ -32,9 +34,23 @@ class CarController():
|
||||
self.params = CarControllerParams(car_fingerprint)
|
||||
self.packer = CANPacker(DBC[car_fingerprint]['pt'])
|
||||
|
||||
# dragonpilot
|
||||
self.turning_signal_timer = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, visual_alert, left_line, right_line):
|
||||
""" Controls thread """
|
||||
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
if frame % 500 == 0:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
|
||||
P = self.params
|
||||
|
||||
# Send CAN commands.
|
||||
@@ -58,6 +74,23 @@ class CarController():
|
||||
if not lkas_enabled:
|
||||
apply_steer = 0
|
||||
|
||||
# dragonpilot
|
||||
if enabled:
|
||||
if self.dragon_enable_steering_on_signal:
|
||||
if CS.left_blinker_on == 0 and CS.right_blinker_on == 0:
|
||||
self.turning_signal_timer = 0
|
||||
else:
|
||||
self.turning_signal_timer = 100
|
||||
|
||||
if self.turning_signal_timer > 0:
|
||||
self.turning_signal_timer -= 1
|
||||
apply_steer = 0
|
||||
else:
|
||||
self.turning_signal_timer = 0
|
||||
|
||||
if not self.dragon_lat_ctrl:
|
||||
apply_steer = 0
|
||||
|
||||
can_sends.append(subarucan.create_steering_control(self.packer, CS.CP.carFingerprint, apply_steer, frame, P.STEER_STEP))
|
||||
|
||||
self.apply_steer_last = apply_steer
|
||||
|
||||
@@ -7,6 +7,10 @@ from selfdrive.car.subaru.values import CAR
|
||||
from selfdrive.car.subaru.carstate import CarState, get_powertrain_can_parser, get_camera_can_parser
|
||||
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, gen_empty_fingerprint
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from common.realtime import sec_since_boot
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
|
||||
@@ -30,6 +34,14 @@ class CarInterface(CarInterfaceBase):
|
||||
if CarController is not None:
|
||||
self.CC = CarController(CP.carFingerprint)
|
||||
|
||||
# dragonpilot
|
||||
self.frame = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_allow_gas = False
|
||||
self.ts_last_check = 0.
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
@staticmethod
|
||||
def compute_gb(accel, speed):
|
||||
return float(accel) / 4.0
|
||||
@@ -95,6 +107,17 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else True
|
||||
self.dragon_allow_gas = True if params.get("DragonAllowGas", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
self.ts_last_check = ts
|
||||
|
||||
self.pt_cp.update_strings(can_strings)
|
||||
self.cam_cp.update_strings(can_strings)
|
||||
|
||||
@@ -166,17 +189,24 @@ class CarInterface(CarInterfaceBase):
|
||||
if ret.doorOpen:
|
||||
events.append(create_event('doorOpen', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
|
||||
|
||||
if not self.dragon_lat_ctrl:
|
||||
events.append(create_event('manualSteeringRequired', [ET.WARNING]))
|
||||
elif (self.CS.left_blinker_on or self.CS.right_blinker_on) and self.dragon_enable_steering_on_signal:
|
||||
events.append(create_event('manualSteeringRequiredBlinkersOn', [ET.WARNING]))
|
||||
|
||||
if self.CS.acc_active and not self.acc_active_prev:
|
||||
events.append(create_event('pcmEnable', [ET.ENABLE]))
|
||||
if not self.CS.acc_active:
|
||||
events.append(create_event('pcmDisable', [ET.USER_DISABLE]))
|
||||
|
||||
# disable on gas pedal rising edge
|
||||
if (ret.gasPressed and not self.gas_pressed_prev):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
# DragonAllowGas
|
||||
if not self.dragon_allow_gas:
|
||||
# disable on gas pedal rising edge
|
||||
if (ret.gasPressed and not self.gas_pressed_prev):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
|
||||
ret.events = events
|
||||
|
||||
|
||||
@@ -6,6 +6,9 @@ from selfdrive.car.toyota.toyotacan import create_steer_command, create_ui_comma
|
||||
create_acc_cancel_command, create_fcw_command
|
||||
from selfdrive.car.toyota.values import Ecu, CAR, STATIC_MSGS, SteerLimitParams
|
||||
from opendbc.can.packer import CANPacker
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
VisualAlert = car.CarControl.HUDControl.VisualAlert
|
||||
|
||||
@@ -101,9 +104,27 @@ class CarController():
|
||||
|
||||
self.packer = CANPacker(dbc_name)
|
||||
|
||||
# dragonpilot
|
||||
self.turning_signal_timer = 0
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dragon_lane_departure_warning = True
|
||||
self.dragon_toyota_sng_mod = False
|
||||
self.dp_last_modified = None
|
||||
|
||||
def update(self, enabled, CS, frame, actuators, pcm_cancel_cmd, hud_alert,
|
||||
left_line, right_line, lead, left_lane_depart, right_lane_depart):
|
||||
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
if frame % 500 == 0:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dragon_lane_departure_warning = False if params.get("DragonToyotaLaneDepartureWarning", encoding='utf8') == "0" else True
|
||||
self.dragon_toyota_sng_mod = True if params.get("DragonToyotaSnGMod", encoding='utf8') == "1" else False
|
||||
self.dp_last_modified = modified
|
||||
|
||||
# *** compute control surfaces ***
|
||||
|
||||
# gas and brake
|
||||
@@ -130,7 +151,7 @@ class CarController():
|
||||
self.last_fault_frame = frame
|
||||
|
||||
# Cut steering for 2s after fault
|
||||
if not enabled or (frame - self.last_fault_frame < 200):
|
||||
if not enabled: # or (frame - self.last_fault_frame < 200):
|
||||
apply_steer = 0
|
||||
apply_steer_req = 0
|
||||
else:
|
||||
@@ -161,7 +182,7 @@ class CarController():
|
||||
pcm_cancel_cmd = 1
|
||||
|
||||
# on entering standstill, send standstill request
|
||||
if CS.standstill and not self.last_standstill:
|
||||
if not self.dragon_toyota_sng_mod and CS.standstill and not self.last_standstill:
|
||||
self.standstill_req = True
|
||||
if CS.pcm_acc_status != 8:
|
||||
# pcm entered standstill or it's disabled
|
||||
@@ -174,6 +195,34 @@ class CarController():
|
||||
|
||||
can_sends = []
|
||||
|
||||
# dragonpilot
|
||||
if enabled:
|
||||
if self.dragon_enable_steering_on_signal:
|
||||
if CS.left_blinker_on == 0 and CS.right_blinker_on == 0:
|
||||
self.turning_signal_timer = 0
|
||||
else:
|
||||
self.turning_signal_timer = 100
|
||||
|
||||
if self.turning_signal_timer > 0:
|
||||
self.turning_signal_timer -= 1
|
||||
apply_steer_req = 0
|
||||
else:
|
||||
self.turning_signal_timer = 0
|
||||
|
||||
if not self.dragon_lat_ctrl:
|
||||
apply_steer_req = 0
|
||||
else:
|
||||
if CS.v_ego > 12.5:
|
||||
if right_lane_depart and not CS.right_blinker_on:
|
||||
apply_steer = self.last_steer + 3
|
||||
apply_steer = min(apply_steer , 800)
|
||||
apply_steer_req = 1
|
||||
|
||||
if left_lane_depart and not CS.left_blinker_on:
|
||||
apply_steer = self.last_steer - 3
|
||||
apply_steer = max(apply_steer , -800)
|
||||
apply_steer_req = 1
|
||||
|
||||
#*** control msgs ***
|
||||
#print("steer {0} {1} {2} {3}".format(apply_steer, min_lim, max_lim, CS.steer_torque_motor)
|
||||
|
||||
@@ -197,7 +246,7 @@ class CarController():
|
||||
lead = lead or CS.v_ego < 12. # at low speed we always assume the lead is present do ACC can be engaged
|
||||
|
||||
# Lexus IS uses a different cancellation message
|
||||
if pcm_cancel_cmd and CS.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
if pcm_cancel_cmd and CS.CP.carFingerprint in [CAR.LEXUS_IS, CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
can_sends.append(create_acc_cancel_command(self.packer))
|
||||
elif CS.CP.openpilotLongitudinalControl:
|
||||
can_sends.append(create_accel_command(self.packer, apply_accel, pcm_cancel_cmd, self.standstill_req, lead))
|
||||
@@ -226,8 +275,16 @@ class CarController():
|
||||
if pcm_cancel_cmd:
|
||||
send_ui = True
|
||||
|
||||
# dragonpilot, lane depart warning mod
|
||||
if self.dragon_lane_departure_warning:
|
||||
dragon_left_lane_depart = left_lane_depart
|
||||
dragon_right_lane_depart = right_lane_depart
|
||||
else:
|
||||
dragon_left_lane_depart = False
|
||||
dragon_right_lane_depart = False
|
||||
|
||||
if (frame % 100 == 0 or send_ui) and Ecu.fwdCamera in self.fake_ecus:
|
||||
can_sends.append(create_ui_command(self.packer, steer, pcm_cancel_cmd, left_line, right_line, left_lane_depart, right_lane_depart))
|
||||
can_sends.append(create_ui_command(self.packer, steer, pcm_cancel_cmd, left_line, right_line, dragon_left_lane_depart, dragon_right_lane_depart))
|
||||
|
||||
if frame % 100 == 0 and Ecu.dsu in self.fake_ecus:
|
||||
can_sends.append(create_fcw_command(self.packer, fcw))
|
||||
|
||||
+220
-165
@@ -1,165 +1,220 @@
|
||||
from common.numpy_fast import mean
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from selfdrive.car.interfaces import CarStateBase
|
||||
from opendbc.can.parser import CANParser
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.car.toyota.values import CAR, DBC, STEER_THRESHOLD, TSS2_CAR, NO_DSU_CAR
|
||||
|
||||
|
||||
def get_can_parser(CP):
|
||||
|
||||
signals = [
|
||||
# sig_name, sig_address, default
|
||||
("STEER_ANGLE", "STEER_ANGLE_SENSOR", 0),
|
||||
("GEAR", "GEAR_PACKET", 0),
|
||||
("BRAKE_PRESSED", "BRAKE_MODULE", 0),
|
||||
("GAS_PEDAL", "GAS_PEDAL", 0),
|
||||
("WHEEL_SPEED_FL", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_FR", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_RL", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_RR", "WHEEL_SPEEDS", 0),
|
||||
("DOOR_OPEN_FL", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_FR", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_RL", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_RR", "SEATS_DOORS", 1),
|
||||
("SEATBELT_DRIVER_UNLATCHED", "SEATS_DOORS", 1),
|
||||
("TC_DISABLED", "ESP_CONTROL", 1),
|
||||
("STEER_FRACTION", "STEER_ANGLE_SENSOR", 0),
|
||||
("STEER_RATE", "STEER_ANGLE_SENSOR", 0),
|
||||
("CRUISE_ACTIVE", "PCM_CRUISE", 0),
|
||||
("CRUISE_STATE", "PCM_CRUISE", 0),
|
||||
("STEER_TORQUE_DRIVER", "STEER_TORQUE_SENSOR", 0),
|
||||
("STEER_TORQUE_EPS", "STEER_TORQUE_SENSOR", 0),
|
||||
("TURN_SIGNALS", "STEERING_LEVERS", 3), # 3 is no blinkers
|
||||
("LKA_STATE", "EPS_STATUS", 0),
|
||||
("IPAS_STATE", "EPS_STATUS", 1),
|
||||
("BRAKE_LIGHTS_ACC", "ESP_CONTROL", 0),
|
||||
("AUTO_HIGH_BEAM", "LIGHT_STALK", 0),
|
||||
]
|
||||
|
||||
checks = [
|
||||
("BRAKE_MODULE", 40),
|
||||
("GAS_PEDAL", 33),
|
||||
("WHEEL_SPEEDS", 80),
|
||||
("STEER_ANGLE_SENSOR", 80),
|
||||
("PCM_CRUISE", 33),
|
||||
("STEER_TORQUE_SENSOR", 50),
|
||||
("EPS_STATUS", 25),
|
||||
]
|
||||
|
||||
if CP.carFingerprint == CAR.LEXUS_IS:
|
||||
signals.append(("MAIN_ON", "DSU_CRUISE", 0))
|
||||
signals.append(("SET_SPEED", "DSU_CRUISE", 0))
|
||||
checks.append(("DSU_CRUISE", 5))
|
||||
else:
|
||||
signals.append(("MAIN_ON", "PCM_CRUISE_2", 0))
|
||||
signals.append(("SET_SPEED", "PCM_CRUISE_2", 0))
|
||||
signals.append(("LOW_SPEED_LOCKOUT", "PCM_CRUISE_2", 0))
|
||||
checks.append(("PCM_CRUISE_2", 33))
|
||||
|
||||
if CP.carFingerprint in NO_DSU_CAR:
|
||||
signals += [("STEER_ANGLE", "STEER_TORQUE_SENSOR", 0)]
|
||||
|
||||
if CP.carFingerprint == CAR.PRIUS:
|
||||
signals += [("STATE", "AUTOPARK_STATUS", 0)]
|
||||
|
||||
# add gas interceptor reading if we are using it
|
||||
if CP.enableGasInterceptor:
|
||||
signals.append(("INTERCEPTOR_GAS", "GAS_SENSOR", 0))
|
||||
signals.append(("INTERCEPTOR_GAS2", "GAS_SENSOR", 0))
|
||||
checks.append(("GAS_SENSOR", 50))
|
||||
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
|
||||
|
||||
|
||||
def get_cam_can_parser(CP):
|
||||
|
||||
signals = [("FORCE", "PRE_COLLISION", 0), ("PRECOLLISION_ACTIVE", "PRE_COLLISION", 0)]
|
||||
|
||||
# use steering message to check if panda is connected to frc
|
||||
checks = [("STEERING_LKA", 42)]
|
||||
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
|
||||
|
||||
|
||||
class CarState(CarStateBase):
|
||||
def __init__(self, CP):
|
||||
super().__init__(CP)
|
||||
can_define = CANDefine(DBC[CP.carFingerprint]['pt'])
|
||||
self.shifter_values = can_define.dv["GEAR_PACKET"]['GEAR']
|
||||
self.angle_offset = 0.
|
||||
self.init_angle_offset = False
|
||||
|
||||
def update(self, cp, cp_cam):
|
||||
# update prevs, update must run once per loop
|
||||
self.prev_left_blinker_on = self.left_blinker_on
|
||||
self.prev_right_blinker_on = self.right_blinker_on
|
||||
|
||||
self.door_all_closed = not any([cp.vl["SEATS_DOORS"]['DOOR_OPEN_FL'], cp.vl["SEATS_DOORS"]['DOOR_OPEN_FR'],
|
||||
cp.vl["SEATS_DOORS"]['DOOR_OPEN_RL'], cp.vl["SEATS_DOORS"]['DOOR_OPEN_RR']])
|
||||
self.seatbelt = not cp.vl["SEATS_DOORS"]['SEATBELT_DRIVER_UNLATCHED']
|
||||
|
||||
self.brake_pressed = cp.vl["BRAKE_MODULE"]['BRAKE_PRESSED']
|
||||
if self.CP.enableGasInterceptor:
|
||||
self.pedal_gas = (cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS'] + cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS2']) / 2.
|
||||
else:
|
||||
self.pedal_gas = cp.vl["GAS_PEDAL"]['GAS_PEDAL']
|
||||
self.esp_disabled = cp.vl["ESP_CONTROL"]['TC_DISABLED']
|
||||
|
||||
self.v_wheel_fl = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_FL'] * CV.KPH_TO_MS
|
||||
self.v_wheel_fr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_FR'] * CV.KPH_TO_MS
|
||||
self.v_wheel_rl = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RL'] * CV.KPH_TO_MS
|
||||
self.v_wheel_rr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RR'] * CV.KPH_TO_MS
|
||||
self.v_ego_raw = mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr])
|
||||
self.v_ego, self.a_ego = self.update_speed_kf(self.v_ego_raw)
|
||||
|
||||
self.standstill = not self.v_ego_raw > 0.001
|
||||
|
||||
if self.CP.carFingerprint in TSS2_CAR:
|
||||
self.angle_steers = cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE']
|
||||
elif self.CP.carFingerprint in NO_DSU_CAR:
|
||||
# cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE'] is zeroed to where the steering angle is at start.
|
||||
# need to apply an offset as soon as the steering angle measurements are both received
|
||||
self.angle_steers = cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE'] - self.angle_offset
|
||||
angle_wheel = cp.vl["STEER_ANGLE_SENSOR"]['STEER_ANGLE'] + cp.vl["STEER_ANGLE_SENSOR"]['STEER_FRACTION']
|
||||
if abs(angle_wheel) > 1e-3 and abs(self.angle_steers) > 1e-3 and not self.init_angle_offset:
|
||||
self.init_angle_offset = True
|
||||
self.angle_offset = self.angle_steers - angle_wheel
|
||||
else:
|
||||
self.angle_steers = cp.vl["STEER_ANGLE_SENSOR"]['STEER_ANGLE'] + cp.vl["STEER_ANGLE_SENSOR"]['STEER_FRACTION']
|
||||
self.angle_steers_rate = cp.vl["STEER_ANGLE_SENSOR"]['STEER_RATE']
|
||||
can_gear = int(cp.vl["GEAR_PACKET"]['GEAR'])
|
||||
self.gear_shifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None))
|
||||
if self.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
self.main_on = cp.vl["DSU_CRUISE"]['MAIN_ON']
|
||||
else:
|
||||
self.main_on = cp.vl["PCM_CRUISE_2"]['MAIN_ON']
|
||||
self.left_blinker_on = cp.vl["STEERING_LEVERS"]['TURN_SIGNALS'] == 1
|
||||
self.right_blinker_on = cp.vl["STEERING_LEVERS"]['TURN_SIGNALS'] == 2
|
||||
|
||||
# 2 is standby, 10 is active. TODO: check that everything else is really a faulty state
|
||||
self.steer_state = cp.vl["EPS_STATUS"]['LKA_STATE']
|
||||
self.steer_error = cp.vl["EPS_STATUS"]['LKA_STATE'] not in [1, 5]
|
||||
self.ipas_active = cp.vl['EPS_STATUS']['IPAS_STATE'] == 3
|
||||
self.brake_error = 0
|
||||
self.steer_torque_driver = cp.vl["STEER_TORQUE_SENSOR"]['STEER_TORQUE_DRIVER']
|
||||
self.steer_torque_motor = cp.vl["STEER_TORQUE_SENSOR"]['STEER_TORQUE_EPS']
|
||||
# we could use the override bit from dbc, but it's triggered at too high torque values
|
||||
self.steer_override = abs(self.steer_torque_driver) > STEER_THRESHOLD
|
||||
|
||||
self.user_brake = 0
|
||||
if self.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
self.v_cruise_pcm = cp.vl["DSU_CRUISE"]['SET_SPEED']
|
||||
self.low_speed_lockout = False
|
||||
else:
|
||||
self.v_cruise_pcm = cp.vl["PCM_CRUISE_2"]['SET_SPEED']
|
||||
self.low_speed_lockout = cp.vl["PCM_CRUISE_2"]['LOW_SPEED_LOCKOUT'] == 2
|
||||
self.pcm_acc_status = cp.vl["PCM_CRUISE"]['CRUISE_STATE']
|
||||
self.pcm_acc_active = bool(cp.vl["PCM_CRUISE"]['CRUISE_ACTIVE'])
|
||||
self.brake_lights = bool(cp.vl["ESP_CONTROL"]['BRAKE_LIGHTS_ACC'] or self.brake_pressed)
|
||||
if self.CP.carFingerprint == CAR.PRIUS:
|
||||
self.generic_toggle = cp.vl["AUTOPARK_STATUS"]['STATE'] != 0
|
||||
else:
|
||||
self.generic_toggle = bool(cp.vl["LIGHT_STALK"]['AUTO_HIGH_BEAM'])
|
||||
|
||||
self.stock_aeb = bool(cp_cam.vl["PRE_COLLISION"]["PRECOLLISION_ACTIVE"] and cp_cam.vl["PRE_COLLISION"]["FORCE"] < -1e-5)
|
||||
from common.numpy_fast import mean
|
||||
from opendbc.can.can_define import CANDefine
|
||||
from selfdrive.car.interfaces import CarStateBase
|
||||
from opendbc.can.parser import CANParser
|
||||
from selfdrive.config import Conversions as CV
|
||||
from selfdrive.car.toyota.values import CAR, DBC, STEER_THRESHOLD, TSS2_CAR, NO_DSU_CAR
|
||||
|
||||
from common.realtime import sec_since_boot
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
|
||||
|
||||
def get_can_parser(CP):
|
||||
|
||||
signals = [
|
||||
# sig_name, sig_address, default
|
||||
("STEER_ANGLE", "STEER_ANGLE_SENSOR", 0),
|
||||
("GEAR", "GEAR_PACKET", 0),
|
||||
("BRAKE_PRESSED", "BRAKE_MODULE", 0),
|
||||
("WHEEL_SPEED_FL", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_FR", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_RL", "WHEEL_SPEEDS", 0),
|
||||
("WHEEL_SPEED_RR", "WHEEL_SPEEDS", 0),
|
||||
("DOOR_OPEN_FL", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_FR", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_RL", "SEATS_DOORS", 1),
|
||||
("DOOR_OPEN_RR", "SEATS_DOORS", 1),
|
||||
("SEATBELT_DRIVER_UNLATCHED", "SEATS_DOORS", 1),
|
||||
("TC_DISABLED", "ESP_CONTROL", 1),
|
||||
("STEER_FRACTION", "STEER_ANGLE_SENSOR", 0),
|
||||
("STEER_RATE", "STEER_ANGLE_SENSOR", 0),
|
||||
("CRUISE_ACTIVE", "PCM_CRUISE", 0),
|
||||
("CRUISE_STATE", "PCM_CRUISE", 0),
|
||||
("STEER_TORQUE_DRIVER", "STEER_TORQUE_SENSOR", 0),
|
||||
("STEER_TORQUE_EPS", "STEER_TORQUE_SENSOR", 0),
|
||||
("TURN_SIGNALS", "STEERING_LEVERS", 3), # 3 is no blinkers
|
||||
("LKA_STATE", "EPS_STATUS", 0),
|
||||
("IPAS_STATE", "EPS_STATUS", 1),
|
||||
("BRAKE_LIGHTS_ACC", "ESP_CONTROL", 0),
|
||||
]
|
||||
|
||||
checks = [
|
||||
("WHEEL_SPEEDS", 80),
|
||||
("STEER_ANGLE_SENSOR", 80),
|
||||
("PCM_CRUISE", 33),
|
||||
("STEER_TORQUE_SENSOR", 50),
|
||||
("EPS_STATUS", 25),
|
||||
]
|
||||
|
||||
if CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
signals.append(("GAS_PEDAL", "GAS_PEDAL_ALT", 0))
|
||||
signals.append(("MAIN_ON", "PCM_CRUISE_ALT", 0))
|
||||
signals.append(("SET_SPEED", "PCM_CRUISE_ALT", 0))
|
||||
signals.append(("AUTO_HIGH_BEAM", "LIGHT_STALK_ISH", 0))
|
||||
checks += [
|
||||
("BRAKE_MODULE", 50),
|
||||
("GAS_PEDAL_ALT", 50),
|
||||
("PCM_CRUISE_ALT", 1),
|
||||
]
|
||||
else:
|
||||
signals += [
|
||||
("AUTO_HIGH_BEAM", "LIGHT_STALK", 0),
|
||||
("GAS_PEDAL", "GAS_PEDAL", 0),
|
||||
]
|
||||
checks += [
|
||||
("BRAKE_MODULE", 40),
|
||||
("GAS_PEDAL", 33),
|
||||
]
|
||||
|
||||
if CP.carFingerprint == CAR.LEXUS_IS:
|
||||
signals.append(("MAIN_ON", "DSU_CRUISE", 0))
|
||||
signals.append(("SET_SPEED", "DSU_CRUISE", 0))
|
||||
checks.append(("DSU_CRUISE", 5))
|
||||
else:
|
||||
signals.append(("MAIN_ON", "PCM_CRUISE_2", 0))
|
||||
signals.append(("SET_SPEED", "PCM_CRUISE_2", 0))
|
||||
signals.append(("LOW_SPEED_LOCKOUT", "PCM_CRUISE_2", 0))
|
||||
checks.append(("PCM_CRUISE_2", 33))
|
||||
|
||||
if CP.carFingerprint in NO_DSU_CAR or CP.carFingerprint == CAR.LEXUS_ISH:
|
||||
signals += [("STEER_ANGLE", "STEER_TORQUE_SENSOR", 0)]
|
||||
|
||||
if CP.carFingerprint == CAR.PRIUS:
|
||||
signals += [("STATE", "AUTOPARK_STATUS", 0)]
|
||||
|
||||
# add gas interceptor reading if we are using it
|
||||
if CP.enableGasInterceptor:
|
||||
signals.append(("INTERCEPTOR_GAS", "GAS_SENSOR", 0))
|
||||
signals.append(("INTERCEPTOR_GAS2", "GAS_SENSOR", 0))
|
||||
checks.append(("GAS_SENSOR", 50))
|
||||
|
||||
checks = []
|
||||
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 0)
|
||||
|
||||
|
||||
def get_cam_can_parser(CP):
|
||||
|
||||
signals = [("FORCE", "PRE_COLLISION", 0), ("PRECOLLISION_ACTIVE", "PRE_COLLISION", 0)]
|
||||
|
||||
# use steering message to check if panda is connected to frc
|
||||
checks = [("STEERING_LKA", 42)]
|
||||
|
||||
return CANParser(DBC[CP.carFingerprint]['pt'], signals, checks, 2)
|
||||
|
||||
|
||||
class CarState(CarStateBase):
|
||||
def __init__(self, CP):
|
||||
super().__init__(CP)
|
||||
can_define = CANDefine(DBC[CP.carFingerprint]['pt'])
|
||||
self.shifter_values = can_define.dv["GEAR_PACKET"]['GEAR']
|
||||
self.angle_offset = 0.
|
||||
self.init_angle_offset = False
|
||||
|
||||
# dragonpilot
|
||||
self.dragon_toyota_stock_dsu = False
|
||||
self.ts_last_check = 0.
|
||||
|
||||
def update(self, cp, cp_cam):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
self.dragon_toyota_stock_dsu = True if params.get("DragonToyotaStockDSU", encoding='utf8') == "1" else False
|
||||
self.ts_last_check = ts
|
||||
|
||||
# update prevs, update must run once per loop
|
||||
self.prev_left_blinker_on = self.left_blinker_on
|
||||
self.prev_right_blinker_on = self.right_blinker_on
|
||||
|
||||
self.door_all_closed = not any([cp.vl["SEATS_DOORS"]['DOOR_OPEN_FL'], cp.vl["SEATS_DOORS"]['DOOR_OPEN_FR'],
|
||||
cp.vl["SEATS_DOORS"]['DOOR_OPEN_RL'], cp.vl["SEATS_DOORS"]['DOOR_OPEN_RR']])
|
||||
self.seatbelt = not cp.vl["SEATS_DOORS"]['SEATBELT_DRIVER_UNLATCHED']
|
||||
|
||||
self.brake_pressed = cp.vl["BRAKE_MODULE"]['BRAKE_PRESSED']
|
||||
if self.CP.enableGasInterceptor:
|
||||
self.pedal_gas = (cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS'] + cp.vl["GAS_SENSOR"]['INTERCEPTOR_GAS2']) / 2.
|
||||
elif self.CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
self.pedal_gas = cp.vl["GAS_PEDAL_ALT"]['GAS_PEDAL']
|
||||
else:
|
||||
self.pedal_gas = cp.vl["GAS_PEDAL"]['GAS_PEDAL']
|
||||
self.esp_disabled = cp.vl["ESP_CONTROL"]['TC_DISABLED']
|
||||
|
||||
self.v_wheel_fl = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_FL'] * CV.KPH_TO_MS
|
||||
self.v_wheel_fr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_FR'] * CV.KPH_TO_MS
|
||||
self.v_wheel_rl = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RL'] * CV.KPH_TO_MS
|
||||
self.v_wheel_rr = cp.vl["WHEEL_SPEEDS"]['WHEEL_SPEED_RR'] * CV.KPH_TO_MS
|
||||
self.v_ego_raw = mean([self.v_wheel_fl, self.v_wheel_fr, self.v_wheel_rl, self.v_wheel_rr])
|
||||
self.v_ego, self.a_ego = self.update_speed_kf(self.v_ego_raw)
|
||||
|
||||
self.standstill = not self.v_ego_raw > 0.001
|
||||
|
||||
if self.CP.carFingerprint in TSS2_CAR:
|
||||
self.angle_steers = cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE']
|
||||
elif self.CP.carFingerprint in NO_DSU_CAR or self.CP.carFingerprint == CAR.LEXUS_ISH:
|
||||
# cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE'] is zeroed to where the steering angle is at start.
|
||||
# need to apply an offset as soon as the steering angle measurements are both received
|
||||
self.angle_steers = cp.vl["STEER_TORQUE_SENSOR"]['STEER_ANGLE'] - self.angle_offset
|
||||
angle_wheel = cp.vl["STEER_ANGLE_SENSOR"]['STEER_ANGLE'] + cp.vl["STEER_ANGLE_SENSOR"]['STEER_FRACTION']
|
||||
if abs(angle_wheel) > 1e-3 and abs(self.angle_steers) > 1e-3 and not self.init_angle_offset:
|
||||
self.init_angle_offset = True
|
||||
self.angle_offset = self.angle_steers - angle_wheel
|
||||
else:
|
||||
self.angle_steers = cp.vl["STEER_ANGLE_SENSOR"]['STEER_ANGLE'] + cp.vl["STEER_ANGLE_SENSOR"]['STEER_FRACTION']
|
||||
self.angle_steers_rate = cp.vl["STEER_ANGLE_SENSOR"]['STEER_RATE']
|
||||
can_gear = int(cp.vl["GEAR_PACKET"]['GEAR'])
|
||||
self.gear_shifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None))
|
||||
if self.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
self.main_on = cp.vl["DSU_CRUISE"]['MAIN_ON']
|
||||
elif self.CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
self.main_on = cp.vl["PCM_CRUISE_ALT"]['MAIN_ON']
|
||||
else:
|
||||
self.main_on = cp.vl["PCM_CRUISE_2"]['MAIN_ON']
|
||||
self.left_blinker_on = cp.vl["STEERING_LEVERS"]['TURN_SIGNALS'] == 1
|
||||
self.right_blinker_on = cp.vl["STEERING_LEVERS"]['TURN_SIGNALS'] == 2
|
||||
|
||||
# 2 is standby, 10 is active. TODO: check that everything else is really a faulty state
|
||||
self.steer_state = cp.vl["EPS_STATUS"]['LKA_STATE']
|
||||
self.steer_error = cp.vl["EPS_STATUS"]['LKA_STATE'] not in [1, 5]
|
||||
self.ipas_active = cp.vl['EPS_STATUS']['IPAS_STATE'] == 3
|
||||
self.brake_error = 0
|
||||
self.steer_torque_driver = cp.vl["STEER_TORQUE_SENSOR"]['STEER_TORQUE_DRIVER']
|
||||
self.steer_torque_motor = cp.vl["STEER_TORQUE_SENSOR"]['STEER_TORQUE_EPS']
|
||||
# we could use the override bit from dbc, but it's triggered at too high torque values
|
||||
self.steer_override = abs(self.steer_torque_driver) > STEER_THRESHOLD
|
||||
|
||||
self.user_brake = 0
|
||||
if self.CP.carFingerprint == CAR.LEXUS_IS:
|
||||
self.v_cruise_pcm = cp.vl["DSU_CRUISE"]['SET_SPEED']
|
||||
self.low_speed_lockout = False
|
||||
elif self.CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
self.v_cruise_pcm = cp.vl["PCM_CRUISE_ALT"]['SET_SPEED']
|
||||
self.low_speed_lockout = False
|
||||
else:
|
||||
self.v_cruise_pcm = cp.vl["PCM_CRUISE_2"]['SET_SPEED']
|
||||
self.low_speed_lockout = cp.vl["PCM_CRUISE_2"]['LOW_SPEED_LOCKOUT'] == 2
|
||||
if self.CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
# Lexus ISH does not have curise status value (always 0), so we use curise_active value instead
|
||||
self.pcm_acc_status = cp.vl["PCM_CRUISE"]['CRUISE_ACTIVE']
|
||||
else:
|
||||
self.pcm_acc_status = cp.vl["PCM_CRUISE"]['CRUISE_STATE']
|
||||
self.pcm_acc_active = bool(cp.vl["PCM_CRUISE"]['CRUISE_ACTIVE'])
|
||||
self.brake_lights = bool(cp.vl["ESP_CONTROL"]['BRAKE_LIGHTS_ACC'] or self.brake_pressed)
|
||||
if self.CP.carFingerprint == CAR.PRIUS:
|
||||
self.generic_toggle = cp.vl["AUTOPARK_STATUS"]['STATE'] != 0
|
||||
elif self.CP.carFingerprint in [CAR.LEXUS_ISH, CAR.LEXUS_GSH]:
|
||||
self.generic_toggle = bool(cp.vl["LIGHT_STALK_ISH"]['AUTO_HIGH_BEAM'])
|
||||
else:
|
||||
self.generic_toggle = bool(cp.vl["LIGHT_STALK"]['AUTO_HIGH_BEAM'])
|
||||
|
||||
self.stock_aeb = bool(cp_cam.vl["PRE_COLLISION"]["PRECOLLISION_ACTIVE"] and cp_cam.vl["PRE_COLLISION"]["FORCE"] < -1e-5)
|
||||
|
||||
if self.dragon_toyota_stock_dsu and self.generic_toggle and self.main_on:
|
||||
enable_acc = True
|
||||
if not self.seatbelt or not self.door_all_closed:
|
||||
enable_acc = False
|
||||
self.pcm_acc_active = enable_acc
|
||||
if self.standstill:
|
||||
self.pcm_acc_status = 7
|
||||
else:
|
||||
self.pcm_acc_status = 1
|
||||
|
||||
Executable → Regular
+62
-8
@@ -8,6 +8,10 @@ from selfdrive.car.toyota.values import Ecu, ECU_FINGERPRINT, CAR, NO_STOP_TIMER
|
||||
from selfdrive.car import STD_CARGO_KG, scale_rot_inertia, scale_tire_stiffness, is_ecu_disconnected, gen_empty_fingerprint
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from common.realtime import sec_since_boot
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
GearShifter = car.CarState.GearShifter
|
||||
@@ -32,6 +36,14 @@ class CarInterface(CarInterfaceBase):
|
||||
if CarController is not None:
|
||||
self.CC = CarController(self.cp.dbc_name, CP.carFingerprint, CP.enableCamera, CP.enableDsu, CP.enableApgs)
|
||||
|
||||
# dragonpilot
|
||||
self.dragon_toyota_stock_dsu = False
|
||||
self.dragon_enable_steering_on_signal = False
|
||||
self.dragon_allow_gas = False
|
||||
self.ts_last_check = 0.
|
||||
self.dragon_lat_ctrl = True
|
||||
self.dp_last_modified = None
|
||||
|
||||
@staticmethod
|
||||
def compute_gb(accel, speed):
|
||||
return float(accel) / 3.0
|
||||
@@ -62,7 +74,7 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.wheelbase = 2.70
|
||||
ret.steerRatio = 15.74 # unknown end-to-end spec
|
||||
tire_stiffness_factor = 0.6371 # hand-tune
|
||||
ret.mass = 3045. * CV.LB_TO_KG + STD_CARGO_KG
|
||||
ret.mass = 3370. * CV.LB_TO_KG + STD_CARGO_KG
|
||||
|
||||
ret.lateralTuning.init('indi')
|
||||
ret.lateralTuning.indi.innerLoopGain = 4.0
|
||||
@@ -273,6 +285,26 @@ class CarInterface(CarInterfaceBase):
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.1]]
|
||||
ret.lateralTuning.pid.kf = 0.00006
|
||||
|
||||
elif candidate == CAR.LEXUS_ISH:
|
||||
stop_and_go = True # set to true because it's a hybrid
|
||||
ret.safetyParam = 130
|
||||
ret.wheelbase = 2.79908
|
||||
ret.steerRatio = 13.3
|
||||
tire_stiffness_factor = 0.444
|
||||
ret.mass = 3736.8 * CV.LB_TO_KG + STD_CARGO_KG
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.05]]
|
||||
ret.lateralTuning.pid.kf = 0.00006
|
||||
|
||||
elif candidate == CAR.LEXUS_GSH:
|
||||
stop_and_go = True # set to true because it's a hybrid
|
||||
ret.safetyParam = 77
|
||||
ret.wheelbase = 2.84988
|
||||
ret.steerRatio = 13.3
|
||||
tire_stiffness_factor = 0.444
|
||||
ret.mass = 4112 * CV.LB_TO_KG + STD_CARGO_KG
|
||||
ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.05]]
|
||||
ret.lateralTuning.pid.kf = 0.00006
|
||||
|
||||
ret.steerRateCost = 1.
|
||||
ret.centerToFront = ret.wheelbase * 0.44
|
||||
|
||||
@@ -339,6 +371,18 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
# returns a car.CarState
|
||||
def update(self, c, can_strings):
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_enable_steering_on_signal = True if params.get("DragonEnableSteeringOnSignal", encoding='utf8') == "1" else False
|
||||
self.dragon_allow_gas = True if params.get("DragonAllowGas", encoding='utf8') == "1" else False
|
||||
self.dragon_toyota_stock_dsu = True if params.get("DragonToyotaStockDSU", encoding='utf8') == "1" else False
|
||||
self.dragon_lat_ctrl = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
self.dp_last_modified = modified
|
||||
self.ts_last_check = ts
|
||||
|
||||
# ******************* do can recv *******************
|
||||
self.cp.update_strings(can_strings)
|
||||
self.cp_cam.update_strings(can_strings)
|
||||
@@ -440,7 +484,11 @@ class CarInterface(CarInterfaceBase):
|
||||
events.append(create_event('wrongCarMode', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
if ret.gearShifter == GearShifter.reverse and self.CP.openpilotLongitudinalControl:
|
||||
events.append(create_event('reverseGear', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
if self.CS.steer_error:
|
||||
if not self.dragon_lat_ctrl:
|
||||
events.append(create_event('manualSteeringRequired', [ET.WARNING]))
|
||||
elif (self.CS.left_blinker_on or self.CS.right_blinker_on) and self.dragon_enable_steering_on_signal:
|
||||
events.append(create_event('manualSteeringRequiredBlinkersOn', [ET.WARNING]))
|
||||
elif self.CS.steer_error:
|
||||
events.append(create_event('steerTempUnavailable', [ET.NO_ENTRY, ET.WARNING]))
|
||||
if self.CS.low_speed_lockout and self.CP.openpilotLongitudinalControl:
|
||||
events.append(create_event('lowSpeedLockout', [ET.NO_ENTRY, ET.PERMANENT]))
|
||||
@@ -459,13 +507,19 @@ class CarInterface(CarInterfaceBase):
|
||||
elif not ret.cruiseState.enabled:
|
||||
events.append(create_event('pcmDisable', [ET.USER_DISABLE]))
|
||||
|
||||
# disable on pedals rising edge or when brake is pressed and speed isn't zero
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
if not self.dragon_toyota_stock_dsu:
|
||||
# DragonAllowGas
|
||||
if not self.dragon_allow_gas:
|
||||
# disable on pedals rising edge or when brake is pressed and speed isn't zero
|
||||
if (ret.gasPressed and not self.gas_pressed_prev) or \
|
||||
(ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001)):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
if ret.gasPressed:
|
||||
events.append(create_event('pedalPressed', [ET.PRE_ENABLE]))
|
||||
else:
|
||||
if ret.brakePressed and (not self.brake_pressed_prev or ret.vEgo > 0.001):
|
||||
events.append(create_event('pedalPressed', [ET.NO_ENTRY, ET.USER_DISABLE]))
|
||||
|
||||
ret.events = events
|
||||
|
||||
|
||||
Executable → Regular
@@ -35,6 +35,8 @@ class CAR:
|
||||
LEXUS_CTH = "LEXUS CT 200H 2018"
|
||||
RAV4H_TSS2 = "TOYOTA RAV4 HYBRID 2019"
|
||||
LEXUS_NXH = "LEXUS NX300H 2018"
|
||||
LEXUS_ISH = "LEXUS IS300h 2017"
|
||||
LEXUS_GSH = "LEXUS GS450h 2017"
|
||||
|
||||
|
||||
# addr: (ecu, cars, bus, 1/freq*100, vl)
|
||||
@@ -89,6 +91,10 @@ FINGERPRINTS = {
|
||||
# with ipas
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 824: 2, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 869: 7, 870: 7, 871: 2,898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 974: 8, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
{
|
||||
# Taiwan Prius 4.5
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 512: 6, 513: 6, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 800: 8, 810: 2, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 845: 5, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
#2019 LE
|
||||
{
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 614: 8, 643: 7, 658: 8, 713: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 814: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1071: 8, 1076: 8, 1077: 8, 1082: 8, 1083: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1175: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
@@ -117,6 +123,10 @@ FINGERPRINTS = {
|
||||
# 2016 Lexus RX 350
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
|
||||
},
|
||||
{
|
||||
# RX300 China
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 742: 8, 743: 8, 744: 8, 800: 8, 810: 2, 812: 3, 830: 7, 835: 8, 836: 8, 845: 5, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1279: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
# 2017 Lexus RX 350
|
||||
{
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 658: 8, 705: 8, 740: 5, 742: 8, 743: 8, 767:4, 800: 8, 810: 2, 812: 3, 814: 8, 818: 8, 819: 8, 820: 8, 821: 8, 822: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1227: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1349: 8, 1350: 8, 1351: 8, 1413: 8, 1414: 8, 1415: 8, 1416: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1595: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
@@ -158,9 +168,13 @@ FINGERPRINTS = {
|
||||
{
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 888: 8, 889: 8, 891: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
# China 2018 Camry from superdongle
|
||||
{
|
||||
36: 8, 37: 8, 119: 6, 170: 8, 180: 8, 186: 4, 355: 5, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1235: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1595: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
{
|
||||
# 2019 XSE
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 942: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1792: 8, 1767:4, 800: 8, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1937: 8, 1945: 8, 1953: 8, 1961: 8, 1968: 8, 1976: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 888: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 942: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 983: 8, 984: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1011: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1412: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1792: 8, 1767:4, 1808: 8, 1816: 8, 1872: 8, 1880: 8, 1904: 8, 1912: 8, 1937: 8, 1945: 8, 1953: 8, 1961: 8, 1968: 8, 1976: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
|
||||
}],
|
||||
CAR.CAMRYH: [
|
||||
#SE, LE and LE with Blindspot Monitor
|
||||
@@ -205,6 +219,14 @@ FINGERPRINTS = {
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 547: 8, 550: 8, 552: 4, 562: 6, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767:4, 800: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 905: 8, 911: 1, 916: 2, 921: 8, 933: 6, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 1005: 2, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1200: 8, 1201: 8, 1202: 8, 1203: 8, 1206: 8, 1227: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
}],
|
||||
CAR.RAV4_TSS2: [
|
||||
# Taiwan 2019 RAV4 from Max Duan / CloudJ
|
||||
{
|
||||
36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 913: 8, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8
|
||||
},
|
||||
# China 2020 RAV4 from superdongle
|
||||
{
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 918: 7, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 987: 8, 993: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1112: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1263: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8
|
||||
},
|
||||
# LE
|
||||
{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8,1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553:8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
@@ -212,11 +234,27 @@ FINGERPRINTS = {
|
||||
# XLE, Limited, and AWD
|
||||
{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 565: 8, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 822: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 891: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1063: 8, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8, 2015: 8, 2016: 8, 2024: 8
|
||||
},
|
||||
# Taiwan 2019 RAV4H from Max Duan
|
||||
{
|
||||
36: 8, 37: 8, 166: 8, 170: 8, 180: 8, 295: 8, 296: 8, 401: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 8, 643: 7, 713: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 863: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 896: 8, 898: 8, 913: 8, 921: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 8, 955: 8, 956: 8, 971: 7, 975: 5, 993: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1063: 8, 1071: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1696: 8, 1745: 8, 1775: 8, 1779: 8
|
||||
}],
|
||||
CAR.COROLLA_TSS2: [
|
||||
# hatch 2019+ and sedan 2020+
|
||||
{
|
||||
36: 8, 37: 8, 114: 5, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1235: 8, 1237: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1595: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1808: 8, 1809: 8, 1816: 8, 1817: 8, 1840: 8, 1848: 8, 1904: 8, 1912: 8, 1940: 8, 1941: 8, 1948: 8, 1949: 8, 1952: 8, 1960: 8, 1981: 8, 1986: 8, 1990: 8, 1994: 8, 1998: 8, 2004: 8
|
||||
},
|
||||
{
|
||||
# 2019 Taiwan Altis
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 918: 7, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1082: 8, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1745: 8, 1775: 8, 1779: 8
|
||||
},
|
||||
{
|
||||
# 2019 Chinese Levin (Petrol) from Shell
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1984: 8, 1992: 8, 2002: 8
|
||||
},
|
||||
{
|
||||
# 2019 Chinese Corolla (Petrol) from Shell
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 742: 8, 743: 8, 761: 8, 765: 8, 800: 8, 810: 2, 812: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 885: 8, 896: 8, 898: 8, 921: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1172: 8, 1235: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1592: 8, 1594: 8, 1595: 8, 1600: 8, 1649: 8, 1745: 8, 1775: 8, 1779: 8, 1808: 8, 1816: 8, 1904: 8, 1912: 8
|
||||
}],
|
||||
CAR.COROLLAH_TSS2: [
|
||||
# 2019 Taiwan Altis Hybrid
|
||||
@@ -230,6 +268,10 @@ FINGERPRINTS = {
|
||||
],
|
||||
CAR.LEXUS_ES_TSS2: [{
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 658: 8, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 767:4, 800: 8, 810: 2, 812: 8, 814: 8, 818: 8, 824: 8, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1237: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1649: 8, 1696: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8,
|
||||
},
|
||||
{
|
||||
# 2019 Lexus ES200 from Shell
|
||||
36: 8, 37: 8, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 355: 5, 401: 8, 426: 6, 452: 8, 464: 8, 466: 8, 467: 8, 544: 4, 550: 8, 552: 4, 562: 6, 608: 8, 610: 8, 643: 7, 705: 8, 728: 8, 740: 5, 761: 8, 764: 8, 765: 8, 800: 8, 810: 2, 812: 8, 818: 8, 824: 8, 829: 2, 830: 7, 835: 8, 836: 8, 865: 8, 869: 7, 870: 7, 871: 2, 877: 8, 881: 8, 882: 8, 885: 8, 889: 8, 896: 8, 898: 8, 900: 6, 902: 6, 905: 8, 913: 8, 918: 8, 921: 8, 933: 8, 934: 8, 935: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 976: 1, 987: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1044: 8, 1056: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1084: 8, 1085: 8, 1086: 8, 1114: 8, 1132: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1172: 8, 1228: 8, 1235: 8, 1264: 8, 1279: 8, 1541: 8, 1552: 8, 1553: 8, 1556: 8, 1557: 8, 1568: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1592: 8, 1594: 8, 1595: 8, 1775: 8, 1777: 8, 1779: 8, 1786: 8, 1787: 8, 1788: 8, 1789: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
}],
|
||||
CAR.LEXUS_ESH_TSS2: [
|
||||
{
|
||||
@@ -247,7 +289,8 @@ FINGERPRINTS = {
|
||||
# IS300 2018
|
||||
{
|
||||
36: 8, 37: 8, 114: 5, 119: 6, 120: 4, 170: 8, 180: 8, 186: 4, 238: 4, 400: 6, 426: 6, 452: 8, 464: 8, 466: 8, 467: 5, 544: 4, 550: 8, 552: 4, 608: 8, 610: 5, 643: 7, 705: 8, 740: 5, 767:4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 8, 933: 8, 944: 8, 945: 8, 951: 8, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1005: 2, 1008: 2, 1009: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1235: 8, 1237: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1590: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1648: 8, 1666: 8, 1667: 8, 1728: 8, 1745: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
},
|
||||
}],
|
||||
CAR.LEXUS_ISH: [
|
||||
# IS300H 2017
|
||||
{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 295: 8, 296: 8, 400: 6, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 767:4, 800: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 7, 921: 7, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1009: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1044: 8, 1056: 8, 1057: 8, 1059: 1, 1112: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1232: 8, 1235: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
@@ -259,11 +302,20 @@ FINGERPRINTS = {
|
||||
},
|
||||
],
|
||||
CAR.LEXUS_CTH: [{
|
||||
# Taiwan CT200h FP from CloudJ
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 288: 8, 426: 6, 452: 8, 466: 8, 467: 8, 548: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 810: 2, 832: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 918: 7, 921: 8, 933: 8, 944: 6, 945: 8, 950: 8, 951: 8, 953: 3, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1112: 8, 1114: 8, 1116: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1190: 8, 1191: 8, 1192: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1664: 8, 1728: 8, 1779: 8
|
||||
},
|
||||
{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 288: 8, 426: 6, 452: 8, 466: 8, 467: 8, 548: 8, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 800: 8, 810: 2, 832: 8, 835: 8, 836: 8, 849: 4, 869: 7, 870: 7, 871: 2, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 916: 1, 921: 8, 933: 8, 944: 6, 945: 8, 950: 8, 951: 8, 953: 3, 955: 4, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1114: 8, 1116: 8, 1160: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1190: 8, 1191: 8, 1192: 8, 1227: 8, 1235: 8, 1279: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1558: 8, 1561: 8, 1562: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
}],
|
||||
CAR.LEXUS_NXH: [{
|
||||
36: 8, 37: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 467: 8, 550: 8, 552: 4, 560: 7, 562: 6, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 742: 8, 743: 8, 764: 8, 800: 8, 810: 2, 812: 3, 818: 8, 822: 8, 824: 8, 835: 8, 836: 8, 845: 5, 849: 4, 869: 7, 870: 7, 871: 2, 889: 8, 891: 8, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 3, 918: 8, 921: 8, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 987: 8, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1002: 8, 1006: 8, 1014: 8, 1017: 8, 1020: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1057: 8, 1059: 1, 1076: 8, 1077: 8, 1082: 8, 1114: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1184: 8, 1185: 8, 1186: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1195: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1206: 8, 1208: 8, 1212: 8, 1227: 8, 1228: 8, 1232: 8, 1235: 8, 1237: 8, 1263: 8, 1264: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1599: 8, 1656: 8, 1728: 8, 1745: 8, 1777: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
}]
|
||||
}],
|
||||
CAR.LEXUS_GSH: [
|
||||
# GS450H 2017
|
||||
{
|
||||
36: 8, 37: 8, 38: 8, 42: 8, 44: 8, 170: 8, 180: 8, 295: 8, 296: 8, 426: 6, 452: 8, 466: 8, 548: 8, 550: 2, 552: 4, 560: 7, 581: 5, 608: 8, 610: 5, 643: 7, 713: 8, 740: 5, 744: 8, 800: 8, 810: 2, 812: 3, 832: 8, 836: 8, 845: 5, 849: 4, 864: 1, 869: 7, 870: 7, 871: 2, 896: 8, 897: 8, 900: 6, 902: 6, 905: 8, 911: 8, 913: 8, 916: 2, 917: 4, 918: 7, 919: 1, 921: 7, 933: 8, 944: 8, 945: 8, 950: 8, 951: 8, 953: 3, 955: 8, 956: 8, 979: 2, 992: 8, 998: 5, 999: 7, 1000: 8, 1001: 8, 1009: 8, 1014: 8, 1017: 8, 1041: 8, 1042: 8, 1043: 8, 1056: 8, 1057: 8, 1059: 1, 1112: 8, 1114: 8, 1116: 8, 1161: 8, 1162: 8, 1163: 8, 1164: 8, 1165: 8, 1166: 8, 1167: 8, 1168: 1, 1176: 8, 1177: 8, 1178: 8, 1179: 8, 1180: 8, 1181: 8, 1182: 8, 1183: 8, 1184: 8, 1185: 8, 1186: 8, 1187: 8, 1188: 8, 1189: 8, 1190: 8, 1191: 8, 1192: 8, 1193: 8, 1195: 8, 1196: 8, 1197: 8, 1198: 8, 1199: 8, 1200: 8, 1201: 8, 1206: 8, 1208: 8, 1226: 8, 1227: 8, 1235: 8, 1237: 8, 1250: 8, 1279: 8, 1408: 8, 1409: 8, 1410: 8, 1552: 8, 1553: 8, 1554: 8, 1555: 8, 1556: 8, 1557: 8, 1561: 8, 1568: 8, 1569: 8, 1570: 8, 1571: 8, 1572: 8, 1575: 8, 1584: 8, 1589: 8, 1592: 8, 1593: 8, 1595: 8, 1596: 8, 1597: 8, 1599: 8, 1664: 8, 1728: 8, 1779: 8, 1904: 8, 1912: 8, 1990: 8, 1998: 8
|
||||
}],
|
||||
}
|
||||
|
||||
# Don't use theses fingerprints for fingerprinting, they are still needed for ECU detection
|
||||
@@ -797,6 +849,8 @@ DBC = {
|
||||
CAR.LEXUS_CTH: dbc_dict('lexus_ct200h_2018_pt_generated', 'toyota_adas'),
|
||||
CAR.RAV4H_TSS2: dbc_dict('toyota_nodsu_hybrid_pt_generated', 'toyota_tss2_adas'),
|
||||
CAR.LEXUS_NXH: dbc_dict('lexus_nx300h_2018_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_ISH: dbc_dict('lexus_is_2018_pt_generated', 'toyota_adas'),
|
||||
CAR.LEXUS_GSH: dbc_dict('lexus_is_2018_pt_generated', 'toyota_adas'),
|
||||
}
|
||||
|
||||
NO_DSU_CAR = [CAR.CHR, CAR.CHRH, CAR.CAMRY, CAR.CAMRYH, CAR.RAV4_TSS2, CAR.COROLLA_TSS2, CAR.COROLLAH_TSS2, CAR.LEXUS_ES_TSS2, CAR.LEXUS_ESH_TSS2, CAR.RAV4H_TSS2, CAR.LEXUS_RX_TSS2, CAR.HIGHLANDER_TSS2]
|
||||
|
||||
@@ -25,6 +25,7 @@ from selfdrive.controls.lib.alertmanager import AlertManager
|
||||
from selfdrive.controls.lib.vehicle_model import VehicleModel
|
||||
from selfdrive.controls.lib.planner import LON_MPC_STEP
|
||||
from selfdrive.locationd.calibration_helpers import Calibration, Filter
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
LANE_DEPARTURE_THRESHOLD = 0.1
|
||||
|
||||
@@ -39,11 +40,20 @@ LaneChangeDirection = log.PathPlan.LaneChangeDirection
|
||||
def add_lane_change_event(events, path_plan):
|
||||
if path_plan.laneChangeState == LaneChangeState.preLaneChange:
|
||||
if path_plan.laneChangeDirection == LaneChangeDirection.left:
|
||||
events.append(create_event('preLaneChangeLeft', [ET.WARNING]))
|
||||
event_name = 'preLaneChangeLeft'
|
||||
if path_plan.autoLCAllowed:
|
||||
event_name = 'preAutoLaneChangeLeft'
|
||||
events.append(create_event(event_name, [ET.WARNING]))
|
||||
else:
|
||||
events.append(create_event('preLaneChangeRight', [ET.WARNING]))
|
||||
event_name = 'preLaneChangeRight'
|
||||
if path_plan.autoLCAllowed:
|
||||
event_name = 'preAutoLaneChangeRight'
|
||||
events.append(create_event(event_name, [ET.WARNING]))
|
||||
elif path_plan.laneChangeState in [LaneChangeState.laneChangeStarting, LaneChangeState.laneChangeFinishing]:
|
||||
events.append(create_event('laneChange', [ET.WARNING]))
|
||||
event_name = 'laneChange'
|
||||
if path_plan.autoLCAllowed:
|
||||
event_name = 'autoLaneChange'
|
||||
events.append(create_event(event_name, [ET.WARNING]))
|
||||
|
||||
|
||||
def isActive(state):
|
||||
@@ -216,7 +226,7 @@ def state_transition(frame, CS, CP, state, events, soft_disable_timer, v_cruise_
|
||||
|
||||
|
||||
def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cruise_kph, v_cruise_kph_last,
|
||||
AM, rk, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame):
|
||||
AM, rk, LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, dragon_lat_control, dragon_display_steering_limit_alert, dragon_lead_car_moving_alert):
|
||||
"""Given the state, this function returns an actuators packet"""
|
||||
|
||||
actuators = car.CarControl.Actuators.new_message()
|
||||
@@ -238,6 +248,11 @@ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cr
|
||||
# State specific actions
|
||||
|
||||
if state in [State.preEnabled, State.disabled]:
|
||||
if dragon_lead_car_moving_alert:
|
||||
for e in get_events(events, [ET.WARNING]):
|
||||
extra_text = ""
|
||||
if e in ["leadCarDetected", "leadCarMoving"]:
|
||||
AM.add(frame, e, enabled, extra_text_2=extra_text)
|
||||
LaC.reset()
|
||||
LoC.reset(v_pid=CS.vEgo)
|
||||
|
||||
@@ -259,19 +274,20 @@ def state_control(frame, rcv_frame, plan, path_plan, CS, CP, state, events, v_cr
|
||||
v_acc_sol = plan.vStart + dt * (a_acc_sol + plan.aStart) / 2.0
|
||||
|
||||
# Gas/Brake PID loop
|
||||
actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.brakePressed, CS.standstill, CS.cruiseState.standstill,
|
||||
actuators.gas, actuators.brake = LoC.update(active, CS.vEgo, CS.gasPressed, CS.brakePressed, CS.standstill, CS.cruiseState.standstill,
|
||||
v_cruise_kph, v_acc_sol, plan.vTargetFuture, a_acc_sol, CP)
|
||||
# Steering PID loop and lateral MPC
|
||||
actuators.steer, actuators.steerAngle, lac_log = LaC.update(active, CS.vEgo, CS.steeringAngle, CS.steeringRate, CS.steeringTorqueEps, CS.steeringPressed, CS.steeringRateLimited, CP, path_plan)
|
||||
|
||||
# Send a "steering required alert" if saturation count has reached the limit
|
||||
if lac_log.saturated and not CS.steeringPressed:
|
||||
# Check if we deviated from the path
|
||||
left_deviation = actuators.steer > 0 and path_plan.dPoly[3] > 0.1
|
||||
right_deviation = actuators.steer < 0 and path_plan.dPoly[3] < -0.1
|
||||
if dragon_display_steering_limit_alert:
|
||||
if dragon_lat_control and lac_log.saturated and not CS.steeringPressed:
|
||||
# Check if we deviated from the path
|
||||
left_deviation = actuators.steer > 0 and path_plan.dPoly[3] > 0.1
|
||||
right_deviation = actuators.steer < 0 and path_plan.dPoly[3] < -0.1
|
||||
|
||||
if left_deviation or right_deviation:
|
||||
AM.add(frame, "steerSaturated", enabled)
|
||||
if left_deviation or right_deviation:
|
||||
AM.add(frame, "steerSaturated", enabled)
|
||||
|
||||
# Parse permanent warnings to display constantly
|
||||
for e in get_events(events, [ET.PERMANENT]):
|
||||
@@ -520,11 +536,32 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
|
||||
# controlsd is driven by can recv, expected at 100Hz
|
||||
rk = Ratekeeper(100, print_delay_threshold=None)
|
||||
|
||||
internet_needed = params.get("Offroad_ConnectivityNeeded", encoding='utf8') is not None
|
||||
# internet_needed = params.get("Offroad_ConnectivityNeeded", encoding='utf8') is not None
|
||||
|
||||
prof = Profiler(False) # off by default
|
||||
|
||||
# dragonpilot
|
||||
ts_last_check = 0.
|
||||
dragon_toyota_stock_dsu = False
|
||||
dragon_lat_control = True
|
||||
dragon_display_steering_limit_alert = True
|
||||
dragon_stopped_has_lead_count = 0
|
||||
dragon_lead_car_moving_alert = False
|
||||
dp_last_modified = None
|
||||
|
||||
while True:
|
||||
# dragonpilot, don't check for param too often as it's a kernel call
|
||||
ts = sec_since_boot()
|
||||
if ts - ts_last_check >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if dp_last_modified != modified:
|
||||
dragon_toyota_stock_dsu = True if params.get("DragonToyotaStockDSU", encoding='utf8') == "1" else False
|
||||
dragon_lat_control = False if params.get("DragonLatCtrl", encoding='utf8') == "0" else True
|
||||
dragon_display_steering_limit_alert = False if params.get("DragonDisplaySteeringLimitAlert", encoding='utf8') == "0" else True
|
||||
dragon_lead_car_moving_alert = True if params.get("DragonEnableLeadCarMovingAlert", encoding='utf8') == "1" else False
|
||||
dp_last_modified = modified
|
||||
ts_last_check = ts
|
||||
|
||||
start_time = sec_since_boot()
|
||||
prof.checkpoint("Ratekeeper", ignore=True)
|
||||
|
||||
@@ -550,19 +587,42 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
|
||||
if sm['plan'].radarCanError:
|
||||
events.append(create_event('radarCanError', [ET.NO_ENTRY, ET.SOFT_DISABLE]))
|
||||
if not CS.canValid:
|
||||
events.append(create_event('canError', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
if dragon_toyota_stock_dsu:
|
||||
events.append(create_event('pcmDisable', [ET.USER_DISABLE]))
|
||||
else:
|
||||
events.append(create_event('canError', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
if not sounds_available:
|
||||
events.append(create_event('soundsUnavailable', [ET.NO_ENTRY, ET.PERMANENT]))
|
||||
if internet_needed:
|
||||
events.append(create_event('internetConnectivityNeeded', [ET.NO_ENTRY, ET.PERMANENT]))
|
||||
#if internet_needed:
|
||||
# events.append(create_event('internetConnectivityNeeded', [ET.NO_ENTRY, ET.PERMANENT]))
|
||||
if community_feature_disallowed:
|
||||
events.append(create_event('communityFeatureDisallowed', [ET.PERMANENT]))
|
||||
if read_only and not passive:
|
||||
events.append(create_event('carUnrecognized', [ET.PERMANENT]))
|
||||
|
||||
# Only allow engagement with brake pressed when stopped behind another stopped car
|
||||
if CS.brakePressed and sm['plan'].vTargetFuture >= STARTING_TARGET_SPEED and not CP.radarOffCan and CS.vEgo < 0.3:
|
||||
events.append(create_event('noTarget', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
if not dragon_toyota_stock_dsu:
|
||||
# Only allow engagement with brake pressed when stopped behind another stopped car
|
||||
if CS.brakePressed and sm['plan'].vTargetFuture >= STARTING_TARGET_SPEED and not CP.radarOffCan and CS.vEgo < 0.3:
|
||||
events.append(create_event('noTarget', [ET.NO_ENTRY, ET.IMMEDIATE_DISABLE]))
|
||||
|
||||
if dragon_lead_car_moving_alert:
|
||||
# when car has a lead and is standstill and lead is barely moving, we start counting
|
||||
if not CP.radarOffCan and sm['plan'].hasLead and CS.vEgo <= 0.01 and 0.3 >= abs(sm['plan'].vTarget) >= 0:
|
||||
dragon_stopped_has_lead_count += 1
|
||||
else:
|
||||
dragon_stopped_has_lead_count = 0
|
||||
|
||||
# when we detect lead car over a sec and the lead car is started moving, we are ready to send alerts
|
||||
# once the condition is triggered, we want to keep the trigger
|
||||
if dragon_stopped_has_lead_count >= 100:
|
||||
if abs(sm['plan'].vTargetFuture) >= 0.1:
|
||||
events.append(create_event('leadCarMoving', [ET.WARNING]))
|
||||
else:
|
||||
events.append(create_event('leadCarDetected', [ET.WARNING]))
|
||||
|
||||
# we remove alert once our car is moving
|
||||
if CS.vEgo > 0.:
|
||||
dragon_stopped_has_lead_count = 0
|
||||
|
||||
if not read_only:
|
||||
# update control state
|
||||
@@ -573,7 +633,7 @@ def controlsd_thread(sm=None, pm=None, can_sock=None):
|
||||
# Compute actuators (runs PID loops and lateral MPC)
|
||||
actuators, v_cruise_kph, v_acc, a_acc, lac_log, last_blinker_frame = \
|
||||
state_control(sm.frame, sm.rcv_frame, sm['plan'], sm['pathPlan'], CS, CP, state, events, v_cruise_kph, v_cruise_kph_last, AM, rk,
|
||||
LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame)
|
||||
LaC, LoC, read_only, is_metric, cal_perc, last_blinker_frame, dragon_lat_control, dragon_display_steering_limit_alert, dragon_lead_car_moving_alert)
|
||||
|
||||
prof.checkpoint("State Control")
|
||||
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
import gc
|
||||
from common.realtime import set_realtime_priority
|
||||
from common.realtime import set_realtime_priority, sec_since_boot
|
||||
from common.params import Params, put_nonblocking
|
||||
import cereal.messaging as messaging
|
||||
from selfdrive.controls.lib.drive_helpers import create_event, EventTypes as ET
|
||||
from selfdrive.controls.lib.driver_monitor import DriverStatus, MAX_TERMINAL_ALERTS, MAX_TERMINAL_DURATION
|
||||
from selfdrive.locationd.calibration_helpers import Calibration
|
||||
from selfdrive.controls.lib.gps_helpers import is_rhd_region
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
def dmonitoringd_thread(sm=None, pm=None):
|
||||
gc.disable()
|
||||
@@ -40,8 +43,46 @@ def dmonitoringd_thread(sm=None, pm=None):
|
||||
v_cruise_last = 0
|
||||
driver_engaged = False
|
||||
|
||||
# dragonpilot
|
||||
last_ts = 0
|
||||
dp_last_modified = None
|
||||
dp_enable_driver_safety_check = True
|
||||
dp_enable_driver_monitoring = True
|
||||
|
||||
# 10Hz <- dmonitoringmodeld
|
||||
while True:
|
||||
cur_time = sec_since_boot()
|
||||
if cur_time - last_ts >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if dp_last_modified != modified:
|
||||
dp_enable_driver_safety_check = False if params.get("DragonEnableDriverSafetyCheck", encoding='utf8') == "0" else True
|
||||
# load driver monitor val only when safety is on
|
||||
if dp_enable_driver_safety_check:
|
||||
dp_enable_driver_monitoring = False if params.get("DragonEnableDriverMonitoring", encoding='utf8') == "0" else True
|
||||
# load steering monitor timer val only when driver monitor is on
|
||||
if dp_enable_driver_safety_check:
|
||||
try:
|
||||
dp_awareness_time = int(params.get("DragonSteeringMonitorTimer", encoding='utf8'))
|
||||
except TypeError:
|
||||
dp_awareness_time = 0.
|
||||
driver_status.awareness_time = 86400 if dp_awareness_time <= 0. else dp_awareness_time * 60.
|
||||
dp_last_modified = modified
|
||||
last_ts = cur_time
|
||||
|
||||
if not dp_enable_driver_safety_check:
|
||||
dp_enable_driver_monitoring = False
|
||||
driver_status.awareness_time = 86400
|
||||
|
||||
# reset all awareness val and set to rhd region, this will enforce steering monitor.
|
||||
if not dp_enable_driver_monitoring:
|
||||
driver_status.is_rhd_region = True
|
||||
driver_status.is_rhd_region_checked = True
|
||||
driver_status.awareness = 1.
|
||||
driver_status.awareness_active = 1.
|
||||
driver_status.awareness_passive = 1.
|
||||
driver_status.terminal_alert_cnt = 0
|
||||
driver_status.terminal_time = 0
|
||||
|
||||
sm.update()
|
||||
|
||||
# GPS coords RHD parsing, once every restart
|
||||
|
||||
+235
-187
@@ -1,3 +1,5 @@
|
||||
# This Python file uses the following encoding: utf-8
|
||||
# -*- coding: utf-8 -*-
|
||||
from cereal import car, log
|
||||
|
||||
# Priority
|
||||
@@ -75,99 +77,99 @@ ALERTS = [
|
||||
|
||||
Alert(
|
||||
"fcw",
|
||||
"BRAKE!",
|
||||
"Risk of Collision",
|
||||
"剎車!",
|
||||
"有碰撞的風險",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.chimeWarningRepeat, 1., 2., 2.),
|
||||
|
||||
Alert(
|
||||
"fcwStock",
|
||||
"BRAKE!",
|
||||
"Risk of Collision",
|
||||
"馬上剎車!",
|
||||
"有碰撞風險",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.fcw, AudibleAlert.none, 1., 2., 2.), # no EON chime for stock FCW
|
||||
|
||||
Alert(
|
||||
"steerSaturated",
|
||||
"TAKE CONTROL",
|
||||
"Turn Exceeds Steering Limit",
|
||||
"接管控制",
|
||||
"彎道超過方向盤轉向限制",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.),
|
||||
|
||||
Alert(
|
||||
"steerTempUnavailable",
|
||||
"TAKE CONTROL",
|
||||
"Steering Temporarily Unavailable",
|
||||
"接管控制",
|
||||
"轉向控制暫時失效",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"steerTempUnavailableMute",
|
||||
"TAKE CONTROL",
|
||||
"Steering Temporarily Unavailable",
|
||||
"接管控制",
|
||||
"轉向控制暫時失效",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .2, .2, .2),
|
||||
|
||||
Alert(
|
||||
"preDriverDistracted",
|
||||
"KEEP EYES ON ROAD: Driver Appears Distracted",
|
||||
"注意路況:駕駛分心",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"promptDriverDistracted",
|
||||
"KEEP EYES ON ROAD",
|
||||
"Driver Appears Distracted",
|
||||
"注意路況",
|
||||
"駕駛分心",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1),
|
||||
|
||||
Alert(
|
||||
"driverDistracted",
|
||||
"DISENGAGE IMMEDIATELY",
|
||||
"Driver Was Distracted",
|
||||
"立即解除",
|
||||
"駕駛分心",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1),
|
||||
|
||||
Alert(
|
||||
"preDriverUnresponsive",
|
||||
"TOUCH STEERING WHEEL: No Face Detected",
|
||||
"請觸碰方向盤:無駕駛監控",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"promptDriverUnresponsive",
|
||||
"TOUCH STEERING WHEEL",
|
||||
"Driver Is Unresponsive",
|
||||
"請觸碰方向盤",
|
||||
"駕駛沒有反應",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1),
|
||||
|
||||
Alert(
|
||||
"driverUnresponsive",
|
||||
"DISENGAGE IMMEDIATELY",
|
||||
"Driver Was Unresponsive",
|
||||
"立即解除",
|
||||
"駕駛沒有反應",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1),
|
||||
|
||||
Alert(
|
||||
"driverMonitorLowAcc",
|
||||
"CHECK DRIVER FACE VISIBILITY",
|
||||
"Driver Monitor Model Output Uncertain",
|
||||
"請檢查駕駛面部的可見度",
|
||||
"駕駛監控模型輸出不明確",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .4, 0., 1.),
|
||||
|
||||
Alert(
|
||||
"geofence",
|
||||
"DISENGAGEMENT REQUIRED",
|
||||
"Not in Geofenced Area",
|
||||
"不在地理圍欄區域之內",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, .1, .1),
|
||||
|
||||
Alert(
|
||||
"startup",
|
||||
"Be ready to take over at any time",
|
||||
"Always keep hands on wheel and eyes on road",
|
||||
"隨時準備好接管",
|
||||
"請您將手放在方向盤上並持續注意路況",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., 15.),
|
||||
|
||||
@@ -180,50 +182,50 @@ ALERTS = [
|
||||
|
||||
Alert(
|
||||
"startupNoControl",
|
||||
"Dashcam mode",
|
||||
"Always keep hands on wheel and eyes on road",
|
||||
"行車記錄模式",
|
||||
"請您將手放在方向盤上並持續注意路況",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., 15.),
|
||||
|
||||
Alert(
|
||||
"startupNoCar",
|
||||
"Dashcam mode with unsupported car",
|
||||
"Always keep hands on wheel and eyes on road",
|
||||
"行車記錄模式 (尚未支援車種)",
|
||||
"請您將手放在方向盤上並持續注意路況",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., 15.),
|
||||
|
||||
Alert(
|
||||
"ethicalDilemma",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"即刻接管控制",
|
||||
"Ethical Dilemma Detected",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 1., 3., 3.),
|
||||
|
||||
Alert(
|
||||
"steerTempUnavailableNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Steering Temporarily Unavailable",
|
||||
"無法使用 dragonpilot",
|
||||
"轉向控制暫時失效",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.),
|
||||
|
||||
Alert(
|
||||
"manualRestart",
|
||||
"TAKE CONTROL",
|
||||
"Resume Driving Manually",
|
||||
"接管控制",
|
||||
"請自行恢復駕駛",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"resumeRequired",
|
||||
"STOPPED",
|
||||
"Press Resume to Move",
|
||||
"已停止",
|
||||
"請按 RES 繼續",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"belowSteerSpeed",
|
||||
"TAKE CONTROL",
|
||||
"Steer Unavailable Below ",
|
||||
"接管控制",
|
||||
"轉向控制暫時失效,車速低於 ",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.none, 0., 0.4, .3),
|
||||
|
||||
@@ -235,539 +237,539 @@ ALERTS = [
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .1, .1, .1),
|
||||
Alert(
|
||||
"preLaneChangeLeft",
|
||||
"Steer Left to Start Lane Change",
|
||||
"Monitor Other Vehicles",
|
||||
"請往左打方向盤切換車道",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"preLaneChangeRight",
|
||||
"Steer Right to Start Lane Change",
|
||||
"Monitor Other Vehicles",
|
||||
"請往右打方向盤切換車道",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"laneChange",
|
||||
"Changing Lane",
|
||||
"Monitor Other Vehicles",
|
||||
"切換車道中",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.none, .0, .1, .1),
|
||||
|
||||
Alert(
|
||||
"posenetInvalid",
|
||||
"TAKE CONTROL",
|
||||
"Vision Model Output Uncertain",
|
||||
"接管控制",
|
||||
"視覺模型輸出不明確",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning1, .4, 2., 3.),
|
||||
|
||||
# Non-entry only alerts
|
||||
Alert(
|
||||
"wrongCarModeNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Main Switch Off",
|
||||
"無法使用 dragonpilot",
|
||||
"主開關關閉",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.),
|
||||
|
||||
Alert(
|
||||
"dataNeededNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Data Needed for Calibration. Upload Drive, Try Again",
|
||||
"無法使用 dragonpilot",
|
||||
"需要更多的數據來協助校準,請將行車記錄上傳後再試",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.),
|
||||
|
||||
Alert(
|
||||
"outOfSpaceNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Out of Storage Space",
|
||||
"無法使用 dragonpilot",
|
||||
"儲存空間不足",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 0., 3.),
|
||||
|
||||
Alert(
|
||||
"pedalPressedNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"無法使用 dragonpilot",
|
||||
"Pedal Pressed During Attempt",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, "brakePressed", AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"speedTooLowNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Speed Too Low",
|
||||
"無法使用 dragonpilot",
|
||||
"車速過慢",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"brakeHoldNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Brake Hold Active",
|
||||
"無法使用 dragonpilot",
|
||||
"駐車煞車已啟用",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"parkBrakeNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Park Brake Engaged",
|
||||
"無法使用 dragonpilot",
|
||||
"電子駐車已啟動",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"lowSpeedLockoutNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Cruise Fault: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"巡航系統錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"lowBatteryNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Low Battery",
|
||||
"無法使用 dragonpilot",
|
||||
"電池電量過低",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"sensorDataInvalidNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"No Data from Device Sensors",
|
||||
"無法使用 dragonpilot",
|
||||
"沒有收到任何來自裝置傳感器的資料",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"soundsUnavailableNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Speaker not found",
|
||||
"無法使用 dragonpilot",
|
||||
"找不到音效裝置",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"tooDistractedNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Distraction Level Too High",
|
||||
"無法使用 dragonpilot",
|
||||
"駕駛分心次數過高",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
# Cancellation alerts causing soft disabling
|
||||
Alert(
|
||||
"overheat",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"System Overheated",
|
||||
"即刻接管控制",
|
||||
"系統過熱",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"wrongGear",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Gear not D",
|
||||
"即刻接管控制",
|
||||
"檔位不在 D 檔",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"calibrationInvalid",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Calibration Invalid: Reposition Device and Recalibrate",
|
||||
"即刻接管控制",
|
||||
"校準無效:請將裝置放於新的位置並重新校準",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"calibrationIncomplete",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Calibration in Progress",
|
||||
"即刻接管控制",
|
||||
"正在校準相機中",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"doorOpen",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Door Open",
|
||||
"即刻接管控制",
|
||||
"車門開啟",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"seatbeltNotLatched",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Seatbelt Unlatched",
|
||||
"即刻接管控制",
|
||||
"安全帶未繫",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"espDisabled",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"ESP Off",
|
||||
"即刻接管控制",
|
||||
"ESP 關閉",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"lowBattery",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Low Battery",
|
||||
"即刻接管控制",
|
||||
"電池電量過低",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"commIssue",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Communication Issue between Processes",
|
||||
"即刻接管控制",
|
||||
"雷達訊號錯誤:請重新發動車子",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"radarCommIssue",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Radar Communication Issue",
|
||||
"即刻接管控制",
|
||||
"雷達通訊出現問題",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"radarCanError",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Radar Error: Restart the Car",
|
||||
"即刻接管控制",
|
||||
"雷達訊號錯誤:請重新發動車子",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
Alert(
|
||||
"radarFault",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Radar Error: Restart the Car",
|
||||
"即刻接管控制",
|
||||
"AI 模型錯誤:請檢查網路連線",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
|
||||
Alert(
|
||||
"lowMemory",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Low Memory: Reboot Your Device",
|
||||
"即刻接管控制",
|
||||
"記憶體不足:請重啟您的裝置",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.MID, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, .1, 2., 2.),
|
||||
|
||||
# Cancellation alerts causing immediate disabling
|
||||
Alert(
|
||||
"controlsFailed",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Controls Failed",
|
||||
"即刻接管控制",
|
||||
"控制發生錯誤",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"controlsMismatch",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Controls Mismatch",
|
||||
"即刻接管控制",
|
||||
"控制不匹配",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"canError",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"CAN Error: Check Connections",
|
||||
"即刻接管控制",
|
||||
"CAN 訊號錯誤:請檢查接線",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"steerUnavailable",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"LKAS Fault: Restart the Car",
|
||||
"即刻接管控制",
|
||||
"LKAS 錯誤:請重新發動車子",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"brakeUnavailable",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Cruise Fault: Restart the Car",
|
||||
"即刻接管控制",
|
||||
"巡航系統錯誤:請重新發動車子",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"gasUnavailable",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Gas Fault: Restart the Car",
|
||||
"即刻接管控制",
|
||||
"油門錯誤:請重新發動車子",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"reverseGear",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Reverse Gear",
|
||||
"即刻接管控制",
|
||||
"切換至倒車檔",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"cruiseDisabled",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Cruise Is Off",
|
||||
"即刻接管控制",
|
||||
"巡航系統關閉",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
Alert(
|
||||
"plannerError",
|
||||
"TAKE CONTROL IMMEDIATELY",
|
||||
"Planner Solution Error",
|
||||
"即刻接管控制",
|
||||
"Planner Solution 錯誤",
|
||||
AlertStatus.critical, AlertSize.full,
|
||||
Priority.HIGHEST, VisualAlert.steerRequired, AudibleAlert.chimeWarningRepeat, 2.2, 3., 4.),
|
||||
|
||||
# not loud cancellations (user is in control)
|
||||
Alert(
|
||||
"noTarget",
|
||||
"openpilot Canceled",
|
||||
"No close lead car",
|
||||
"dragonpilot 已取消",
|
||||
"沒有偵測到前車",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"speedTooLow",
|
||||
"openpilot Canceled",
|
||||
"Speed too low",
|
||||
"dragonpilot 已取消",
|
||||
"車速過慢",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.HIGH, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
# Cancellation alerts causing non-entry
|
||||
Alert(
|
||||
"overheatNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"System overheated",
|
||||
"無法使用 dragonpilot",
|
||||
"系統過熱",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"wrongGearNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Gear not D",
|
||||
"無法使用 dragonpilot",
|
||||
"車子不在 D 檔",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"calibrationInvalidNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Calibration Invalid: Reposition Device and Recalibrate",
|
||||
"無法使用 dragonpilot",
|
||||
"校準無效:請將裝置放於新的位置並重新校準",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"calibrationIncompleteNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Calibration in Progress",
|
||||
"無法使用 dragonpilot",
|
||||
"正在校準相機中",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"doorOpenNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Door open",
|
||||
"無法使用 dragonpilot",
|
||||
"車門未關",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"seatbeltNotLatchedNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Seatbelt unlatched",
|
||||
"無法使用 dragonpilot",
|
||||
"安全帶未繫",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"espDisabledNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"ESP Off",
|
||||
"無法使用 dragonpilot",
|
||||
"ESP 關閉",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"geofenceNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Not in Geofenced Area",
|
||||
"無法使用 dragonpilot",
|
||||
"不在地理圍欄區域之內",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.MID, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"radarCanErrorNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Radar Error: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"雷達訊號錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"radarFaultNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Radar Error: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"雷達訊號錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"posenetInvalidNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Vision Model Output Uncertain",
|
||||
"無法使用 dragonpilot",
|
||||
"視覺模型輸出不明確",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"controlsFailedNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Controls Failed",
|
||||
"無法使用 dragonpilot",
|
||||
"控制發生錯誤",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"canErrorNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"CAN Error: Check Connections",
|
||||
"無法使用 dragonpilot",
|
||||
"CAN 訊號錯誤:請檢查接線",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"steerUnavailableNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"LKAS Fault: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"LKAS 錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"brakeUnavailableNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Cruise Fault: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"巡航系統錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"gasUnavailableNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Gas Error: Restart the Car",
|
||||
"無法使用 dragonpilot",
|
||||
"油門錯誤:請重新發動車子",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"reverseGearNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Reverse Gear",
|
||||
"無法使用 dragonpilot",
|
||||
"切換至倒車檔",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"cruiseDisabledNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Cruise is Off",
|
||||
"無法使用 dragonpilot",
|
||||
"巡航系統關閉",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"noTargetNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"No Close Lead Car",
|
||||
"無法使用 dragonpilot",
|
||||
"沒有偵測到前車",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"plannerErrorNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Planner Solution Error",
|
||||
"無法使用 dragonpilot",
|
||||
"Planner Solution 錯誤",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeError, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"commIssueNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Communication Issue between Processes",
|
||||
"無法使用 dragonpilot",
|
||||
"行程出現通訊問題",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"radarCommIssueNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Radar Communication Issue",
|
||||
"無法使用 dragonpilot",
|
||||
"雷達通訊出現問題",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"internetConnectivityNeededNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Please Connect to Internet",
|
||||
"無法使用 dragonpilot",
|
||||
"請連接網路",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
Alert(
|
||||
"lowMemoryNoEntry",
|
||||
"openpilot Unavailable",
|
||||
"Low Memory: Reboot Your Device",
|
||||
"無法使用 dragonpilot",
|
||||
"記憶體不足:請重啟您的裝置",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.chimeDisengage, .4, 2., 3.),
|
||||
|
||||
# permanent alerts
|
||||
Alert(
|
||||
"steerUnavailablePermanent",
|
||||
"LKAS Fault: Restart the car to engage",
|
||||
"LKAS 錯誤:請重新發動車子",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"brakeUnavailablePermanent",
|
||||
"Cruise Fault: Restart the car to engage",
|
||||
"巡航系統錯誤:請重新發動車子",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"lowSpeedLockoutPermanent",
|
||||
"Cruise Fault: Restart the car to engage",
|
||||
"巡航系統錯誤:請重新發動車子",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"calibrationIncompletePermanent",
|
||||
"Calibration in Progress: ",
|
||||
"Drive Above ",
|
||||
"正在校準相機中:",
|
||||
"車速請高於 ",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"invalidGiraffeToyotaPermanent",
|
||||
"Unsupported Giraffe Configuration",
|
||||
"Visit comma.ai/tg",
|
||||
"未支援的 Giraffe 設置",
|
||||
"請查閱 comma.ai/tg",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"internetConnectivityNeededPermanent",
|
||||
"Please connect to Internet",
|
||||
"An Update Check Is Required to Engage",
|
||||
"請連接網路",
|
||||
"需檢查更新後才能啟用",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"communityFeatureDisallowedPermanent",
|
||||
"Community Feature Detected",
|
||||
"Enable Community Features in Developer Settings",
|
||||
"偵測到社群開發功能",
|
||||
"請至開發人員設定裡啟用社群開發功能",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, 0., 0., .2), # LOW priority to overcome Cruise Error
|
||||
|
||||
Alert(
|
||||
"sensorDataInvalidPermanent",
|
||||
"No Data from Device Sensors",
|
||||
"Reboot your Device",
|
||||
"沒有收到任何來自 EON 傳感器的資料",
|
||||
"請重啟您的裝置",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"soundsUnavailablePermanent",
|
||||
"Speaker not found",
|
||||
"Reboot your Device",
|
||||
"找不到音效裝置",
|
||||
"請重啟您的裝置",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"lowMemoryPermanent",
|
||||
"RAM Critically Low",
|
||||
"Reboot your Device",
|
||||
"記憶體嚴重不足",
|
||||
"請重啟您的裝置",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"carUnrecognizedPermanent",
|
||||
"Dashcam Mode",
|
||||
"Car Unrecognized",
|
||||
"行車記錄模式",
|
||||
"無法辨識您的車款",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW_LOWEST, VisualAlert.none, AudibleAlert.none, 0., 0., .2),
|
||||
|
||||
Alert(
|
||||
"vehicleModelInvalid",
|
||||
"Vehicle Parameter Identification Failed",
|
||||
"車子參數識別失敗",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOWEST, VisualAlert.steerRequired, AudibleAlert.none, .0, .0, .1),
|
||||
@@ -775,8 +777,54 @@ ALERTS = [
|
||||
# offroad alerts
|
||||
Alert(
|
||||
"ldwPermanent",
|
||||
"TAKE CONTROL",
|
||||
"Lane Departure Detected",
|
||||
"接管控制",
|
||||
"偵測到已偏離車道",
|
||||
AlertStatus.userPrompt, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimePrompt, 1., 2., 3.),
|
||||
# dragonpilot
|
||||
Alert(
|
||||
"manualSteeringRequired",
|
||||
"請接管方向盤:車道維持關閉",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1, alert_rate=0.25),
|
||||
|
||||
Alert(
|
||||
"manualSteeringRequiredBlinkersOn",
|
||||
"請接管方向盤:方向燈開啟",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1, alert_rate=0.25),
|
||||
Alert(
|
||||
"leadCarMoving",
|
||||
"前車移動中,請開始加速",
|
||||
"",
|
||||
AlertStatus.userPrompt, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1),
|
||||
Alert(
|
||||
"leadCarDetected",
|
||||
"偵測到前車,等待中",
|
||||
"",
|
||||
AlertStatus.normal, AlertSize.small,
|
||||
Priority.LOW, VisualAlert.none, AudibleAlert.none, .0, .1, .1, alert_rate=0.25),
|
||||
Alert(
|
||||
"preAutoLaneChangeLeft",
|
||||
"將在三秒後自動切至左車道",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"preAutoLaneChangeRight",
|
||||
"將在三秒後自動切至右車道",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1, alert_rate=0.75),
|
||||
|
||||
Alert(
|
||||
"autoLaneChange",
|
||||
"切換車道中",
|
||||
"請注意其它車輛",
|
||||
AlertStatus.normal, AlertSize.mid,
|
||||
Priority.LOW, VisualAlert.steerRequired, AudibleAlert.chimeWarning2, .1, .1, .1),
|
||||
]
|
||||
|
||||
@@ -1,31 +1,31 @@
|
||||
{
|
||||
"Offroad_ChargeDisabled": {
|
||||
"text": "EON charging disabled after car being off for more than 30 hours. Turn ignition on to start charging again.",
|
||||
"text": "因車輛已熄火超過 30 小時,系統將會停止為 EON 充電,再次發動車輛後 EON 會恢復充電",
|
||||
"severity": 0
|
||||
},
|
||||
"Offroad_TemperatureTooHigh": {
|
||||
"text": "Device temperature too high. System won't start.",
|
||||
"text": "裝置溫度過高,系統暫時無法啟用。",
|
||||
"severity": 1
|
||||
},
|
||||
"Offroad_ConnectivityNeededPrompt": {
|
||||
"text": "Immediately connect to the internet to check for updates. If you do not connect to the internet, openpilot won't engage in ",
|
||||
"text": "目前 dragonpilot 無法啟用,請馬上連網檢查更新。",
|
||||
"severity": 0,
|
||||
"_comment": "Append the number of days at the end of the text"
|
||||
},
|
||||
"Offroad_ConnectivityNeeded": {
|
||||
"text": "Connect to internet to check for updates. openpilot won't engage until it connects to internet to check for updates.",
|
||||
"text": "請連網檢查更新。不然 dragonpilot 將無法啟用。",
|
||||
"severity": 1
|
||||
},
|
||||
"Offroad_PandaFirmwareMismatch": {
|
||||
"text": "Unexpected panda firmware version. System won't start. Reboot your device to reflash panda.",
|
||||
"text": "Panda 的韌體版本出現異常,系統無法啟用。請重啟您的裝置以刷新 Panda 韌體。",
|
||||
"severity": 1
|
||||
},
|
||||
"Offroad_InvalidTime": {
|
||||
"text": "Invalid date and time settings, system won't start. Connect to internet to set time.",
|
||||
"text": "系統日期/時間設定錯誤,系統無法啟用。請連上網設定的時間。",
|
||||
"severity": 1
|
||||
},
|
||||
"Offroad_IsTakingSnapshot": {
|
||||
"text": "Taking camera snapshots. System won't start until finished.",
|
||||
"text": "相機拍攝中,完成前系統無法啟用。",
|
||||
"severity": 0
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,6 +111,9 @@ class DriverStatus():
|
||||
self.is_rhd_region = False
|
||||
self.is_rhd_region_checked = False
|
||||
|
||||
# dragonpilot
|
||||
self.awareness_time = 70.
|
||||
|
||||
self._set_timers(active_monitoring=True)
|
||||
|
||||
def _set_timers(self, active_monitoring):
|
||||
@@ -138,9 +141,9 @@ class DriverStatus():
|
||||
self.awareness_active = self.awareness
|
||||
self.awareness = self.awareness_passive
|
||||
|
||||
self.threshold_pre = _AWARENESS_PRE_TIME_TILL_TERMINAL / _AWARENESS_TIME
|
||||
self.threshold_prompt = _AWARENESS_PROMPT_TIME_TILL_TERMINAL / _AWARENESS_TIME
|
||||
self.step_change = DT_DMON / _AWARENESS_TIME
|
||||
self.threshold_pre = _AWARENESS_PRE_TIME_TILL_TERMINAL / self.awareness_time
|
||||
self.threshold_prompt = _AWARENESS_PROMPT_TIME_TILL_TERMINAL / self.awareness_time
|
||||
self.step_change = DT_DMON / self.awareness_time
|
||||
self.active_monitoring_mode = False
|
||||
|
||||
def _is_driver_distracted(self, pose, blink):
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
from common.numpy_fast import interp
|
||||
import numpy as np
|
||||
from cereal import log
|
||||
from common.realtime import sec_since_boot
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
|
||||
CAMERA_OFFSET = 0.06 # m from center car to camera
|
||||
|
||||
@@ -53,6 +56,9 @@ class LanePlanner():
|
||||
self._path_pinv = compute_path_pinv()
|
||||
self.x_points = np.arange(50)
|
||||
|
||||
self.ts_last_check = 0.
|
||||
self.camera_offset = 0.06
|
||||
|
||||
def parse_model(self, md):
|
||||
if len(md.leftLane.poly):
|
||||
self.l_poly = np.array(md.leftLane.poly)
|
||||
@@ -70,9 +76,13 @@ class LanePlanner():
|
||||
self.r_lane_change_prob = md.meta.desirePrediction[log.PathPlan.Desire.laneChangeRight - 1]
|
||||
|
||||
def update_d_poly(self, v_ego):
|
||||
ts = sec_since_boot()
|
||||
if ts - self.ts_last_check >= 5.:
|
||||
self.camera_offset = int(params.get("DragonCameraOffset", encoding='utf8')) * 0.01
|
||||
self.ts_last_check = ts
|
||||
# only offset left and right lane lines; offsetting p_poly does not make sense
|
||||
self.l_poly[3] += CAMERA_OFFSET
|
||||
self.r_poly[3] += CAMERA_OFFSET
|
||||
self.l_poly[3] += self.camera_offset
|
||||
self.r_poly[3] += self.camera_offset
|
||||
|
||||
# Find current lanewidth
|
||||
self.lane_width_certainty += 0.05 * (self.l_prob * self.r_prob - self.lane_width_certainty)
|
||||
|
||||
@@ -71,7 +71,7 @@ class LongControl():
|
||||
self.pid.reset()
|
||||
self.v_pid = v_pid
|
||||
|
||||
def update(self, active, v_ego, brake_pressed, standstill, cruise_standstill, v_cruise, v_target, v_target_future, a_target, CP):
|
||||
def update(self, active, v_ego, gas_pressed, brake_pressed, standstill, cruise_standstill, v_cruise, v_target, v_target_future, a_target, CP):
|
||||
"""Update longitudinal control. This updates the state machine and runs a PID loop"""
|
||||
# Actuation limits
|
||||
gas_max = interp(v_ego, CP.gasMaxBP, CP.gasMaxV)
|
||||
@@ -85,7 +85,7 @@ class LongControl():
|
||||
|
||||
v_ego_pid = max(v_ego, MIN_CAN_SPEED) # Without this we get jumps, CAN bus reports 0 when speed < 0.3
|
||||
|
||||
if self.long_control_state == LongCtrlState.off:
|
||||
if self.long_control_state == LongCtrlState.off or gas_pressed:
|
||||
self.v_pid = v_ego_pid
|
||||
self.pid.reset()
|
||||
output_gb = 0.
|
||||
|
||||
@@ -9,6 +9,9 @@ from selfdrive.config import Conversions as CV
|
||||
from common.params import Params
|
||||
import cereal.messaging as messaging
|
||||
from cereal import log
|
||||
# dragonpilot
|
||||
from common.params import Params
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
LaneChangeState = log.PathPlan.LaneChangeState
|
||||
LaneChangeDirection = log.PathPlan.LaneChangeDirection
|
||||
@@ -60,6 +63,18 @@ class PathPlanner():
|
||||
self.lane_change_timer = 0.0
|
||||
self.prev_one_blinker = False
|
||||
|
||||
# dragonpilot
|
||||
self.params = Params()
|
||||
self.dragon_assisted_lc_enabled = False
|
||||
self.dragon_auto_lc_enabled = False
|
||||
self.dragon_auto_lc_allowed = False
|
||||
self.dragon_auto_lc_timer = None
|
||||
self.dragon_assisted_lc_min_mph = 37 * CV.MPH_TO_MS
|
||||
self.dragon_auto_lc_min_mph = 60 * CV.MPH_TO_MS
|
||||
self.dragon_auto_lc_delay = 2.
|
||||
self.last_ts = 0.
|
||||
self.dp_last_modified = None
|
||||
|
||||
def setup_mpc(self):
|
||||
self.libmpc = libmpc_py.libmpc
|
||||
self.libmpc.init(MPC_COST_LAT.PATH, MPC_COST_LAT.LANE, MPC_COST_LAT.HEADING, self.steer_rate_cost)
|
||||
@@ -77,6 +92,33 @@ class PathPlanner():
|
||||
self.angle_steers_des_time = 0.0
|
||||
|
||||
def update(self, sm, pm, CP, VM):
|
||||
# dragonpilot
|
||||
cur_time = sec_since_boot()
|
||||
if cur_time - self.last_ts >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_assisted_lc_enabled = self.lane_change_enabled
|
||||
if self.dragon_assisted_lc_enabled:
|
||||
self.dragon_auto_lc_enabled = True if self.params.get("DragonEnableAutoLC", encoding='utf8') == "1" else False
|
||||
# adjustable assisted lc min speed
|
||||
self.dragon_assisted_lc_min_mph = int(self.params.get("DragonAssistedLCMinMPH", encoding='utf8')) * CV.MPH_TO_MS
|
||||
if self.dragon_assisted_lc_min_mph < 0:
|
||||
self.dragon_assisted_lc_min_mph = 0
|
||||
if self.dragon_auto_lc_enabled:
|
||||
# adjustable auto lc min speed
|
||||
self.dragon_auto_lc_min_mph = int(self.params.get("DragonAutoLCMinMPH", encoding='utf8')) * CV.MPH_TO_MS
|
||||
if self.dragon_auto_lc_min_mph < 0:
|
||||
self.dragon_auto_lc_min_mph = 0
|
||||
# when auto lc is smaller than assisted lc, we set assisted lc to the same speed as auto lc
|
||||
if self.dragon_auto_lc_min_mph < self.dragon_assisted_lc_min_mph:
|
||||
self.dragon_assisted_lc_min_mph = self.dragon_auto_lc_min_mph
|
||||
# adjustable auto lc delay
|
||||
self.dragon_auto_lc_delay = int(self.params.get("DragonAutoLCDelay", encoding='utf8'))
|
||||
if self.dragon_auto_lc_delay < 0:
|
||||
self.dragon_auto_lc_delay = 0
|
||||
self.dp_last_modified = modified
|
||||
self.last_ts = cur_time
|
||||
|
||||
v_ego = sm['carState'].vEgo
|
||||
angle_steers = sm['carState'].steeringAngle
|
||||
active = sm['controlsState'].active
|
||||
@@ -92,7 +134,7 @@ class PathPlanner():
|
||||
|
||||
# Lane change logic
|
||||
one_blinker = sm['carState'].leftBlinker != sm['carState'].rightBlinker
|
||||
below_lane_change_speed = v_ego < LANE_CHANGE_SPEED_MIN
|
||||
below_lane_change_speed = v_ego < self.dragon_assisted_lc_min_mph
|
||||
|
||||
if sm['carState'].leftBlinker:
|
||||
self.lane_change_direction = LaneChangeDirection.left
|
||||
@@ -109,6 +151,27 @@ class PathPlanner():
|
||||
|
||||
lane_change_prob = self.LP.l_lane_change_prob + self.LP.r_lane_change_prob
|
||||
|
||||
# dragonpilot auto lc
|
||||
if not below_lane_change_speed and self.dragon_auto_lc_enabled and v_ego >= self.dragon_auto_lc_min_mph:
|
||||
# we allow auto lc when speed reached dragon_auto_lc_min_mph
|
||||
self.dragon_auto_lc_allowed = True
|
||||
|
||||
if self.dragon_auto_lc_timer is None:
|
||||
# we only set timer when in preLaneChange state, dragon_auto_lc_delay delay
|
||||
if self.lane_change_state == LaneChangeState.preLaneChange:
|
||||
self.dragon_auto_lc_timer = cur_time + self.dragon_auto_lc_delay
|
||||
elif cur_time >= self.dragon_auto_lc_timer:
|
||||
# if timer is up, we set torque_applied to True to fake user input
|
||||
torque_applied = True
|
||||
else:
|
||||
# if too slow, we reset all the variables
|
||||
self.dragon_auto_lc_allowed = False
|
||||
self.dragon_auto_lc_timer = None
|
||||
|
||||
# we reset the timers when torque is applied regardless
|
||||
if torque_applied:
|
||||
self.dragon_auto_lc_timer = None
|
||||
|
||||
# State transitions
|
||||
# off
|
||||
if self.lane_change_state == LaneChangeState.off and one_blinker and not self.prev_one_blinker and not below_lane_change_speed:
|
||||
@@ -132,6 +195,9 @@ class PathPlanner():
|
||||
else:
|
||||
self.lane_change_state = LaneChangeState.off
|
||||
|
||||
# when finishing, we reset timer to none.
|
||||
self.dragon_auto_lc_timer = None
|
||||
|
||||
if self.lane_change_state in [LaneChangeState.off, LaneChangeState.preLaneChange]:
|
||||
self.lane_change_timer = 0.0
|
||||
else:
|
||||
@@ -209,6 +275,7 @@ class PathPlanner():
|
||||
plan_send.pathPlan.desire = desire
|
||||
plan_send.pathPlan.laneChangeState = self.lane_change_state
|
||||
plan_send.pathPlan.laneChangeDirection = self.lane_change_direction
|
||||
plan_send.pathPlan.autoLCAllowed = self.dragon_auto_lc_allowed
|
||||
|
||||
pm.send('pathPlan', plan_send)
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ from selfdrive.controls.lib.speed_smoother import speed_smoother
|
||||
from selfdrive.controls.lib.longcontrol import LongCtrlState, MIN_CAN_SPEED
|
||||
from selfdrive.controls.lib.fcw import FCWChecker
|
||||
from selfdrive.controls.lib.long_mpc import LongitudinalMpc
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
MAX_SPEED = 255.0
|
||||
|
||||
@@ -22,33 +23,51 @@ AWARENESS_DECEL = -0.2 # car smoothly decel at .2m/s^2 when user is distract
|
||||
|
||||
# lookup tables VS speed to determine min and max accels in cruise
|
||||
# make sure these accelerations are smaller than mpc limits
|
||||
_A_CRUISE_MIN_V = [-1.0, -.8, -.67, -.5, -.30]
|
||||
_A_CRUISE_MIN_BP = [ 0., 5., 10., 20., 40.]
|
||||
_A_CRUISE_MIN_V_ECO = [-1.0, -0.7, -0.6, -0.5, -0.3]
|
||||
_A_CRUISE_MIN_V_SPORT = [-3.0, -2.6, -2.3, -2.0, -1.0]
|
||||
|
||||
_A_CRUISE_MIN_V = [-2.0, -1.5, -1.0, -0.7, -0.5]
|
||||
_A_CRUISE_MIN_BP = [0.0, 5.0, 10.0, 20.0, 55.0]
|
||||
|
||||
# need fast accel at very low speed for stop and go
|
||||
# make sure these accelerations are smaller than mpc limits
|
||||
_A_CRUISE_MAX_V = [1.2, 1.2, 0.65, .4]
|
||||
_A_CRUISE_MAX_V_FOLLOWING = [1.6, 1.6, 0.65, .4]
|
||||
_A_CRUISE_MAX_BP = [0., 6.4, 22.5, 40.]
|
||||
_A_CRUISE_MAX_V = [2.0, 2.0, 1.5, .5, .3]
|
||||
_A_CRUISE_MAX_V_ECO = [1.0, 1.5, 1.0, 0.3, 0.1]
|
||||
_A_CRUISE_MAX_V_SPORT = [3.0, 3.5, 4.0, 4.0, 4.0]
|
||||
_A_CRUISE_MAX_V_FOLLOWING = [1.3, 1.6, 1.2, .7, .3]
|
||||
_A_CRUISE_MAX_BP = [0., 5., 10., 20., 55.]
|
||||
|
||||
# Lookup table for turns
|
||||
_A_TOTAL_MAX_V = [1.7, 3.2]
|
||||
_A_TOTAL_MAX_BP = [20., 40.]
|
||||
_A_TOTAL_MAX_V = [3.3, 3.0, 3.9]
|
||||
_A_TOTAL_MAX_BP = [0., 25., 55.]
|
||||
|
||||
# 75th percentile
|
||||
SPEED_PERCENTILE_IDX = 7
|
||||
|
||||
# dragonpilot, accel profiles
|
||||
ACCEL_ECO_MODE = -1
|
||||
ACCEL_NORMAL_MODE = 0
|
||||
ACCEL_SPORT_MODE = 1
|
||||
|
||||
def calc_cruise_accel_limits(v_ego, following):
|
||||
a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
||||
def calc_cruise_accel_limits(v_ego, following, accel_profile):
|
||||
if accel_profile == ACCEL_ECO_MODE:
|
||||
a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V_ECO)
|
||||
elif accel_profile == ACCEL_SPORT_MODE:
|
||||
a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V_SPORT)
|
||||
else:
|
||||
a_cruise_min = interp(v_ego, _A_CRUISE_MIN_BP, _A_CRUISE_MIN_V)
|
||||
|
||||
if following:
|
||||
a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_FOLLOWING)
|
||||
else:
|
||||
a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V)
|
||||
if accel_profile == ACCEL_ECO_MODE:
|
||||
a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_ECO)
|
||||
elif accel_profile == ACCEL_SPORT_MODE:
|
||||
a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V_SPORT)
|
||||
else:
|
||||
a_cruise_max = interp(v_ego, _A_CRUISE_MAX_BP, _A_CRUISE_MAX_V)
|
||||
return np.vstack([a_cruise_min, a_cruise_max])
|
||||
|
||||
|
||||
def limit_accel_in_turns(v_ego, angle_steers, a_target, CP):
|
||||
"""
|
||||
This function returns a limited long acceleration allowed, depending on the existing lateral acceleration
|
||||
@@ -87,6 +106,14 @@ class Planner():
|
||||
self.params = Params()
|
||||
self.first_loop = True
|
||||
|
||||
# dragonpilot
|
||||
self.dragon_slow_on_curve = True
|
||||
self.dragon_alt_accel_profile = False
|
||||
self.dragon_fast_accel = False
|
||||
self.dragon_accel_profile = ACCEL_NORMAL_MODE
|
||||
self.last_ts = 0.
|
||||
self.dp_last_modified = None
|
||||
|
||||
def choose_solution(self, v_cruise_setpoint, enabled):
|
||||
if enabled:
|
||||
solutions = {'model': self.v_model, 'cruise': self.v_cruise}
|
||||
@@ -119,6 +146,18 @@ class Planner():
|
||||
cur_time = sec_since_boot()
|
||||
v_ego = sm['carState'].vEgo
|
||||
|
||||
# dragonpilot
|
||||
# update variable status every 5 secs
|
||||
if cur_time - self.last_ts >= 5.:
|
||||
modified = dp_get_last_modified()
|
||||
if self.dp_last_modified != modified:
|
||||
self.dragon_slow_on_curve = False if self.params.get("DragonEnableSlowOnCurve", encoding='utf8') == "0" else True
|
||||
self.dragon_accel_profile = int(self.params.get("DragonAccelProfile", encoding='utf8'))
|
||||
if self.dragon_accel_profile >= 2 or self.dragon_accel_profile <= -2:
|
||||
self.dragon_accel_profile = 0
|
||||
self.dp_last_modified = modified
|
||||
self.last_ts = cur_time
|
||||
|
||||
long_control_state = sm['controlsState'].longControlState
|
||||
v_cruise_kph = sm['controlsState'].vCruise
|
||||
force_slow_decel = sm['controlsState'].forceDecel
|
||||
@@ -130,7 +169,7 @@ class Planner():
|
||||
enabled = (long_control_state == LongCtrlState.pid) or (long_control_state == LongCtrlState.stopping)
|
||||
following = lead_1.status and lead_1.dRel < 45.0 and lead_1.vLeadK > v_ego and lead_1.aLeadK > 0.0
|
||||
|
||||
if len(sm['model'].path.poly):
|
||||
if self.dragon_slow_on_curve and len(sm['model'].path.poly):
|
||||
path = list(sm['model'].path.poly)
|
||||
|
||||
# Curvature of polynomial https://en.wikipedia.org/wiki/Curvature#Curvature_of_the_graph_of_a_function
|
||||
@@ -150,7 +189,7 @@ class Planner():
|
||||
|
||||
# Calculate speed for normal cruise control
|
||||
if enabled and not self.first_loop:
|
||||
accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, following)]
|
||||
accel_limits = [float(x) for x in calc_cruise_accel_limits(v_ego, following, self.dragon_accel_profile)]
|
||||
jerk_limits = [min(-0.1, accel_limits[0]), max(0.1, accel_limits[1])] # TODO: make a separate lookup for jerk tuning
|
||||
accel_limits_turns = limit_accel_in_turns(v_ego, sm['carState'].steeringAngle, accel_limits, self.CP)
|
||||
|
||||
|
||||
+20
-3
@@ -3,7 +3,9 @@ import os
|
||||
import sys
|
||||
import threading
|
||||
import capnp
|
||||
from selfdrive.version import version, dirty
|
||||
from common.params import Params
|
||||
from selfdrive.version import version, dirty, origin, branch
|
||||
uniqueID = Params().get('DongleId', None)
|
||||
|
||||
from selfdrive.swaglog import cloudlog
|
||||
|
||||
@@ -19,8 +21,15 @@ if os.getenv("NOLOG") or os.getenv("NOCRASH"):
|
||||
else:
|
||||
from raven import Client
|
||||
from raven.transport.http import HTTPTransport
|
||||
client = Client('https://1994756b5e6f41cf939a4c65de45f4f2:cefebaf3a8aa40d182609785f7189bd7@app.getsentry.com/77924',
|
||||
install_sys_hook=False, transport=HTTPTransport, release=version, tags={'dirty': dirty})
|
||||
params = Params()
|
||||
try:
|
||||
dongle_id = params.get("DongleId").decode('utf8')
|
||||
except AttributeError:
|
||||
dongle_id = "None"
|
||||
error_tags = {'dirty': dirty, 'username': uniqueID, 'dongle_id': dongle_id, 'branch': branch, 'remote': origin}
|
||||
|
||||
client = Client('https://980a0cba712a4c3593c33c78a12446e1:fecab286bcaf4dba8b04f7cff0188e2d@sentry.io/1488600',
|
||||
install_sys_hook=False, transport=HTTPTransport, release=version, tags=error_tags)
|
||||
|
||||
def capture_exception(*args, **kwargs):
|
||||
exc_info = sys.exc_info()
|
||||
@@ -31,6 +40,14 @@ else:
|
||||
def bind_user(**kwargs):
|
||||
client.user_context(kwargs)
|
||||
|
||||
def capture_warning(warning_string):
|
||||
bind_user(id=dongle_id)
|
||||
client.captureMessage(warning_string, level='warning')
|
||||
|
||||
def capture_info(info_string):
|
||||
bind_user(id=dongle_id)
|
||||
client.captureMessage(info_string, level='info')
|
||||
|
||||
def bind_extra(**kwargs):
|
||||
client.extra_context(kwargs)
|
||||
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
The MIT License
|
||||
|
||||
Copyright (c) 2019-, Rick Lan, dragonpilot community, and a number of other of contributors.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
@@ -0,0 +1,391 @@
|
||||
#!/usr/bin/env python3
|
||||
import time
|
||||
import subprocess
|
||||
import cereal
|
||||
import cereal.messaging as messaging
|
||||
ThermalStatus = cereal.log.ThermalData.ThermalStatus
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from common.realtime import sec_since_boot
|
||||
from common.params import Params, put_nonblocking
|
||||
params = Params()
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
from math import floor
|
||||
|
||||
class App():
|
||||
|
||||
# app type
|
||||
TYPE_GPS = 0
|
||||
TYPE_SERVICE = 1
|
||||
TYPE_GPS_SERVICE = 2
|
||||
TYPE_FULLSCREEN = 3
|
||||
TYPE_UTIL = 4
|
||||
|
||||
# frame app
|
||||
FRAME = "ai.comma.plus.frame"
|
||||
FRAME_MAIN = ".MainActivity"
|
||||
|
||||
# offroad app
|
||||
OFFROAD = "ai.comma.plus.offroad"
|
||||
OFFROAD_MAIN = ".MainActivity"
|
||||
|
||||
# manual switch stats
|
||||
MANUAL_OFF = "-1"
|
||||
MANUAL_IDLE = "0"
|
||||
MANUAL_ON = "1"
|
||||
|
||||
def appops_set(self, package, op, mode):
|
||||
self.system(f"LD_LIBRARY_PATH= appops set {package} {op} {mode}")
|
||||
|
||||
def pm_grant(self, package, permission):
|
||||
self.system(f"pm grant {package} {permission}")
|
||||
|
||||
def set_package_permissions(self):
|
||||
if self.permissions is not None:
|
||||
for permission in self.permissions:
|
||||
self.pm_grant(self.app, permission)
|
||||
if self.opts is not None:
|
||||
for opt in self.opts:
|
||||
self.appops_set(self.app, opt, "allow")
|
||||
|
||||
def __init__(self, app, activity, enable_param, auto_run_param, manual_ctrl_param, app_type, permissions, opts):
|
||||
self.app = app
|
||||
# main activity
|
||||
self.activity = activity
|
||||
# read enable param
|
||||
self.enable_param = enable_param
|
||||
# read auto run param
|
||||
self.auto_run_param = auto_run_param
|
||||
# read manual run param
|
||||
self.manual_ctrl_param = manual_ctrl_param
|
||||
# if it's a service app, we do not kill if device is too hot
|
||||
# if it's a full screen app, we need to do extra process on frame/offroad
|
||||
self.app_type = app_type
|
||||
# app permissions
|
||||
self.permissions = permissions
|
||||
# app options
|
||||
self.opts = opts
|
||||
|
||||
self.is_enabled = False
|
||||
self.last_is_enabled = False
|
||||
self.is_auto_runnable = False
|
||||
self.is_running = False
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
self.manually_ctrled = False
|
||||
|
||||
self.set_package_permissions()
|
||||
self.system("pm disable %s" % self.app)
|
||||
if self.manual_ctrl_param is not None:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
self.last_ts = sec_since_boot()
|
||||
|
||||
def read_params(self):
|
||||
self.last_is_enabled = self.is_enabled
|
||||
if self.enable_param is None:
|
||||
self.is_enabled = False
|
||||
else:
|
||||
self.is_enabled = True if params.get(self.enable_param, encoding='utf8') == "1" else False
|
||||
|
||||
if self.is_enabled:
|
||||
# a service app should run automatically and not manual controllable.
|
||||
if self.app_type in [App.TYPE_SERVICE, App.TYPE_GPS_SERVICE]:
|
||||
self.is_auto_runnable = True
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
else:
|
||||
if self.manual_ctrl_param is None:
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
else:
|
||||
self.manual_ctrl_status = params.get(self.manual_ctrl_param, encoding='utf8')
|
||||
|
||||
if self.manual_ctrl_status == self.MANUAL_IDLE:
|
||||
if self.auto_run_param is None:
|
||||
self.is_auto_runnable = False
|
||||
else:
|
||||
self.is_auto_runnable = True if params.get(self.auto_run_param, encoding='utf8') == "1" else False
|
||||
else:
|
||||
self.is_auto_runnable = False
|
||||
self.manual_ctrl_status = self.MANUAL_IDLE
|
||||
self.manually_ctrled = False
|
||||
|
||||
def run(self, force = False):
|
||||
if force or self.is_enabled:
|
||||
# app is manually ctrl, we record that
|
||||
if self.manual_ctrl_param is not None and self.manual_ctrl_status == self.MANUAL_ON:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
put_nonblocking('DragonLastModified', str(floor(time.time())))
|
||||
self.manually_ctrled = True
|
||||
self.is_running = False
|
||||
|
||||
# only run app if it's not running
|
||||
if force or not self.is_running:
|
||||
# if it's a full screen app, we need to stop frame and offroad to get keyboard access
|
||||
if self.app_type == self.TYPE_FULLSCREEN:
|
||||
self.system("pm disable %s" % self.FRAME)
|
||||
self.system("am start -n %s/%s" % (self.OFFROAD, self.OFFROAD_MAIN))
|
||||
|
||||
self.system("pm enable %s" % self.app)
|
||||
|
||||
if self.app_type == self.TYPE_GPS_SERVICE:
|
||||
self.appops_set(self.app, "android:mock_location", "allow")
|
||||
|
||||
if self.app_type in [self.TYPE_SERVICE, self.TYPE_GPS_SERVICE]:
|
||||
self.system("am startservice %s/%s" % (self.app, self.activity))
|
||||
else:
|
||||
self.system("am start -n %s/%s" % (self.app, self.activity))
|
||||
self.is_running = True
|
||||
|
||||
def kill(self, force = False):
|
||||
if force or self.is_enabled:
|
||||
# app is manually ctrl, we record that
|
||||
if self.manual_ctrl_param is not None and self.manual_ctrl_status == self.MANUAL_OFF:
|
||||
put_nonblocking(self.manual_ctrl_param, '0')
|
||||
self.manually_ctrled = True
|
||||
self.is_running = True
|
||||
|
||||
# only kill app if it's running
|
||||
if force or self.is_running:
|
||||
# if it's a full screen app, we need to restart offroad and frame
|
||||
if self.app_type == self.TYPE_FULLSCREEN:
|
||||
self.system("pm disable %s" % self.OFFROAD)
|
||||
self.system("pm enable %s" % self.OFFROAD)
|
||||
self.system("pm enable %s" % self.FRAME)
|
||||
self.system("am start -n %s/%s" % (self.FRAME, self.FRAME_MAIN))
|
||||
|
||||
if self.app_type == self.TYPE_GPS_SERVICE:
|
||||
self.appops_set(self.app, "android:mock_location", "deny")
|
||||
|
||||
self.system("pkill %s" % self.app)
|
||||
self.is_running = False
|
||||
|
||||
def system(self, cmd):
|
||||
try:
|
||||
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)
|
||||
|
||||
def init_apps(apps):
|
||||
apps.append(App(
|
||||
"cn.dragonpilot.gpsservice",
|
||||
"cn.dragonpilot.gpsservice.MainService",
|
||||
"DragonGreyPandaMode",
|
||||
None,
|
||||
None,
|
||||
App.TYPE_GPS_SERVICE,
|
||||
[],
|
||||
[],
|
||||
))
|
||||
apps.append(App(
|
||||
# v1.16.2
|
||||
"com.tomtom.speedcams.android.map",
|
||||
"com.tomtom.speedcams.android.activities.SpeedCamActivity",
|
||||
"DragonEnableTomTom",
|
||||
"DragonBootTomTom",
|
||||
"DragonRunTomTom",
|
||||
App.TYPE_GPS,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[
|
||||
"SYSTEM_ALERT_WINDOW",
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v4.5.0.600053
|
||||
"com.autonavi.amapauto",
|
||||
"com.autonavi.amapauto.MainMapActivity",
|
||||
"DragonEnableAutonavi",
|
||||
"DragonBootAutonavi",
|
||||
"DragonRunAutonavi",
|
||||
App.TYPE_GPS,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[
|
||||
"SYSTEM_ALERT_WINDOW",
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v6.40.3
|
||||
"com.mixplorer",
|
||||
"com.mixplorer.activities.BrowseActivity",
|
||||
"DragonEnableMixplorer",
|
||||
None,
|
||||
"DragonRunMixplorer",
|
||||
App.TYPE_UTIL,
|
||||
[
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[],
|
||||
))
|
||||
apps.append(App(
|
||||
# v2.9.5 build 74
|
||||
"tw.com.ainvest.outpack",
|
||||
"tw.com.ainvest.outpack.ui.MainActivity",
|
||||
"DragonEnableAegis",
|
||||
"DragonBootAegis",
|
||||
"DragonRunAegis",
|
||||
App.TYPE_GPS,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
],
|
||||
[
|
||||
"SYSTEM_ALERT_WINDOW",
|
||||
]
|
||||
))
|
||||
apps.append(App(
|
||||
# v4.57.2.0
|
||||
"com.waze",
|
||||
"com.waze.MainActivity",
|
||||
"DragonWazeMode",
|
||||
None,
|
||||
"DragonRunWaze",
|
||||
App.TYPE_FULLSCREEN,
|
||||
[
|
||||
"android.permission.ACCESS_FINE_LOCATION",
|
||||
"android.permission.ACCESS_COARSE_LOCATION",
|
||||
"android.permission.READ_EXTERNAL_STORAGE",
|
||||
"android.permission.WRITE_EXTERNAL_STORAGE",
|
||||
"android.permission.RECORD_AUDIO",
|
||||
],
|
||||
[],
|
||||
))
|
||||
|
||||
def main():
|
||||
apps = []
|
||||
|
||||
# enable hotspot on boot
|
||||
if params.get("DragonBootHotspot", encoding='utf8') == "1":
|
||||
system(f"settings put system accelerometer_rotation 0")
|
||||
system(f"settings put system user_rotation 1")
|
||||
system(f"pm enable com.android.settings")
|
||||
system(f"am start -n com.android.settings/.TetherSettings")
|
||||
time.sleep(1)
|
||||
system(f"LD_LIBRARY_PATH= input tap 995 160")
|
||||
system(f"pkill com.android.settings")
|
||||
|
||||
last_started = False
|
||||
thermal_sock = messaging.sub_sock('thermal')
|
||||
|
||||
frame = 0
|
||||
start_delay = None
|
||||
stop_delay = None
|
||||
allow_auto_run = True
|
||||
last_thermal_status = None
|
||||
thermal_status = None
|
||||
start_ts = sec_since_boot()
|
||||
init_done = False
|
||||
last_modified = None
|
||||
|
||||
while 1: #has_enabled_apps:
|
||||
if not init_done and sec_since_boot() - start_ts >= 10:
|
||||
init_apps(apps)
|
||||
init_done = True
|
||||
|
||||
if init_done:
|
||||
enabled_apps = []
|
||||
has_fullscreen_apps = False
|
||||
modified = dp_get_last_modified()
|
||||
for app in apps:
|
||||
# read params loop
|
||||
if last_modified != modified:
|
||||
app.read_params()
|
||||
if app.last_is_enabled and not app.is_enabled and app.is_running:
|
||||
app.kill(True)
|
||||
|
||||
if app.is_enabled:
|
||||
if not has_fullscreen_apps and app.app_type == App.TYPE_FULLSCREEN:
|
||||
has_fullscreen_apps = True
|
||||
|
||||
# process manual ctrl apps
|
||||
if app.manual_ctrl_status != App.MANUAL_IDLE:
|
||||
app.run(True) if app.manual_ctrl_status == App.MANUAL_ON else app.kill(True)
|
||||
|
||||
enabled_apps.append(app)
|
||||
last_modified = modified
|
||||
msg = messaging.recv_sock(thermal_sock, wait=True)
|
||||
started = msg.thermal.started
|
||||
# when car is running
|
||||
if started:
|
||||
stop_delay = None
|
||||
# apps start 5 secs later
|
||||
if start_delay is None:
|
||||
start_delay = frame + 5
|
||||
|
||||
thermal_status = msg.thermal.thermalStatus
|
||||
if thermal_status <= ThermalStatus.yellow:
|
||||
allow_auto_run = True
|
||||
# when temp reduce from red to yellow, we add start up delay as well
|
||||
# so apps will not start up immediately
|
||||
if last_thermal_status == ThermalStatus.red:
|
||||
start_delay = frame + 60
|
||||
elif thermal_status >= ThermalStatus.red:
|
||||
allow_auto_run = False
|
||||
|
||||
last_thermal_status = thermal_status
|
||||
|
||||
# we run service apps and kill all util apps
|
||||
# only run once
|
||||
if last_started != started:
|
||||
for app in enabled_apps:
|
||||
if app.app_type in [App.TYPE_SERVICE, App.TYPE_GPS_SERVICE]:
|
||||
app.run()
|
||||
elif app.app_type == App.TYPE_UTIL:
|
||||
app.kill()
|
||||
|
||||
# only run apps that's not manually ctrled
|
||||
for app in enabled_apps:
|
||||
if not app.manually_ctrled:
|
||||
if has_fullscreen_apps:
|
||||
if app.app_type == App.TYPE_FULLSCREEN:
|
||||
app.run()
|
||||
elif app.app_type in [App.TYPE_GPS, App.TYPE_UTIL]:
|
||||
app.kill()
|
||||
else:
|
||||
if not allow_auto_run:
|
||||
app.kill()
|
||||
else:
|
||||
if frame >= start_delay and app.is_auto_runnable and app.app_type == App.TYPE_GPS:
|
||||
app.run()
|
||||
# when car is stopped
|
||||
else:
|
||||
start_delay = None
|
||||
# set delay to 30 seconds
|
||||
if stop_delay is None:
|
||||
stop_delay = frame + 30
|
||||
|
||||
for app in enabled_apps:
|
||||
if app.is_running and not app.manually_ctrled:
|
||||
if has_fullscreen_apps or frame >= stop_delay:
|
||||
app.kill()
|
||||
|
||||
if last_started != started:
|
||||
for app in enabled_apps:
|
||||
app.manually_ctrled = False
|
||||
|
||||
last_started = started
|
||||
frame += 3
|
||||
time.sleep(3)
|
||||
|
||||
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)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,80 @@
|
||||
#!/usr/bin/env python3
|
||||
#
|
||||
# courtesy of pjlao307 (https://github.com/pjlao307/)
|
||||
# this is just his original implementation but
|
||||
# in openpilot service form so it's always on
|
||||
#
|
||||
# with the highest bit rates, the video is approx. 0.5MB per second
|
||||
# the default value is set to 2.56Mbps = 0.32MB per second
|
||||
#
|
||||
import os
|
||||
import time
|
||||
import datetime
|
||||
import cereal.messaging as messaging
|
||||
import subprocess
|
||||
from selfdrive.swaglog import cloudlog
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
|
||||
dashcam_videos = '/sdcard/dashcam/'
|
||||
duration = 60 # max is 180
|
||||
bit_rates = 2560000 # max is 4000000
|
||||
max_size_per_file = bit_rates/8*duration # 2.56Mbps / 8 * 60 = 19.2MB per 60 seconds
|
||||
max_storage = max_size_per_file/duration*60*60*6 # 6 hours worth of footage (around 7gb)
|
||||
freespace_limit = 0.15 # we start cleaning up footage when freespace is below 15%
|
||||
|
||||
def main(gctx=None):
|
||||
if not os.path.exists(dashcam_videos):
|
||||
os.makedirs(dashcam_videos)
|
||||
|
||||
thermal_sock = messaging.sub_sock('thermal')
|
||||
while 1:
|
||||
if params.get("DragonEnableDashcam", encoding='utf8') == "1":
|
||||
now = datetime.datetime.now()
|
||||
file_name = now.strftime("%Y-%m-%d_%H-%M-%S")
|
||||
os.system("screenrecord --bit-rate %s --time-limit %s %s%s.mp4 &" % (bit_rates, duration, dashcam_videos, file_name))
|
||||
start_time = time.time()
|
||||
try:
|
||||
used_spaces = get_used_spaces()
|
||||
last_used_spaces = used_spaces
|
||||
|
||||
# we should clean up files here if use too much spaces
|
||||
# when used spaces greater than max available storage
|
||||
# or when free space is less than 10%
|
||||
# get health of board, log this in "thermal"
|
||||
msg = messaging.recv_sock(thermal_sock, wait=True)
|
||||
if used_spaces >= max_storage or (msg is not None and msg.thermal.freeSpace < freespace_limit):
|
||||
# get all the files in the dashcam_videos path
|
||||
files = [f for f in sorted(os.listdir(dashcam_videos)) if os.path.isfile(dashcam_videos + f)]
|
||||
for file in files:
|
||||
msg = messaging.recv_sock(thermal_sock, wait=True)
|
||||
# delete file one by one and once it has enough space for 1 video, we stop deleting
|
||||
if used_spaces - last_used_spaces < max_size_per_file or msg.thermal.freeSpace < freespace_limit:
|
||||
system("rm -fr %s" % (dashcam_videos + file))
|
||||
last_used_spaces = get_used_spaces()
|
||||
else:
|
||||
break
|
||||
except os.error as e:
|
||||
pass
|
||||
time_diff = int(time.time()-start_time)
|
||||
# we start the process 1 second before screenrecord ended
|
||||
# to make sure there are no missing footage
|
||||
time.sleep(duration-1-time_diff)
|
||||
else:
|
||||
time.sleep(5)
|
||||
|
||||
def get_used_spaces():
|
||||
return sum(os.path.getsize(dashcam_videos + f) for f in os.listdir(dashcam_videos) if os.path.isfile(dashcam_videos + f))
|
||||
|
||||
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)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,111 @@
|
||||
#!/usr/bin/env python2.7
|
||||
from common.params import Params, put_nonblocking
|
||||
import time
|
||||
from math import floor
|
||||
|
||||
default_conf = {
|
||||
'DragonEnableDashcam': '0',
|
||||
'DragonEnableDriverSafetyCheck': '1',
|
||||
'DragonEnableAutoShutdown': '1',
|
||||
'DragonAutoShutdownAt': '0', # in minute
|
||||
'DragonEnableSteeringOnSignal': '0',
|
||||
'DragonEnableLogger': '1',
|
||||
'DragonEnableUploader': '1',
|
||||
'DragonNoctuaMode': '0',
|
||||
'DragonCacheCar': '0',
|
||||
'DragonCachedModel': '', # for cache car
|
||||
'DragonCachedFP': '', # for cache car
|
||||
'DragonCachedVIN': '', # for cache car
|
||||
'DragonCachedCarFW': '', # for cache car
|
||||
'DragonCachedSource': '', # for cache car
|
||||
'DragonAllowGas': '0',
|
||||
'DragonToyotaStockDSU': '0',
|
||||
'DragonLatCtrl': '1',
|
||||
'DragonUISpeed': '1',
|
||||
'DragonUIEvent': '1',
|
||||
'DragonUIMaxSpeed': '1',
|
||||
'DragonUIFace': '1',
|
||||
'DragonUIDev': '0',
|
||||
'DragonUIDevMini': '0',
|
||||
# 3rd party app
|
||||
'DragonEnableTomTom': '0',
|
||||
'DragonBootTomTom': '0',
|
||||
'DragonRunTomTom': '0',
|
||||
'DragonEnableAutonavi': '0',
|
||||
'DragonBootAutonavi': '0',
|
||||
'DragonRunAutonavi': '0',
|
||||
'DragonEnableAegis': '0',
|
||||
'DragonBootAegis': '0',
|
||||
'DragonRunAegis': '0',
|
||||
'DragonEnableMixplorer': '0',
|
||||
'DragonRunMixplorer': '0',
|
||||
'DragonSteeringMonitorTimer': '3', # 180 secs
|
||||
'DragonCameraOffset': '6',
|
||||
'DragonUIVolumeBoost': '0',
|
||||
'DragonGreyPandaMode': '0',
|
||||
'DragonDrivingUI': '1',
|
||||
'DragonDisplaySteeringLimitAlert': '1',
|
||||
'DragonChargingCtrl': '0',
|
||||
'DragonCharging': 70,
|
||||
'DragonDisCharging': 60,
|
||||
'DragonToyotaLaneDepartureWarning': '1',
|
||||
'DragonUILane': '1',
|
||||
'DragonUILead': '1',
|
||||
'DragonUIPath': '1',
|
||||
'DragonUIBlinker': '0',
|
||||
'DragonUIDMView': '0',
|
||||
'DragonEnableDriverMonitoring': '1',
|
||||
'DragonCarModel': '',
|
||||
'DragonEnableSlowOnCurve': '1',
|
||||
'DragonEnableLeadCarMovingAlert': '0',
|
||||
'DragonToyotaSnGMod': '0',
|
||||
'DragonEnableSRLearner': '1',
|
||||
'DragonWazeMode': '0',
|
||||
'DragonRunWaze': '0',
|
||||
'DragonEnableAutoLC': '0',
|
||||
'DragonAssistedLCMinMPH': 45,
|
||||
'DragonAutoLCMinMPH': 60,
|
||||
'DragonAutoLCDelay': 2,
|
||||
'DragonBTG': 0,
|
||||
'DragonBootHotspot': 0,
|
||||
'DragonAccelProfile': '0',
|
||||
'DragonLastModified': str(floor(time.time()))
|
||||
}
|
||||
|
||||
deprecated_conf = {
|
||||
}
|
||||
|
||||
deprecated_conf_invert = {
|
||||
# 'DragonDisableDriverSafetyCheck': True,
|
||||
# 'DragonTempDisableSteerOnSignal': False,
|
||||
# 'DragonDisableLogger': True,
|
||||
# 'DragonDisableUploader': True,
|
||||
# 'DragonBBUI': False
|
||||
}
|
||||
|
||||
def dp_get_last_modified():
|
||||
return Params().get('DragonLastModified', encoding='utf-8')
|
||||
|
||||
def dragonpilot_set_params(params):
|
||||
# # remove deprecated params
|
||||
# for old, new in deprecated_conf.items():
|
||||
# if params.get(old) is not None:
|
||||
# if new is not None:
|
||||
# old_val = str(params.get(old))
|
||||
# new_val = old_val
|
||||
# # invert the value if true
|
||||
# if old in deprecated_conf_invert and deprecated_conf_invert[old] is True:
|
||||
# new_val = "1" if old_val == "0" else "0"
|
||||
# put_nonblocking(new, new_val)
|
||||
# params.delete(old)
|
||||
|
||||
# set params
|
||||
for key, val in default_conf.items():
|
||||
if params.get(key) is None and key not in deprecated_conf:
|
||||
put_nonblocking(key, str(val))
|
||||
|
||||
if __name__ == "__main__":
|
||||
params = Params()
|
||||
params.manager_start()
|
||||
|
||||
dragonpilot_set_params(params)
|
||||
Binary file not shown.
BIN
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python2.7
|
||||
#
|
||||
# I had a few incidents where OP suddenly stopped while cruising.
|
||||
# This script is used to detect such event
|
||||
#
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
import zmq
|
||||
from selfdrive.services import service_list
|
||||
import selfdrive.messaging as messaging
|
||||
|
||||
mediaplayer = '/data/openpilot/selfdrive/dragonpilot/mediaplayer/'
|
||||
|
||||
def main(gctx=None):
|
||||
|
||||
poller = zmq.Poller()
|
||||
sock = messaging.sub_sock(service_list['controlsState'].port, poller)
|
||||
poller.poll(timeout=1000)
|
||||
|
||||
last_v_ego = 0.
|
||||
last_active = False
|
||||
|
||||
env = dict(os.environ)
|
||||
env['LD_LIBRARY_PATH'] = mediaplayer
|
||||
|
||||
while 1:
|
||||
|
||||
v_ego = 0
|
||||
active = False
|
||||
controls_state = messaging.recv_sock(sock, wait=True)
|
||||
|
||||
if controls_state is not None:
|
||||
v_ego = controls_state.controlsState.vEgo
|
||||
active = controls_state.controlsState.active
|
||||
|
||||
# we are driving and all of sudden we dont have any speed at all
|
||||
# we better warn the driver before it's too late
|
||||
if last_active and last_v_ego >= 5 and v_ego == 0:
|
||||
subprocess.Popen([mediaplayer + 'mediaplayer', '/data/openpilot/selfdrive/dragonpilot/safeguardd/error.wav'], shell = False, stdin=None, stdout=None, stderr=None, env = env, close_fds=True)
|
||||
|
||||
last_active = active
|
||||
last_v_ego = v_ego
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,49 @@
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import time
|
||||
from common.params import Params
|
||||
params = Params()
|
||||
import cereal.messaging as messaging
|
||||
from common.realtime import sec_since_boot
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
def main():
|
||||
thermal_sock = messaging.sub_sock('thermal')
|
||||
last_ts = 0
|
||||
secs = 0
|
||||
last_secs = None
|
||||
shutdown_at = 0
|
||||
started = False
|
||||
usb_online = False
|
||||
enabled = False
|
||||
last_enabled = None
|
||||
dp_last_modified = None
|
||||
while 1:
|
||||
cur_time = sec_since_boot()
|
||||
if cur_time - last_ts >= 10.:
|
||||
modified = dp_get_last_modified()
|
||||
if dp_last_modified != modified:
|
||||
enabled = True if params.get("DragonEnableAutoShutdown", encoding='utf8') == '1' else False
|
||||
if enabled:
|
||||
secs = int(params.get("DragonAutoShutdownAt", encoding='utf8')) * 60
|
||||
|
||||
dp_last_modified = modified
|
||||
|
||||
if enabled:
|
||||
msg = messaging.recv_sock(thermal_sock, wait=True)
|
||||
started = msg.thermal.started
|
||||
usb_online = msg.thermal.usbOnline
|
||||
|
||||
if last_enabled != enabled or last_secs != secs or started or usb_online:
|
||||
shutdown_at = cur_time + secs
|
||||
|
||||
last_enabled = enabled
|
||||
last_secs = secs
|
||||
last_ts = cur_time
|
||||
|
||||
if enabled and not started and not usb_online and secs > 0 and cur_time >= shutdown_at:
|
||||
os.system('LD_LIBRARY_PATH="" svc power shutdown')
|
||||
time.sleep(10)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -44,7 +44,7 @@ ParamsLearner::ParamsLearner(cereal::CarParams::Reader car_params,
|
||||
alpha4 = 1.0 * learning_rate;
|
||||
}
|
||||
|
||||
bool ParamsLearner::update(double psi, double u, double sa) {
|
||||
bool ParamsLearner::update(double psi, double u, double sa, bool enable_sr_learner) {
|
||||
if (u > 10.0 && fabs(sa) < (DEGREES_TO_RADIANS * 90.)) {
|
||||
double ao_diff = 2.0*cF0*cR0*l*u*x*(1.0*cF0*cR0*l*u*x*(ao - sa) + psi*sR*(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0)))/(pow(sR, 2)*pow(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0), 2));
|
||||
double new_ao = ao - alpha1 * ao_diff;
|
||||
@@ -54,6 +54,9 @@ bool ParamsLearner::update(double psi, double u, double sa) {
|
||||
|
||||
double new_x = x - alpha3 * (-2.0*cF0*cR0*l*m*pow(u, 3)*(slow_ao - sa)*(aF*cF0 - aR*cR0)*(1.0*cF0*cR0*l*u*x*(slow_ao - sa) + psi*sR*(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0)))/(pow(sR, 2)*pow(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0), 3)));
|
||||
double new_sR = sR - alpha4 * (-2.0*cF0*cR0*l*u*x*(slow_ao - sa)*(1.0*cF0*cR0*l*u*x*(slow_ao - sa) + psi*sR*(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0)))/(pow(sR, 3)*pow(cF0*cR0*pow(l, 2)*x - m*pow(u, 2)*(aF*cF0 - aR*cR0), 2)));
|
||||
if (!enable_sr_learner) {
|
||||
new_sR = sR;
|
||||
}
|
||||
|
||||
ao = new_ao;
|
||||
slow_ao = new_slow_ao;
|
||||
@@ -69,12 +72,16 @@ bool ParamsLearner::update(double psi, double u, double sa) {
|
||||
ao = clip(ao, -MAX_ANGLE_OFFSET, MAX_ANGLE_OFFSET);
|
||||
slow_ao = clip(slow_ao, -MAX_ANGLE_OFFSET, MAX_ANGLE_OFFSET);
|
||||
x = clip(x, MIN_STIFFNESS, MAX_STIFFNESS);
|
||||
sR = clip(sR, min_sr, max_sr);
|
||||
if (enable_sr_learner) {
|
||||
sR = clip(sR, min_sr, max_sr);
|
||||
|
||||
bool valid = fabs(slow_ao) < MAX_ANGLE_OFFSET_TH;
|
||||
valid = valid && sR > min_sr_th;
|
||||
valid = valid && sR < max_sr_th;
|
||||
return valid;
|
||||
bool valid = fabs(slow_ao) < MAX_ANGLE_OFFSET_TH;
|
||||
valid = valid && sR > min_sr_th;
|
||||
valid = valid && sR < max_sr_th;
|
||||
return valid;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,7 +100,7 @@ extern "C" {
|
||||
|
||||
bool params_learner_update(void * params_learner, double psi, double u, double sa) {
|
||||
ParamsLearner * p = (ParamsLearner*) params_learner;
|
||||
return p->update(psi, u, sa);
|
||||
return p->update(psi, u, sa, true);
|
||||
}
|
||||
|
||||
double params_learner_get_ao(void * params_learner){
|
||||
|
||||
@@ -31,5 +31,5 @@ public:
|
||||
double steer_ratio,
|
||||
double learning_rate);
|
||||
|
||||
bool update(double psi, double u, double sa);
|
||||
bool update(double psi, double u, double sa, bool enable_sr_learner);
|
||||
};
|
||||
|
||||
@@ -103,6 +103,18 @@ int main(int argc, char *argv[]) {
|
||||
|
||||
// Main loop
|
||||
int save_counter = 0;
|
||||
|
||||
// dragonpilot
|
||||
// Steer Ratio Learner
|
||||
char* enable_sr_learner_val = NULL;
|
||||
read_db_value(NULL, "DragonEnableSRLearner", &enable_sr_learner_val, NULL);
|
||||
bool enable_sr_learner = true;
|
||||
if (enable_sr_learner_val && strlen(enable_sr_learner_val) && enable_sr_learner_val[0] == '1') {
|
||||
enable_sr_learner = true;
|
||||
} else {
|
||||
enable_sr_learner = false;
|
||||
}
|
||||
|
||||
while (true){
|
||||
for (auto s : poller->poll(100)){
|
||||
Message * msg = s->receive();
|
||||
@@ -127,7 +139,7 @@ int main(int argc, char *argv[]) {
|
||||
save_counter++;
|
||||
|
||||
double yaw_rate = -localizer.x[0];
|
||||
bool valid = learner.update(yaw_rate, localizer.car_speed, localizer.steering_angle);
|
||||
bool valid = learner.update(yaw_rate, localizer.car_speed, localizer.steering_angle, enable_sr_learner);
|
||||
|
||||
// TODO: Fix in replay
|
||||
double sensor_data_age = localizer.controls_state_time - localizer.sensor_data_time;
|
||||
|
||||
@@ -8,6 +8,7 @@ import signal
|
||||
import shutil
|
||||
import subprocess
|
||||
import datetime
|
||||
from selfdrive.dragonpilot.dragonconf import dragonpilot_set_params
|
||||
|
||||
from common.basedir import BASEDIR, PARAMS
|
||||
from common.android import ANDROID
|
||||
@@ -158,6 +159,9 @@ managed_processes = {
|
||||
"updated": "selfdrive.updated",
|
||||
"dmonitoringmodeld": ("selfdrive/modeld", ["./dmonitoringmodeld"]),
|
||||
"modeld": ("selfdrive/modeld", ["./modeld"]),
|
||||
"dashcamd": "selfdrive.dragonpilot.dashcamd.dashcamd",
|
||||
"shutdownd": "selfdrive.dragonpilot.shutdownd.shutdownd",
|
||||
"appd": "selfdrive.dragonpilot.appd.appd",
|
||||
}
|
||||
|
||||
daemon_processes = {
|
||||
@@ -191,6 +195,8 @@ if ANDROID:
|
||||
'logcatd',
|
||||
'tombstoned',
|
||||
'updated',
|
||||
'shutdownd',
|
||||
'appd',
|
||||
]
|
||||
|
||||
car_started_processes = [
|
||||
@@ -214,6 +220,7 @@ if ANDROID:
|
||||
'gpsd',
|
||||
'dmonitoringmodeld',
|
||||
'deleter',
|
||||
'dashcamd',
|
||||
]
|
||||
|
||||
def register_managed_process(name, desc, car_started=False):
|
||||
@@ -510,6 +517,8 @@ def main():
|
||||
if params.get("LaneChangeEnabled") is None:
|
||||
params.put("LaneChangeEnabled", "1")
|
||||
|
||||
dragonpilot_set_params(params)
|
||||
|
||||
# is this chffrplus?
|
||||
if os.getenv("PASSIVE") is not None:
|
||||
params.put("Passive", str(int(os.getenv("PASSIVE"))))
|
||||
@@ -526,6 +535,13 @@ def main():
|
||||
if os.getenv("PREPAREONLY") is not None:
|
||||
return
|
||||
|
||||
if params.get("DragonEnableLogger", encoding='utf8') == "0":
|
||||
del managed_processes['loggerd']
|
||||
del managed_processes['tombstoned']
|
||||
|
||||
if params.get("DragonEnableUploader", encoding='utf8') == "0":
|
||||
del managed_processes['uploader']
|
||||
|
||||
# SystemExit on sigterm
|
||||
signal.signal(signal.SIGTERM, lambda signum, frame: sys.exit(1))
|
||||
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ from panda import Panda, PandaDFU, BASEDIR, build_st
|
||||
|
||||
def get_firmware_fn():
|
||||
signed_fn = os.path.join(BASEDIR, "board", "obj", "panda.bin.signed")
|
||||
if os.path.exists(signed_fn):
|
||||
if False: #os.path.exists(signed_fn):
|
||||
cloudlog.info("Using prebuilt signed firmware")
|
||||
return signed_fn
|
||||
else:
|
||||
|
||||
+97
-37
@@ -9,7 +9,7 @@ from smbus2 import SMBus
|
||||
from cereal import log
|
||||
from common.android import ANDROID, get_network_type
|
||||
from common.basedir import BASEDIR
|
||||
from common.params import Params
|
||||
from common.params import Params, put_nonblocking
|
||||
from common.realtime import sec_since_boot, DT_TRML
|
||||
from common.numpy_fast import clip, interp
|
||||
from common.filter_simple import FirstOrderFilter
|
||||
@@ -21,6 +21,11 @@ from selfdrive.pandad import get_expected_signature
|
||||
|
||||
FW_SIGNATURE = get_expected_signature()
|
||||
|
||||
params = Params()
|
||||
import subprocess
|
||||
import re
|
||||
from selfdrive.dragonpilot.dragonconf import dp_get_last_modified
|
||||
|
||||
ThermalStatus = log.ThermalData.ThermalStatus
|
||||
NetworkType = log.ThermalData.NetworkType
|
||||
CURRENT_TAU = 15. # 15s time constant
|
||||
@@ -107,6 +112,9 @@ _TEMP_THRS_L = [42.5, 57.5, 72.5, 10000]
|
||||
_FAN_SPEEDS = [0, 16384, 32768, 65535]
|
||||
# max fan speed only allowed if battery is hot
|
||||
_BAT_TEMP_THERSHOLD = 45.
|
||||
if params.get('DragonNoctuaMode', encoding='utf8') == "1":
|
||||
_FAN_SPEEDS = [65535, 65535, 65535, 65535]
|
||||
_BAT_TEMP_THERSHOLD = 20.
|
||||
|
||||
|
||||
def handle_fan_eon(max_cpu_temp, bat_temp, fan_speed, ignition):
|
||||
@@ -176,7 +184,16 @@ def thermald_thread():
|
||||
setup_eon_fan()
|
||||
handle_fan = handle_fan_eon
|
||||
|
||||
params = Params()
|
||||
# dragonpilot
|
||||
ts_last_ip = None
|
||||
ts_last_update_vars = 0
|
||||
ts_last_charging_ctrl = None
|
||||
dp_last_modified = None
|
||||
|
||||
ip_addr = '255.255.255.255'
|
||||
dragon_charging_ctrl = False
|
||||
dragon_to_discharge = 70
|
||||
dragon_to_charge = 60
|
||||
|
||||
while 1:
|
||||
health = messaging.recv_sock(health_sock, wait=True)
|
||||
@@ -223,6 +240,18 @@ def thermald_thread():
|
||||
msg.thermal.batteryPercent = 100
|
||||
msg.thermal.batteryStatus = "Charging"
|
||||
|
||||
# dragonpilot ip Mod
|
||||
# update ip every 10 seconds
|
||||
ts = sec_since_boot()
|
||||
if ts_last_ip is None or ts - ts_last_ip >= 10.:
|
||||
try:
|
||||
result = subprocess.check_output(["ifconfig", "wlan0"], encoding='utf8') # pylint: disable=unexpected-keyword-arg
|
||||
ip_addr = re.findall(r"inet addr:((\d+\.){3}\d+)", result)[0][0]
|
||||
except:
|
||||
ip_addr = 'N/A'
|
||||
ts_last_ip = ts
|
||||
msg.thermal.ipAddr = ip_addr
|
||||
|
||||
current_filter.update(msg.thermal.batteryCurrent / 1e6)
|
||||
|
||||
# TODO: add car battery voltage check
|
||||
@@ -257,43 +286,44 @@ def thermald_thread():
|
||||
# **** starting logic ****
|
||||
|
||||
# Check for last update time and display alerts if needed
|
||||
now = datetime.datetime.now()
|
||||
|
||||
# show invalid date/time alert
|
||||
time_valid = now.year >= 2019
|
||||
if time_valid and not time_valid_prev:
|
||||
params.delete("Offroad_InvalidTime")
|
||||
if not time_valid and time_valid_prev:
|
||||
params.put("Offroad_InvalidTime", json.dumps(OFFROAD_ALERTS["Offroad_InvalidTime"]))
|
||||
time_valid_prev = time_valid
|
||||
# now = datetime.datetime.now()
|
||||
#
|
||||
# # show invalid date/time alert
|
||||
# time_valid = now.year >= 2019
|
||||
# if time_valid and not time_valid_prev:
|
||||
# params.delete("Offroad_InvalidTime")
|
||||
# if not time_valid and time_valid_prev:
|
||||
# params.put("Offroad_InvalidTime", json.dumps(OFFROAD_ALERTS["Offroad_InvalidTime"]))
|
||||
# time_valid_prev = time_valid
|
||||
time_valid = True
|
||||
|
||||
# Show update prompt
|
||||
try:
|
||||
last_update = datetime.datetime.fromisoformat(params.get("LastUpdateTime", encoding='utf8'))
|
||||
except (TypeError, ValueError):
|
||||
last_update = now
|
||||
dt = now - last_update
|
||||
|
||||
update_failed_count = params.get("UpdateFailedCount")
|
||||
update_failed_count = 0 if update_failed_count is None else int(update_failed_count)
|
||||
|
||||
if dt.days > DAYS_NO_CONNECTIVITY_MAX and update_failed_count > 1:
|
||||
if current_connectivity_alert != "expired":
|
||||
current_connectivity_alert = "expired"
|
||||
params.delete("Offroad_ConnectivityNeededPrompt")
|
||||
params.put("Offroad_ConnectivityNeeded", json.dumps(OFFROAD_ALERTS["Offroad_ConnectivityNeeded"]))
|
||||
elif dt.days > DAYS_NO_CONNECTIVITY_PROMPT:
|
||||
remaining_time = str(max(DAYS_NO_CONNECTIVITY_MAX - dt.days, 0))
|
||||
if current_connectivity_alert != "prompt" + remaining_time:
|
||||
current_connectivity_alert = "prompt" + remaining_time
|
||||
alert_connectivity_prompt = copy.copy(OFFROAD_ALERTS["Offroad_ConnectivityNeededPrompt"])
|
||||
alert_connectivity_prompt["text"] += remaining_time + " days."
|
||||
params.delete("Offroad_ConnectivityNeeded")
|
||||
params.put("Offroad_ConnectivityNeededPrompt", json.dumps(alert_connectivity_prompt))
|
||||
elif current_connectivity_alert is not None:
|
||||
current_connectivity_alert = None
|
||||
params.delete("Offroad_ConnectivityNeeded")
|
||||
params.delete("Offroad_ConnectivityNeededPrompt")
|
||||
# try:
|
||||
# last_update = datetime.datetime.fromisoformat(params.get("LastUpdateTime", encoding='utf8'))
|
||||
# except (TypeError, ValueError):
|
||||
# last_update = now
|
||||
# dt = now - last_update
|
||||
#
|
||||
# update_failed_count = params.get("UpdateFailedCount")
|
||||
# update_failed_count = 0 if update_failed_count is None else int(update_failed_count)
|
||||
#
|
||||
# if dt.days > DAYS_NO_CONNECTIVITY_MAX and update_failed_count > 1:
|
||||
# if current_connectivity_alert != "expired":
|
||||
# current_connectivity_alert = "expired"
|
||||
# params.delete("Offroad_ConnectivityNeededPrompt")
|
||||
# params.put("Offroad_ConnectivityNeeded", json.dumps(OFFROAD_ALERTS["Offroad_ConnectivityNeeded"]))
|
||||
# elif dt.days > DAYS_NO_CONNECTIVITY_PROMPT:
|
||||
# remaining_time = str(max(DAYS_NO_CONNECTIVITY_MAX - dt.days, 0))
|
||||
# if current_connectivity_alert != "prompt" + remaining_time:
|
||||
# current_connectivity_alert = "prompt" + remaining_time
|
||||
# alert_connectivity_prompt = copy.copy(OFFROAD_ALERTS["Offroad_ConnectivityNeededPrompt"])
|
||||
# alert_connectivity_prompt["text"] += remaining_time + " days."
|
||||
# params.delete("Offroad_ConnectivityNeeded")
|
||||
# params.put("Offroad_ConnectivityNeededPrompt", json.dumps(alert_connectivity_prompt))
|
||||
# elif current_connectivity_alert is not None:
|
||||
# current_connectivity_alert = None
|
||||
# params.delete("Offroad_ConnectivityNeeded")
|
||||
# params.delete("Offroad_ConnectivityNeededPrompt")
|
||||
|
||||
# start constellation of processes when the car starts
|
||||
ignition = health is not None and (health.health.ignitionLine or health.health.ignitionCan)
|
||||
@@ -382,6 +412,36 @@ def thermald_thread():
|
||||
|
||||
#print(msg)
|
||||
|
||||
# dragonpilot
|
||||
ts = sec_since_boot()
|
||||
# update variable status every 10 secs
|
||||
if ts - ts_last_update_vars >= 10.:
|
||||
modified = dp_get_last_modified()
|
||||
if dp_last_modified != modified:
|
||||
dragon_charging_ctrl = True if params.get('DragonChargingCtrl', encoding='utf8') == "1" else False
|
||||
if dragon_charging_ctrl:
|
||||
try:
|
||||
dragon_to_discharge = int(params.get('DragonCharging', encoding='utf8'))
|
||||
except TypeError:
|
||||
dragon_to_discharge = 70
|
||||
try:
|
||||
dragon_to_charge = int(params.get('DragonDisCharging', encoding='utf8'))
|
||||
except TypeError:
|
||||
dragon_to_charge = 60
|
||||
dp_last_modified = modified
|
||||
ts_last_update_vars = ts
|
||||
|
||||
# we update charging status once every min
|
||||
if ts_last_charging_ctrl is None or ts - ts_last_charging_ctrl >= 60.:
|
||||
if dragon_charging_ctrl:
|
||||
if msg.thermal.batteryPercent >= dragon_to_discharge:
|
||||
os.system('echo "0" > /sys/class/power_supply/battery/charging_enabled')
|
||||
if msg.thermal.batteryPercent <= dragon_to_charge:
|
||||
os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled')
|
||||
else:
|
||||
os.system('echo "1" > /sys/class/power_supply/battery/charging_enabled')
|
||||
ts_last_charging_ctrl = ts
|
||||
|
||||
# report to server once per minute
|
||||
if (count % int(60. / DT_TRML)) == 0:
|
||||
cloudlog.event("STATUS_PACKET",
|
||||
|
||||
@@ -104,7 +104,7 @@ def report_tombstone(fn, client):
|
||||
def main(gctx=None):
|
||||
initial_tombstones = set(get_tombstones())
|
||||
|
||||
client = Client('https://d3b175702f62402c91ade04d1c547e68:b20d68c813c74f63a7cdf9c4039d8f56@sentry.io/157615',
|
||||
client = Client('https://980a0cba712a4c3593c33c78a12446e1:fecab286bcaf4dba8b04f7cff0188e2d@sentry.io/1488600',
|
||||
install_sys_hook=False, transport=HTTPTransport, release=version, tags={'dirty': dirty}, string_max_length=10000)
|
||||
|
||||
client.user_context({'id': os.environ.get('DONGLE_ID')})
|
||||
|
||||
+415
-57
@@ -264,6 +264,30 @@ static void draw_steering(UIState *s, float curvature) {
|
||||
// ui_draw_lane_edge(s, points, 0.0, nvgRGBA(0, 0, 255, 128), 5);
|
||||
}
|
||||
|
||||
static void draw_front_frame(UIState *s) {
|
||||
const UIScene *scene = &s->scene;
|
||||
|
||||
float x1, x2, y1, y2;
|
||||
glBindVertexArray(s->frame_vao[1]);
|
||||
|
||||
mat4 *out_mat;
|
||||
out_mat = &s->front_frame_mat;
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
if (s->cur_vision_front_idx >= 0) {
|
||||
glBindTexture(GL_TEXTURE_2D, s->frame_front_texs[s->cur_vision_front_idx]);
|
||||
}
|
||||
|
||||
glUseProgram(s->frame_program);
|
||||
glUniform1i(s->frame_texture_loc, 0);
|
||||
glUniformMatrix4fv(s->frame_transform_loc, 1, GL_TRUE, out_mat->v);
|
||||
|
||||
assert(glGetError() == GL_NO_ERROR);
|
||||
glEnableVertexAttribArray(0);
|
||||
glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, (const void*)0);
|
||||
glDisableVertexAttribArray(0);
|
||||
glBindVertexArray(0);
|
||||
}
|
||||
|
||||
static void draw_frame(UIState *s) {
|
||||
const UIScene *scene = &s->scene;
|
||||
|
||||
@@ -355,27 +379,30 @@ static void ui_draw_vision_lanes(UIState *s) {
|
||||
update_all_lane_lines_data(s, scene->model.right_lane, pvd + MODEL_LANE_PATH_CNT);
|
||||
s->model_changed = false;
|
||||
}
|
||||
// Draw left lane edge
|
||||
ui_draw_lane(
|
||||
s, &scene->model.left_lane,
|
||||
pvd,
|
||||
nvgRGBAf(1.0, 1.0, 1.0, scene->model.left_lane.prob));
|
||||
|
||||
// Draw right lane edge
|
||||
ui_draw_lane(
|
||||
s, &scene->model.right_lane,
|
||||
pvd + MODEL_LANE_PATH_CNT,
|
||||
nvgRGBAf(1.0, 1.0, 1.0, scene->model.right_lane.prob));
|
||||
if (s->dragon_ui_lane) {
|
||||
// Draw left lane edge
|
||||
ui_draw_lane(
|
||||
s, &scene->model.left_lane,
|
||||
pvd,
|
||||
nvgRGBAf(1.0, 1.0, 1.0, scene->model.left_lane.prob));
|
||||
|
||||
// Draw right lane edge
|
||||
ui_draw_lane(
|
||||
s, &scene->model.right_lane,
|
||||
pvd + MODEL_LANE_PATH_CNT,
|
||||
nvgRGBAf(1.0, 1.0, 1.0, scene->model.right_lane.prob));
|
||||
}
|
||||
if(s->livempc_or_radarstate_changed) {
|
||||
update_all_track_data(s);
|
||||
s->livempc_or_radarstate_changed = false;
|
||||
}
|
||||
// Draw vision path
|
||||
ui_draw_track(s, false, &s->track_vertices[0]);
|
||||
if (scene->engaged) {
|
||||
// Draw MPC path when engaged
|
||||
ui_draw_track(s, true, &s->track_vertices[1]);
|
||||
if (s->dragon_ui_path) {
|
||||
// Draw vision path
|
||||
ui_draw_track(s, false, &s->track_vertices[0]);
|
||||
if (scene->engaged) {
|
||||
// Draw MPC path when engaged
|
||||
ui_draw_track(s, true, &s->track_vertices[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,7 +416,7 @@ static void ui_draw_world(UIState *s) {
|
||||
// Draw lane edges and vision/mpc tracks
|
||||
ui_draw_vision_lanes(s);
|
||||
|
||||
if (scene->lead_status) {
|
||||
if (s->dragon_ui_lead && scene->lead_status) {
|
||||
// Draw lead car indicator
|
||||
float fillAlpha = 0;
|
||||
float speedBuff = 10.;
|
||||
@@ -592,28 +619,58 @@ static void ui_draw_vision_speed(UIState *s) {
|
||||
const int viz_speed_x = ui_viz_rx+((ui_viz_rw/2)-(viz_speed_w/2));
|
||||
char speed_str[32];
|
||||
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRect(s->vg, viz_speed_x, box_y, viz_speed_w, header_h);
|
||||
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
|
||||
// blinker, from kegman
|
||||
if (s->dragon_ui_blinker) {
|
||||
if(s->scene.leftBlinker) {
|
||||
nvgBeginPath(s->vg);
|
||||
nvgMoveTo(s->vg, viz_speed_x, box_y + header_h/4);
|
||||
nvgLineTo(s->vg, viz_speed_x - viz_speed_w/2, box_y + header_h/4 + header_h/4);
|
||||
nvgLineTo(s->vg, viz_speed_x, box_y + header_h/2 + header_h/4);
|
||||
nvgClosePath(s->vg);
|
||||
nvgFillColor(s->vg, nvgRGBA(23,134,68,s->scene.blinker_blinkingrate>=50?210:60));
|
||||
nvgFill(s->vg);
|
||||
}
|
||||
|
||||
if (s->is_metric) {
|
||||
snprintf(speed_str, sizeof(speed_str), "%d", (int)(speed * 3.6 + 0.5));
|
||||
} else {
|
||||
snprintf(speed_str, sizeof(speed_str), "%d", (int)(speed * 2.2369363 + 0.5));
|
||||
if(s->scene.rightBlinker) {
|
||||
nvgBeginPath(s->vg);
|
||||
nvgMoveTo(s->vg, viz_speed_x+viz_speed_w, box_y + header_h/4);
|
||||
nvgLineTo(s->vg, viz_speed_x+viz_speed_w + viz_speed_w/2, box_y + header_h/4 + header_h/4);
|
||||
nvgLineTo(s->vg, viz_speed_x+viz_speed_w, box_y + header_h/2 + header_h/4);
|
||||
nvgClosePath(s->vg);
|
||||
nvgFillColor(s->vg, nvgRGBA(23,134,68,s->scene.blinker_blinkingrate>=50?210:60));
|
||||
nvgFill(s->vg);
|
||||
}
|
||||
|
||||
if(s->scene.leftBlinker || s->scene.rightBlinker) {
|
||||
s->scene.blinker_blinkingrate -= 3;
|
||||
if(s->scene.blinker_blinkingrate<0) s->scene.blinker_blinkingrate = 120;
|
||||
}
|
||||
}
|
||||
nvgFontFace(s->vg, "sans-bold");
|
||||
nvgFontSize(s->vg, 96*2.5);
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, 255));
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 240, speed_str, NULL);
|
||||
|
||||
nvgFontFace(s->vg, "sans-regular");
|
||||
nvgFontSize(s->vg, 36*2.5);
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, 200));
|
||||
if (s->dragon_ui_speed) {
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRect(s->vg, viz_speed_x, box_y, viz_speed_w, header_h);
|
||||
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
|
||||
|
||||
if (s->is_metric) {
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 320, "kph", NULL);
|
||||
} else {
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 320, "mph", NULL);
|
||||
if (s->is_metric) {
|
||||
snprintf(speed_str, sizeof(speed_str), "%d", (int)(speed * 3.6 + 0.5));
|
||||
} else {
|
||||
snprintf(speed_str, sizeof(speed_str), "%d", (int)(speed * 2.2369363 + 0.5));
|
||||
}
|
||||
nvgFontFace(s->vg, "sans-bold");
|
||||
nvgFontSize(s->vg, 96*2.5);
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, 255));
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 240, speed_str, NULL);
|
||||
|
||||
nvgFontFace(s->vg, "sans-regular");
|
||||
nvgFontSize(s->vg, 36*2.5);
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, 200));
|
||||
|
||||
if (s->is_metric) {
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 320, "kph", NULL);
|
||||
} else {
|
||||
nvgText(s->vg, viz_speed_x+viz_speed_w/2, 320, "mph", NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -728,22 +785,307 @@ static void ui_draw_vision_header(UIState *s) {
|
||||
int ui_viz_rx = scene->ui_viz_rx;
|
||||
int ui_viz_rw = scene->ui_viz_rw;
|
||||
|
||||
nvgBeginPath(s->vg);
|
||||
NVGpaint gradient = nvgLinearGradient(s->vg, ui_viz_rx,
|
||||
(box_y+(header_h-(header_h/2.5))),
|
||||
ui_viz_rx, box_y+header_h,
|
||||
nvgRGBAf(0,0,0,0.45), nvgRGBAf(0,0,0,0));
|
||||
nvgFillPaint(s->vg, gradient);
|
||||
nvgRect(s->vg, ui_viz_rx, box_y, ui_viz_rw, header_h);
|
||||
nvgFill(s->vg);
|
||||
if (s->dragon_driving_ui) {
|
||||
nvgBeginPath(s->vg);
|
||||
NVGpaint gradient = nvgLinearGradient(s->vg, ui_viz_rx,
|
||||
(box_y+(header_h-(header_h/2.5))),
|
||||
ui_viz_rx, box_y+header_h,
|
||||
nvgRGBAf(0,0,0,0.45), nvgRGBAf(0,0,0,0));
|
||||
nvgFillPaint(s->vg, gradient);
|
||||
nvgRect(s->vg, ui_viz_rx, box_y, ui_viz_rw, header_h);
|
||||
nvgFill(s->vg);
|
||||
}
|
||||
|
||||
ui_draw_vision_maxspeed(s);
|
||||
if (s->dragon_ui_maxspeed) {
|
||||
ui_draw_vision_maxspeed(s);
|
||||
}
|
||||
|
||||
#ifdef SHOW_SPEEDLIMIT
|
||||
ui_draw_vision_speedlimit(s);
|
||||
#endif
|
||||
ui_draw_vision_speed(s);
|
||||
ui_draw_vision_event(s);
|
||||
if (s->dragon_ui_event) {
|
||||
ui_draw_vision_event(s);
|
||||
}
|
||||
}
|
||||
|
||||
static void ui_draw_infobar(UIState *s) {
|
||||
const UIScene *scene = &s->scene;
|
||||
int ui_viz_rx = scene->ui_viz_rx;
|
||||
bool hasSidebar = !s->scene.uilayout_sidebarcollapsed;
|
||||
// rect_w = screen_width - sidebar width
|
||||
|
||||
int rect_w = vwp_w - ui_viz_rx - bdr_s;
|
||||
int rect_h = 80;
|
||||
// rect_x = 0 + sidebar width
|
||||
|
||||
// if driving ui is enabled, rect_x = rect_x + vision start x
|
||||
int rect_x = (hasSidebar? (bdr_s+sbr_w) : ui_viz_rx);
|
||||
|
||||
// rect_y = screen height - board - background height
|
||||
int rect_y = vwp_h - bdr_s - rect_h;
|
||||
|
||||
// int text_width;
|
||||
int text_x = rect_w / 2 + ui_viz_rx;
|
||||
int text_y = rect_y + 55;
|
||||
|
||||
char infobar[100];
|
||||
// create time string
|
||||
char date_time[20];
|
||||
time_t rawtime = time(NULL);
|
||||
struct tm timeinfo;
|
||||
localtime_r(&rawtime, &timeinfo);
|
||||
strftime(date_time, sizeof(date_time),"%F %T", &timeinfo);
|
||||
|
||||
if (s->dragon_ui_dev_mini) {
|
||||
char rel_steer[9];
|
||||
snprintf(rel_steer, sizeof(rel_steer), "%s%05.1f°", s->scene.angleSteers < 0? "-" : "+", fabs(s->scene.angleSteers));
|
||||
|
||||
char des_steer[9];
|
||||
if (s->scene.engaged) {
|
||||
snprintf(des_steer, sizeof(des_steer), "%s%05.1f°", s->scene.angleSteersDes < 0? "-" : "+", fabs(s->scene.angleSteersDes));
|
||||
} else {
|
||||
snprintf(des_steer, sizeof(des_steer), "%7s", "-");
|
||||
}
|
||||
|
||||
char lead_dist[8];
|
||||
if (s->scene.lead_status) {
|
||||
snprintf(lead_dist, sizeof(lead_dist), "%06.2fm", s->scene.lead_d_rel);
|
||||
} else {
|
||||
snprintf(lead_dist, sizeof(lead_dist), "%7s", "-");
|
||||
}
|
||||
|
||||
snprintf(
|
||||
infobar,
|
||||
sizeof(infobar),
|
||||
"%s /REL: %s /DES: %s /DIS: %s",
|
||||
date_time,
|
||||
rel_steer,
|
||||
des_steer,
|
||||
lead_dist
|
||||
);
|
||||
} else {
|
||||
snprintf(
|
||||
infobar,
|
||||
sizeof(infobar),
|
||||
"%s",
|
||||
date_time
|
||||
);
|
||||
}
|
||||
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRoundedRect(s->vg, rect_x, rect_y, rect_w, rect_h, 15);
|
||||
nvgFillColor(s->vg, nvgRGBA(0, 0, 0, 180));
|
||||
nvgFill(s->vg);
|
||||
|
||||
nvgFontSize(s->vg, hasSidebar? 43:50);
|
||||
nvgFontFace(s->vg, "courbd");
|
||||
nvgFillColor(s->vg, nvgRGBA(255, 255, 255, 180));
|
||||
nvgTextAlign(s->vg, NVG_ALIGN_CENTER);
|
||||
nvgText(s->vg, text_x, text_y, infobar, NULL);
|
||||
}
|
||||
|
||||
//BB START: functions added for the display of various items
|
||||
static int bb_ui_draw_measure(UIState *s, const char* bb_value, const char* bb_uom, const char* bb_label,
|
||||
int bb_x, int bb_y, int bb_uom_dx,
|
||||
NVGcolor bb_valueColor, NVGcolor bb_labelColor, NVGcolor bb_uomColor,
|
||||
int bb_valueFontSize, int bb_labelFontSize, int bb_uomFontSize ) {
|
||||
const UIScene *scene = &s->scene;
|
||||
nvgTextAlign(s->vg, NVG_ALIGN_CENTER | NVG_ALIGN_BASELINE);
|
||||
int dx = 0;
|
||||
if (strlen(bb_uom) > 0) {
|
||||
dx = (int)(bb_uomFontSize*2.5/2);
|
||||
}
|
||||
//print value
|
||||
nvgFontFace(s->vg, "sans-bold");
|
||||
nvgFontSize(s->vg, bb_valueFontSize*2.5);
|
||||
nvgFillColor(s->vg, bb_valueColor);
|
||||
nvgText(s->vg, bb_x-dx/2, bb_y+ (int)(bb_valueFontSize*2.5)+5, bb_value, NULL);
|
||||
//print label
|
||||
nvgFontFace(s->vg, "sans-regular");
|
||||
nvgFontSize(s->vg, bb_labelFontSize*2.5);
|
||||
nvgFillColor(s->vg, bb_labelColor);
|
||||
nvgText(s->vg, bb_x, bb_y + (int)(bb_valueFontSize*2.5)+5 + (int)(bb_labelFontSize*2.5)+5, bb_label, NULL);
|
||||
//print uom
|
||||
if (strlen(bb_uom) > 0) {
|
||||
nvgSave(s->vg);
|
||||
int rx =bb_x + bb_uom_dx + bb_valueFontSize -3;
|
||||
int ry = bb_y + (int)(bb_valueFontSize*2.5/2)+25;
|
||||
nvgTranslate(s->vg,rx,ry);
|
||||
nvgRotate(s->vg, -1.5708); //-90deg in radians
|
||||
nvgFontFace(s->vg, "sans-regular");
|
||||
nvgFontSize(s->vg, (int)(bb_uomFontSize*2.5));
|
||||
nvgFillColor(s->vg, bb_uomColor);
|
||||
nvgText(s->vg, 0, 0, bb_uom, NULL);
|
||||
nvgRestore(s->vg);
|
||||
}
|
||||
return (int)((bb_valueFontSize + bb_labelFontSize)*2.5) + 5;
|
||||
}
|
||||
|
||||
static void bb_ui_draw_measures_left(UIState *s, int bb_x, int bb_y, int bb_w ) {
|
||||
const UIScene *scene = &s->scene;
|
||||
int bb_rx = bb_x + (int)(bb_w/2);
|
||||
int bb_ry = bb_y;
|
||||
int bb_h = 5;
|
||||
NVGcolor lab_color = nvgRGBA(255, 255, 255, 200);
|
||||
NVGcolor uom_color = nvgRGBA(255, 255, 255, 200);
|
||||
int value_fontSize=30;
|
||||
int label_fontSize=15;
|
||||
int uom_fontSize = 15;
|
||||
int bb_uom_dx = (int)(bb_w /2 - uom_fontSize*2.5) ;
|
||||
|
||||
//add visual radar relative distance
|
||||
if (true) {
|
||||
char val_str[16];
|
||||
char uom_str[6];
|
||||
NVGcolor val_color = nvgRGBA(255, 255, 255, 200);
|
||||
if (scene->lead_status) {
|
||||
//show RED if less than 5 meters
|
||||
//show orange if less than 15 meters
|
||||
if((int)(scene->lead_d_rel) < 15) {
|
||||
val_color = nvgRGBA(255, 188, 3, 200);
|
||||
}
|
||||
if((int)(scene->lead_d_rel) < 5) {
|
||||
val_color = nvgRGBA(255, 0, 0, 200);
|
||||
}
|
||||
// lead car relative distance is always in meters
|
||||
snprintf(val_str, sizeof(val_str), "%d", (int)scene->lead_d_rel);
|
||||
} else {
|
||||
snprintf(val_str, sizeof(val_str), "-");
|
||||
}
|
||||
snprintf(uom_str, sizeof(uom_str), "m ");
|
||||
bb_h +=bb_ui_draw_measure(s, val_str, uom_str, "相對距離",
|
||||
bb_rx, bb_ry, bb_uom_dx,
|
||||
val_color, lab_color, uom_color,
|
||||
value_fontSize, label_fontSize, uom_fontSize );
|
||||
bb_ry = bb_y + bb_h;
|
||||
}
|
||||
|
||||
//add visual radar relative speed
|
||||
if (true) {
|
||||
char val_str[16];
|
||||
char uom_str[6];
|
||||
NVGcolor val_color = nvgRGBA(255, 255, 255, 200);
|
||||
if (scene->lead_status) {
|
||||
//show Orange if negative speed (approaching)
|
||||
//show Orange if negative speed faster than 5mph (approaching fast)
|
||||
if((int)(scene->lead_v_rel) < 0) {
|
||||
val_color = nvgRGBA(255, 188, 3, 200);
|
||||
}
|
||||
if((int)(scene->lead_v_rel) < -5) {
|
||||
val_color = nvgRGBA(255, 0, 0, 200);
|
||||
}
|
||||
// lead car relative speed is always in meters
|
||||
if (s->is_metric) {
|
||||
snprintf(val_str, sizeof(val_str), "%d", (int)(scene->lead_v_rel * 3.6 + 0.5));
|
||||
} else {
|
||||
snprintf(val_str, sizeof(val_str), "%d", (int)(scene->lead_v_rel * 2.2374144 + 0.5));
|
||||
}
|
||||
} else {
|
||||
snprintf(val_str, sizeof(val_str), "-");
|
||||
}
|
||||
if (s->is_metric) {
|
||||
snprintf(uom_str, sizeof(uom_str), "km/h");;
|
||||
} else {
|
||||
snprintf(uom_str, sizeof(uom_str), "mph");
|
||||
}
|
||||
bb_h +=bb_ui_draw_measure(s, val_str, uom_str, "相對速度",
|
||||
bb_rx, bb_ry, bb_uom_dx,
|
||||
val_color, lab_color, uom_color,
|
||||
value_fontSize, label_fontSize, uom_fontSize );
|
||||
bb_ry = bb_y + bb_h;
|
||||
}
|
||||
|
||||
//finally draw the frame
|
||||
bb_h += 20;
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRoundedRect(s->vg, bb_x, bb_y, bb_w, bb_h, 20);
|
||||
nvgStrokeColor(s->vg, nvgRGBA(255,255,255,80));
|
||||
nvgStrokeWidth(s->vg, 6);
|
||||
nvgStroke(s->vg);
|
||||
}
|
||||
|
||||
static void bb_ui_draw_measures_right(UIState *s, int bb_x, int bb_y, int bb_w ) {
|
||||
const UIScene *scene = &s->scene;
|
||||
int bb_rx = bb_x + (int)(bb_w/2);
|
||||
int bb_ry = bb_y;
|
||||
int bb_h = 5;
|
||||
NVGcolor lab_color = nvgRGBA(255, 255, 255, 200);
|
||||
NVGcolor uom_color = nvgRGBA(255, 255, 255, 200);
|
||||
int value_fontSize=30;
|
||||
int label_fontSize=15;
|
||||
int uom_fontSize = 15;
|
||||
int bb_uom_dx = (int)(bb_w /2 - uom_fontSize*2.5) ;
|
||||
|
||||
//add steering angle
|
||||
if (true) {
|
||||
char val_str[16];
|
||||
char uom_str[6];
|
||||
NVGcolor val_color = nvgRGBA(255, 255, 255, 200);
|
||||
//show Orange if more than 6 degrees
|
||||
//show red if more than 12 degrees
|
||||
if(((int)(scene->angleSteers) < -6) || ((int)(scene->angleSteers) > 6)) {
|
||||
val_color = nvgRGBA(255, 188, 3, 200);
|
||||
}
|
||||
if(((int)(scene->angleSteers) < -12) || ((int)(scene->angleSteers) > 12)) {
|
||||
val_color = nvgRGBA(255, 0, 0, 200);
|
||||
}
|
||||
// steering is in degrees
|
||||
snprintf(val_str, sizeof(val_str), "%.1f°",(scene->angleSteers));
|
||||
|
||||
snprintf(uom_str, sizeof(uom_str), "");
|
||||
bb_h +=bb_ui_draw_measure(s, val_str, uom_str, "實際轉角",
|
||||
bb_rx, bb_ry, bb_uom_dx,
|
||||
val_color, lab_color, uom_color,
|
||||
value_fontSize, label_fontSize, uom_fontSize );
|
||||
bb_ry = bb_y + bb_h;
|
||||
}
|
||||
|
||||
//add desired steering angle
|
||||
if (true) {
|
||||
char val_str[16];
|
||||
char uom_str[6];
|
||||
NVGcolor val_color = nvgRGBA(255, 255, 255, 200);
|
||||
//show Orange if more than 6 degrees
|
||||
//show red if more than 12 degrees
|
||||
if(((int)(scene->angleSteersDes) < -6) || ((int)(scene->angleSteersDes) > 6)) {
|
||||
val_color = nvgRGBA(255, 188, 3, 200);
|
||||
}
|
||||
if(((int)(scene->angleSteersDes) < -12) || ((int)(scene->angleSteersDes) > 12)) {
|
||||
val_color = nvgRGBA(255, 0, 0, 200);
|
||||
}
|
||||
// steering is in degrees
|
||||
snprintf(val_str, sizeof(val_str), "%.1f°",(scene->angleSteersDes));
|
||||
|
||||
snprintf(uom_str, sizeof(uom_str), "");
|
||||
bb_h +=bb_ui_draw_measure(s, val_str, uom_str, "所需轉角",
|
||||
bb_rx, bb_ry, bb_uom_dx,
|
||||
val_color, lab_color, uom_color,
|
||||
value_fontSize, label_fontSize, uom_fontSize );
|
||||
bb_ry = bb_y + bb_h;
|
||||
}
|
||||
|
||||
//finally draw the frame
|
||||
bb_h += 20;
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRoundedRect(s->vg, bb_x, bb_y, bb_w, bb_h, 20);
|
||||
nvgStrokeColor(s->vg, nvgRGBA(255,255,255,80));
|
||||
nvgStrokeWidth(s->vg, 6);
|
||||
nvgStroke(s->vg);
|
||||
}
|
||||
|
||||
static void ui_draw_bbui(UIState *s) {
|
||||
const UIScene *scene = &s->scene;
|
||||
const int bb_dml_w = 180;
|
||||
const int bb_dml_x = (scene->ui_viz_rx + (bdr_s * 2));
|
||||
const int bb_dml_y = (box_y + (bdr_s * 1.5)) + 220;
|
||||
|
||||
const int bb_dmr_w = 180;
|
||||
const int bb_dmr_x = scene->ui_viz_rx + scene->ui_viz_rw - bb_dmr_w - (bdr_s * 2);
|
||||
const int bb_dmr_y = (box_y + (bdr_s * 1.5)) + 220;
|
||||
|
||||
bb_ui_draw_measures_right(s, bb_dml_x, bb_dml_y, bb_dml_w);
|
||||
bb_ui_draw_measures_left(s, bb_dmr_x, bb_dmr_y, bb_dmr_w);
|
||||
}
|
||||
|
||||
static void ui_draw_vision_footer(UIState *s) {
|
||||
@@ -754,11 +1096,18 @@ static void ui_draw_vision_footer(UIState *s) {
|
||||
nvgBeginPath(s->vg);
|
||||
nvgRect(s->vg, ui_viz_rx, footer_y, ui_viz_rw, footer_h);
|
||||
|
||||
ui_draw_vision_face(s);
|
||||
|
||||
if (s->dragon_ui_face) {
|
||||
ui_draw_vision_face(s);
|
||||
}
|
||||
#ifdef SHOW_SPEEDLIMIT
|
||||
// ui_draw_vision_map(s);
|
||||
#endif
|
||||
if (s->dragon_ui_dev) {
|
||||
ui_draw_bbui(s);
|
||||
}
|
||||
if (s->dragon_ui_dev_mini || s->dragon_enable_dashcam || s->dragon_waze_mode) {
|
||||
ui_draw_infobar(s);
|
||||
}
|
||||
}
|
||||
|
||||
void ui_draw_vision_alert(UIState *s, int va_size, int va_color,
|
||||
@@ -830,7 +1179,14 @@ static void ui_draw_vision(UIState *s) {
|
||||
glScissor(ui_viz_rx, s->fb_h-(box_y+box_h), ui_viz_rw, box_h);
|
||||
glEnable(GL_BLEND);
|
||||
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
|
||||
draw_frame(s);
|
||||
if (s->dragon_driving_ui) {
|
||||
draw_frame(s);
|
||||
}
|
||||
if (s->dragon_ui_dm_view) {
|
||||
glViewport(1240, 110, viz_w*0.4, box_h*0.4);
|
||||
draw_front_frame(s);
|
||||
glClear(GL_STENCIL_BUFFER_BIT);
|
||||
}
|
||||
glViewport(0, 0, s->fb_w, s->fb_h);
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
@@ -840,12 +1196,14 @@ static void ui_draw_vision(UIState *s) {
|
||||
nvgSave(s->vg);
|
||||
|
||||
// Draw augmented elements
|
||||
const int inner_height = viz_w*9/16;
|
||||
nvgScissor(s->vg, ui_viz_rx, box_y, ui_viz_rw, box_h);
|
||||
nvgTranslate(s->vg, ui_viz_rx+ui_viz_ro, box_y + (box_h-inner_height)/2.0);
|
||||
nvgScale(s->vg, (float)viz_w / s->fb_w, (float)inner_height / s->fb_h);
|
||||
if (!scene->frontview && !scene->fullview) {
|
||||
ui_draw_world(s);
|
||||
if (s->dragon_driving_ui) {
|
||||
const int inner_height = viz_w*9/16;
|
||||
nvgScissor(s->vg, ui_viz_rx, box_y, ui_viz_rw, box_h);
|
||||
nvgTranslate(s->vg, ui_viz_rx+ui_viz_ro, box_y + (box_h-inner_height)/2.0);
|
||||
nvgScale(s->vg, (float)viz_w / s->fb_w, (float)inner_height / s->fb_h);
|
||||
if (!scene->frontview && !scene->fullview) {
|
||||
ui_draw_world(s);
|
||||
}
|
||||
}
|
||||
|
||||
nvgRestore(s->vg);
|
||||
@@ -961,11 +1319,11 @@ void ui_nvg_init(UIState *s) {
|
||||
|
||||
s->font_courbd = nvgCreateFont(s->vg, "courbd", "../assets/fonts/courbd.ttf");
|
||||
assert(s->font_courbd >= 0);
|
||||
s->font_sans_regular = nvgCreateFont(s->vg, "sans-regular", "../assets/fonts/opensans_regular.ttf");
|
||||
s->font_sans_regular = nvgCreateFont(s->vg, "sans-regular", "../../dragonpilot/chinese-fonts/NotoSansCJKtc-Regular.otf");
|
||||
assert(s->font_sans_regular >= 0);
|
||||
s->font_sans_semibold = nvgCreateFont(s->vg, "sans-semibold", "../assets/fonts/opensans_semibold.ttf");
|
||||
s->font_sans_semibold = nvgCreateFont(s->vg, "sans-semibold", "../../dragonpilot/chinese-fonts/NotoSansCJKtc-Medium.otf");
|
||||
assert(s->font_sans_semibold >= 0);
|
||||
s->font_sans_bold = nvgCreateFont(s->vg, "sans-bold", "../assets/fonts/opensans_bold.ttf");
|
||||
s->font_sans_bold = nvgCreateFont(s->vg, "sans-bold", "../../dragonpilot/chinese-fonts/NotoSansCJKtc-Bold.otf");
|
||||
assert(s->font_sans_bold >= 0);
|
||||
|
||||
assert(s->img_wheel >= 0);
|
||||
|
||||
Binary file not shown.
+106
-3
@@ -111,19 +111,22 @@ static void ui_init(UIState *s) {
|
||||
s->uilayout_sock = SubSocket::create(s->ctx, "uiLayoutState");
|
||||
s->livecalibration_sock = SubSocket::create(s->ctx, "liveCalibration");
|
||||
s->radarstate_sock = SubSocket::create(s->ctx, "radarState");
|
||||
s->carstate_sock = SubSocket::create(s->ctx, "carState");
|
||||
|
||||
assert(s->model_sock != NULL);
|
||||
assert(s->controlsstate_sock != NULL);
|
||||
assert(s->uilayout_sock != NULL);
|
||||
assert(s->livecalibration_sock != NULL);
|
||||
assert(s->radarstate_sock != NULL);
|
||||
assert(s->carstate_sock != NULL);
|
||||
|
||||
s->poller = Poller::create({
|
||||
s->model_sock,
|
||||
s->controlsstate_sock,
|
||||
s->uilayout_sock,
|
||||
s->livecalibration_sock,
|
||||
s->radarstate_sock
|
||||
s->radarstate_sock,
|
||||
s->carstate_sock
|
||||
});
|
||||
|
||||
#ifdef SHOW_SPEEDLIMIT
|
||||
@@ -195,11 +198,61 @@ static void ui_init_vision(UIState *s, const VisionStreamBufs back_bufs,
|
||||
read_param_bool(&s->is_metric, "IsMetric");
|
||||
read_param_bool(&s->longitudinal_control, "LongitudinalControl");
|
||||
read_param_bool(&s->limit_set_speed, "LimitSetSpeed");
|
||||
// dragonpilot
|
||||
read_param_float(&s->dragon_ui_volume_boost, "DragonUIVolumeBoost");
|
||||
read_param_bool(&s->dragon_waze_mode, "DragonWazeMode");
|
||||
if (s->dragon_waze_mode) {
|
||||
s->dragon_ui_speed = false;
|
||||
s->dragon_ui_event = false;
|
||||
s->dragon_ui_maxspeed = false;
|
||||
s->dragon_ui_face = false;
|
||||
s->dragon_ui_dev = false;
|
||||
s->dragon_ui_dev_mini = false;
|
||||
s->dragon_enable_dashcam = false;
|
||||
s->dragon_driving_ui = false;
|
||||
s->dragon_ui_lane = false;
|
||||
s->dragon_ui_lead = false;
|
||||
s->dragon_ui_path = false;
|
||||
s->dragon_ui_blinker = false;
|
||||
s->dragon_ui_dm_view = false;
|
||||
} else {
|
||||
read_param_bool(&s->dragon_ui_speed, "DragonUISpeed");
|
||||
read_param_bool(&s->dragon_ui_event, "DragonUIEvent");
|
||||
read_param_bool(&s->dragon_ui_maxspeed, "DragonUIMaxSpeed");
|
||||
read_param_bool(&s->dragon_ui_face, "DragonUIFace");
|
||||
read_param_bool(&s->dragon_ui_dev, "DragonUIDev");
|
||||
read_param_bool(&s->dragon_ui_dev_mini, "DragonUIDevMini");
|
||||
read_param_bool(&s->dragon_enable_dashcam, "DragonEnableDashcam");
|
||||
read_param_bool(&s->dragon_driving_ui, "DragonDrivingUI");
|
||||
read_param_bool(&s->dragon_ui_lane, "DragonUILane");
|
||||
read_param_bool(&s->dragon_ui_lead, "DragonUILead");
|
||||
read_param_bool(&s->dragon_ui_path, "DragonUIPath");
|
||||
read_param_bool(&s->dragon_ui_blinker, "DragonUIBlinker");
|
||||
read_param_bool(&s->dragon_ui_dm_view, "DragonUIDMView");
|
||||
}
|
||||
|
||||
|
||||
// Set offsets so params don't get read at the same time
|
||||
s->longitudinal_control_timeout = UI_FREQ / 3;
|
||||
s->is_metric_timeout = UI_FREQ / 2;
|
||||
s->limit_set_speed_timeout = UI_FREQ;
|
||||
|
||||
// dragonpilot, 1hz
|
||||
s->dragon_ui_speed_timeout = UI_FREQ * 5.1;
|
||||
s->dragon_ui_event_timeout = UI_FREQ * 5.2;
|
||||
s->dragon_ui_maxspeed_timeout = UI_FREQ * 5.3;
|
||||
s->dragon_ui_face_timeout = UI_FREQ * 5.4;
|
||||
s->dragon_ui_dev_timeout = UI_FREQ * 5.5;
|
||||
s->dragon_ui_dev_mini_timeout = UI_FREQ * 5.6;
|
||||
s->dragon_enable_dashcam_timeout = UI_FREQ * 5.7;
|
||||
s->dragon_ui_volume_boost_timeout = UI_FREQ * 5.8;
|
||||
s->dragon_driving_ui_timeout = UI_FREQ * 5.9;
|
||||
s->dragon_ui_lane_timeout = UI_FREQ * 6.0;
|
||||
s->dragon_ui_lead_timeout = UI_FREQ * 6.1;
|
||||
s->dragon_ui_path_timeout = UI_FREQ * 6.2;
|
||||
s->dragon_ui_blinker_timeout = UI_FREQ * 6.3;
|
||||
s->dragon_waze_mode_timeout = UI_FREQ * 6.4;
|
||||
s->dragon_ui_dm_view_timeout = UI_FREQ * 6.5;
|
||||
}
|
||||
|
||||
static PathData read_path(cereal_ModelData_PathData_ptr pathp) {
|
||||
@@ -284,6 +337,10 @@ void handle_message(UIState *s, Message * msg) {
|
||||
|
||||
s->scene.decel_for_model = datad.decelForModel;
|
||||
|
||||
// dragonpilot
|
||||
s->scene.angleSteers = datad.angleSteers;
|
||||
s->scene.angleSteersDes = datad.angleSteersDes;
|
||||
|
||||
if (datad.alertSound != cereal_CarControl_HUDControl_AudibleAlert_none && datad.alertSound != s->alert_sound) {
|
||||
if (s->alert_sound != cereal_CarControl_HUDControl_AudibleAlert_none) {
|
||||
stop_alert_sound(s->alert_sound);
|
||||
@@ -417,6 +474,15 @@ void handle_message(UIState *s, Message * msg) {
|
||||
struct cereal_LiveMapData datad;
|
||||
cereal_read_LiveMapData(&datad, eventd.liveMapData);
|
||||
s->scene.map_valid = datad.mapValid;
|
||||
} else if (eventd.which == cereal_Event_carState) {
|
||||
struct cereal_CarState datad;
|
||||
cereal_read_CarState(&datad, eventd.carState);
|
||||
|
||||
if(s->scene.leftBlinker!=datad.leftBlinker || s->scene.rightBlinker!=datad.rightBlinker) {
|
||||
s->scene.blinker_blinkingrate = 100;
|
||||
}
|
||||
s->scene.leftBlinker = datad.leftBlinker;
|
||||
s->scene.rightBlinker = datad.rightBlinker;
|
||||
}
|
||||
capn_free(&ctx);
|
||||
}
|
||||
@@ -895,6 +961,10 @@ int main(int argc, char* argv[]) {
|
||||
s->volume_timeout--;
|
||||
} else {
|
||||
int volume = fmin(MAX_VOLUME, MIN_VOLUME + s->scene.v_ego / 5); // up one notch every 5 m/s
|
||||
if (s->dragon_ui_volume_boost > 0 || s->dragon_ui_volume_boost < 0) {
|
||||
volume = volume * (1 + s->dragon_ui_volume_boost /100);
|
||||
volume = volume > MAX_VOLUME? MAX_VOLUME : volume;
|
||||
}
|
||||
set_volume(volume);
|
||||
s->volume_timeout = 5 * UI_FREQ;
|
||||
}
|
||||
@@ -916,8 +986,8 @@ int main(int argc, char* argv[]) {
|
||||
if (s->status != STATUS_STOPPED) {
|
||||
update_status(s, STATUS_ALERT);
|
||||
}
|
||||
snprintf(s->scene.alert_text1, sizeof(s->scene.alert_text1), "%s", "TAKE CONTROL IMMEDIATELY");
|
||||
snprintf(s->scene.alert_text2, sizeof(s->scene.alert_text2), "%s", "Controls Unresponsive");
|
||||
snprintf(s->scene.alert_text1, sizeof(s->scene.alert_text1), "%s", "即刻接管控制");
|
||||
snprintf(s->scene.alert_text2, sizeof(s->scene.alert_text2), "%s", "操控服務沒有反應");
|
||||
ui_draw_vision_alert(s, s->scene.alert_size, s->status, s->scene.alert_text1, s->scene.alert_text2);
|
||||
|
||||
s->alert_sound_timeout = 2 * UI_FREQ;
|
||||
@@ -933,6 +1003,39 @@ int main(int argc, char* argv[]) {
|
||||
read_param_bool_timeout(&s->longitudinal_control, "LongitudinalControl", &s->longitudinal_control_timeout);
|
||||
read_param_bool_timeout(&s->limit_set_speed, "LimitSetSpeed", &s->limit_set_speed_timeout);
|
||||
read_param_float_timeout(&s->speed_lim_off, "SpeedLimitOffset", &s->limit_set_speed_timeout);
|
||||
// dragonpilot
|
||||
read_param_float_timeout(&s->dragon_ui_volume_boost, "DragonUIVolumeBoost", &s->dragon_ui_volume_boost_timeout);
|
||||
read_param_bool_timeout(&s->dragon_waze_mode, "DragonWazeMode", &s->dragon_waze_mode_timeout);
|
||||
|
||||
if (s->dragon_waze_mode) {
|
||||
s->dragon_ui_speed = false;
|
||||
s->dragon_ui_event = false;
|
||||
s->dragon_ui_maxspeed = false;
|
||||
s->dragon_ui_face = false;
|
||||
s->dragon_ui_dev = false;
|
||||
s->dragon_ui_dev_mini = false;
|
||||
s->dragon_enable_dashcam = false;
|
||||
s->dragon_driving_ui = false;
|
||||
s->dragon_ui_lane = false;
|
||||
s->dragon_ui_lead = false;
|
||||
s->dragon_ui_path = false;
|
||||
s->dragon_ui_blinker = false;
|
||||
s->dragon_ui_dm_view = false;
|
||||
} else {
|
||||
read_param_bool_timeout(&s->dragon_ui_speed, "DragonUISpeed", &s->dragon_ui_speed_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_event, "DragonUIEvent", &s->dragon_ui_event_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_maxspeed, "DragonUIMaxSpeed", &s->dragon_ui_maxspeed_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_face, "DragonUIFace", &s->dragon_ui_face_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_dev, "DragonUIDev", &s->dragon_ui_dev_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_dev_mini, "DragonUIDevMini", &s->dragon_ui_dev_mini_timeout);
|
||||
read_param_bool_timeout(&s->dragon_enable_dashcam, "DragonEnableDashcam", &s->dragon_enable_dashcam_timeout);
|
||||
read_param_bool_timeout(&s->dragon_driving_ui, "DragonDrivingUI", &s->dragon_driving_ui_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_lane, "DragonUILane", &s->dragon_ui_lane_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_lead, "DragonUILead", &s->dragon_ui_lead_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_path, "DragonUIPath", &s->dragon_ui_path_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_blinker, "DragonUIBlinker", &s->dragon_ui_blinker_timeout);
|
||||
read_param_bool_timeout(&s->dragon_ui_dm_view, "DragonUIDMView", &s->dragon_ui_dm_view_timeout);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&s->lock);
|
||||
|
||||
|
||||
@@ -128,6 +128,16 @@ typedef struct UIScene {
|
||||
|
||||
// Used to show gps planner status
|
||||
bool gps_planner_active;
|
||||
|
||||
// dragonpilot
|
||||
// for minimal UI
|
||||
float angleSteersDes;
|
||||
float angleSteers;
|
||||
|
||||
// for blinker, from kegman
|
||||
bool leftBlinker;
|
||||
bool rightBlinker;
|
||||
int blinker_blinkingrate;
|
||||
} UIScene;
|
||||
|
||||
typedef struct {
|
||||
@@ -247,6 +257,40 @@ typedef struct UIState {
|
||||
model_path_vertices_data model_path_vertices[MODEL_LANE_PATH_CNT * 2];
|
||||
|
||||
track_vertices_data track_vertices[2];
|
||||
|
||||
// dragonpilot
|
||||
SubSocket *carstate_sock;
|
||||
int dragon_ui_speed_timeout;
|
||||
int dragon_ui_event_timeout;
|
||||
int dragon_ui_maxspeed_timeout;
|
||||
int dragon_ui_face_timeout;
|
||||
int dragon_ui_dev_timeout;
|
||||
int dragon_ui_dev_mini_timeout;
|
||||
int dragon_enable_dashcam_timeout;
|
||||
int dragon_ui_volume_boost_timeout;
|
||||
int dragon_driving_ui_timeout;
|
||||
int dragon_ui_lane_timeout;
|
||||
int dragon_ui_lead_timeout;
|
||||
int dragon_ui_path_timeout;
|
||||
int dragon_ui_blinker_timeout;
|
||||
int dragon_waze_mode_timeout;
|
||||
int dragon_ui_dm_view_timeout;
|
||||
|
||||
bool dragon_ui_speed;
|
||||
bool dragon_ui_event;
|
||||
bool dragon_ui_maxspeed;
|
||||
bool dragon_ui_face;
|
||||
bool dragon_ui_dev;
|
||||
bool dragon_ui_dev_mini;
|
||||
bool dragon_enable_dashcam;
|
||||
float dragon_ui_volume_boost;
|
||||
bool dragon_driving_ui;
|
||||
bool dragon_ui_lane;
|
||||
bool dragon_ui_lead;
|
||||
bool dragon_ui_path;
|
||||
bool dragon_ui_blinker;
|
||||
bool dragon_waze_mode;
|
||||
bool dragon_ui_dm_view;
|
||||
} UIState;
|
||||
|
||||
// API
|
||||
|
||||
+38
-1
@@ -292,7 +292,7 @@ def attempt_update():
|
||||
set_update_available_params(new_version=new_version)
|
||||
|
||||
|
||||
def main(gctx=None):
|
||||
def main_bak(gctx=None):
|
||||
update_failed_count = 0
|
||||
overlay_init_done = False
|
||||
wait_helper = WaitTimeHelper()
|
||||
@@ -360,5 +360,42 @@ def main(gctx=None):
|
||||
# We've been signaled to shut down
|
||||
dismount_ovfs()
|
||||
|
||||
def main(gctx=None):
|
||||
wait_helper = WaitTimeHelper()
|
||||
params = Params()
|
||||
|
||||
while True:
|
||||
# try network
|
||||
ping_failed = subprocess.call(["ping", "-W", "4", "-c", "1", "117.28.245.92"])
|
||||
|
||||
if not ping_failed:
|
||||
# download application update
|
||||
git_fetch_output = run(NICE_LOW_PRIORITY + ["git", "-C", "/data/openpilot/", "fetch"])
|
||||
cloudlog.info("git fetch success: %s", git_fetch_output)
|
||||
|
||||
# Write update available param
|
||||
cur_hash = run(["git", "-C", "/data/openpilot/", "rev-parse", "HEAD"]).rstrip()
|
||||
upstream_hash = run(["git", "-C", "/data/openpilot/", "rev-parse", "@{u}"]).rstrip()
|
||||
cloudlog.info("comparing %s to %s" % (cur_hash, upstream_hash))
|
||||
params.put("UpdateAvailable", str(int(cur_hash != upstream_hash)))
|
||||
|
||||
# Write latest release notes to param
|
||||
try:
|
||||
# r = subprocess.check_output(["git", "--no-pager", "show", "@{u}:RELEASES.md"])
|
||||
r = subprocess.check_output(["curl", "-H", "'Cache-Control: no-cache'", "-s", "https://raw.githubusercontent.com/dragonpilot-community/dragonpilot/docs/CHANGELOG.md"])
|
||||
r = r[:r.find(b'\n\n')] # Slice latest release notes
|
||||
params.put("ReleaseNotes", r + b"\n")
|
||||
except:
|
||||
params.put("ReleaseNotes", "")
|
||||
|
||||
t = datetime.datetime.now().isoformat()
|
||||
params.put("LastUpdateTime", t.encode('utf8'))
|
||||
|
||||
wait_between_updates(wait_helper.ready_event)
|
||||
if wait_helper.shutdown:
|
||||
break
|
||||
# We've been signaled to shut down
|
||||
dismount_ovfs()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Executable
+8
@@ -0,0 +1,8 @@
|
||||
#!/usr/bin/bash
|
||||
|
||||
export LD_LIBRARY_PATH=/data/data/com.termux/files/usr/lib
|
||||
export HOME=/data/data/com.termux/files/home
|
||||
export PATH=/usr/local/bin:/data/data/com.termux/files/usr/bin:/data/data/com.termux/files/usr/sbin:/data/data/com.termux/files/usr/bin/applets:/bin:/sbin:/vendor/bin:/system/sbin:/system/bin:/system/xbin:/data/data/com.termux/files/usr/bin/python
|
||||
export PYTHONPATH=/data/openpilot
|
||||
|
||||
cd /data/openpilot/panda ; pkill -f boardd ; python -c "from panda import Panda; Panda().flash()" && reboot
|
||||
Reference in New Issue
Block a user