mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-31 05:03:42 +08:00
GUM
This commit is contained in:
+2
-2
@@ -76,7 +76,7 @@ A supported vehicle is one that just works when you install a comma device. All
|
||||
|Chevrolet|Volt 2019|Adaptive Cruise Control (ACC) & LKAS|Stock|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM SDGM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 USB-C coupler<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 long OBD-C cable (9.5 ft)<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Volt 2019">Buy Here</a></sub></details>|||
|
||||
|Chevrolet|Volt ASCM Harness 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Volt ASCM Harness 2017-18">Buy Here</a></sub></details>|<a href="https://youtu.be/QeMCN_4TFfQ" target="_blank"><img height="18px" src="assets/icon-youtube.svg"></img></a>||
|
||||
|Chevrolet|Volt Camera Harness 2017-18|Flashed camera-forward integration with ACC|openpilot available[<sup>1</sup>](#footnotes)|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Volt Camera Harness 2017-18">Buy Here</a></sub></details>|||
|
||||
|Chevrolet|Volt No-ACC 2017-18|Adaptive Cruise Control (ACC)|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 GM connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Volt No-ACC 2017-18">Buy Here</a></sub></details>|||
|
||||
|Chevrolet|Volt No-ACC 2016-18 (OBD-C / L&P Harness)|Redneck ACC|openpilot|0 mph|7 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 OBD-II connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chevrolet Volt No-ACC 2016-18 (OBD-C / L&P Harness)">Buy Here</a></sub></details>|||
|
||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|Stock|0 mph|9 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2017-18">Buy Here</a></sub></details>|||
|
||||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2019-20">Buy Here</a></sub></details>|||
|
||||
|Chrysler|Pacifica 2021-23|All|Stock|0 mph|39 mph|[](##)|[](##)|<details><summary>Parts</summary><sub>- 1 FCA connector<br>- 1 OBD-C cable (2 ft)<br>- 1 comma four<br>- 1 comma power v3<br>- 1 harness box<br>- 1 mount<br><a href="https://comma.ai/shop/comma-3x?harness=Chrysler Pacifica 2021-23">Buy Here</a></sub></details>|||
|
||||
@@ -545,4 +545,4 @@ openpilot does not yet support these Toyota models due to a new message authenti
|
||||
* Toyota Camry 2025+
|
||||
* Lexus NX 2022+
|
||||
* Toyota bZ4x 2023+
|
||||
* Subaru Solterra 2023+
|
||||
* Subaru Solterra 2023+
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
|Chevrolet|Volt 2019|Adaptive Cruise Control (ACC) & LKAS|[Upstream](#upstream)|
|
||||
|Chevrolet|Volt ASCM Harness 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|
||||
|Chevrolet|Volt Camera Harness 2017-18|Flashed camera-forward integration with ACC|[Upstream](#upstream)|
|
||||
|Chevrolet|Volt No-ACC 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|
||||
|Chevrolet|Volt No-ACC 2016-18 (OBD-C / L&P Harness)|Redneck ACC|[Upstream](#upstream)|
|
||||
|Chrysler|Pacifica 2017-18|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|
||||
|Chrysler|Pacifica 2019-20|Adaptive Cruise Control (ACC)|[Upstream](#upstream)|
|
||||
|Chrysler|Pacifica 2021-23|All|[Upstream](#upstream)|
|
||||
@@ -578,4 +578,4 @@ Toyota, and the GM Global B platform.
|
||||
All the cars that openpilot supports use a [CAN bus](https://en.wikipedia.org/wiki/CAN_bus) for communication between all the car's computers, however a
|
||||
CAN bus isn't the only way that the computers in your car can communicate. Most, if not all, vehicles from the following
|
||||
manufacturers use [FlexRay](https://en.wikipedia.org/wiki/FlexRay) instead of a CAN bus: **BMW, Mercedes, Audi, Land Rover, and some Volvo**. These cars
|
||||
may one day be supported, but we have no immediate plans to support FlexRay.
|
||||
may one day be supported, but we have no immediate plans to support FlexRay.
|
||||
|
||||
@@ -30,20 +30,20 @@ FINGERPRINTS = {
|
||||
CAR.BUICK_LACROSSE: [{
|
||||
190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 353: 3, 381: 6, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 455: 7, 456: 8, 463: 3, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 8, 503: 1, 508: 8, 510: 8, 528: 5, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 5, 707: 8, 753: 5, 761: 7, 801: 8, 804: 3, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 872: 1, 882: 8, 890: 1, 892: 2, 893: 1, 894: 1, 961: 8, 967: 4, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 3, 1017: 8, 1019: 2, 1020: 8, 1022: 1, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1243: 3, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1609: 8, 1613: 8, 1649: 8, 1792: 8, 1798: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1858: 8, 1860: 8, 1863: 8, 1872: 8, 1875: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1904: 7, 1906: 7, 1907: 7, 1912: 7, 1913: 7, 1914: 7, 1916: 7, 1918: 7, 1919: 7, 1937: 8, 1953: 8, 1968: 8, 2001: 8, 2017: 8, 2018: 8, 2020: 8, 2026: 8
|
||||
}],
|
||||
# CAR.CHEVROLET_VOLT_CC: [
|
||||
# FIXME: Need a message to distinguish flashed from non-flashed
|
||||
# Volt Premier w/o acc 2016
|
||||
# {
|
||||
# 170: 8, 171: 8, 189: 7, 190: 6, 192: 5, 193: 8, 197: 8, 199: 4, 201: 6, 209: 7, 211: 2, 241: 6, 288: 5, 289: 1, 290: 1, 298: 2, 304: 8, 308: 4, 309: 8, 311: 8, 313: 8, 320: 8, 328: 1, 352: 5, 368: 8, 381: 6, 384: 8, 386: 5, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 458: 8, 479: 3, 481: 7, 485: 8, 489: 5, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 3, 508: 8, 512: 3, 528: 4, 530: 8, 532: 6, 537: 4, 539: 8, 542: 7, 546: 7, 550: 8, 554: 3, 558: 8, 560: 6, 562: 8, 563: 5, 564: 5, 565: 8, 566: 5, 567: 3, 568: 1, 577: 8, 578: 8, 594: 8, 647: 3, 707: 8, 711: 6, 717: 5, 761: 7, 800: 6, 810: 8, 821: 4, 823: 7, 832: 8, 840: 5, 842: 6, 844: 8, 866: 4, 869: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 5, 1003: 5, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1602: 8, 1618: 8, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 1930: 7, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2024: 8, 2025: 8, 2028: 8
|
||||
# },
|
||||
# {
|
||||
# 201: 8, 493: 8, 495: 4, 193: 8, 197: 8, 209: 7, 171: 8, 456: 8, 199: 4, 489: 8, 211: 2, 499: 3, 390: 7, 532: 6, 568: 1, 761: 7, 381: 6, 485: 8, 189: 7, 479: 3, 711: 6, 501: 8, 241: 6, 717: 5, 869: 4, 389: 2, 454: 8, 170: 8, 190: 6, 497: 8, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 500: 6, 508: 8, 528: 4, 647: 3, 1105: 6, 1005: 6, 481: 7, 844: 8, 866: 4, 564: 5, 969: 8, 388: 8, 352: 5, 562: 8, 961: 8, 386: 8, 707: 8, 977: 8, 979: 7, 298: 8, 840: 5, 842: 5, 988: 6, 1001: 8, 560: 8, 546: 7, 558: 8, 309: 8, 995: 7, 311: 8, 566: 5, 567:3, 989: 8, 384: 4, 800: 6, 1033: 7, 1034: 7, 313: 8, 554: 3, 810: 8, 1017: 8, 1019: 2, 1020: 8, 1217: 8, 1223: 3, 1233: 8, 1227: 4, 1417: 8, 1009: 8, 1221: 5, 1275: 3, 1225: 7, 289: 8, 550: 8, 1273: 3, 1928: 7, 1187: 4, 1265: 8, 1927: 7, 1267: 1, 1906: 7, 288: 5, 304: 1, 328: 1, 1912: 7, 320: 3, 1910: 7, 563: 5, 1249: 8, 1930: 7, 1257: 6, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 565: 5, 1280: 4, 1907: 7
|
||||
# },
|
||||
# # Volt Premier w/o ACC 2018 + Pedal
|
||||
# {
|
||||
# 189: 7, 193: 8, 197: 8, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 451: 8, 452: 8, 453: 6, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 497: 8, 500: 6, 501: 8, 513: 6, 528: 4, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 566: 5, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 717: 5, 761: 7, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 869: 4, 977: 8, 1001: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1922: 7, 1930: 7
|
||||
# }
|
||||
# ],
|
||||
CAR.CHEVROLET_VOLT_CC: [
|
||||
# Captured no-ACC Volt fingerprints for OBD-C/L&P harness installations
|
||||
# Volt Premier w/o ACC 2016
|
||||
{
|
||||
170: 8, 171: 8, 189: 7, 190: 6, 192: 5, 193: 8, 197: 8, 199: 4, 201: 6, 209: 7, 211: 2, 241: 6, 288: 5, 289: 1, 290: 1, 298: 2, 304: 8, 308: 4, 309: 8, 311: 8, 313: 8, 320: 8, 328: 1, 352: 5, 368: 8, 381: 6, 384: 8, 386: 5, 388: 8, 389: 2, 390: 7, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 454: 8, 456: 8, 458: 8, 479: 3, 481: 7, 485: 8, 489: 5, 493: 8, 495: 4, 497: 8, 499: 3, 500: 6, 501: 3, 508: 8, 512: 3, 528: 4, 530: 8, 532: 6, 537: 4, 539: 8, 542: 7, 546: 7, 550: 8, 554: 3, 558: 8, 560: 6, 562: 8, 563: 5, 564: 5, 565: 8, 566: 5, 567: 3, 568: 1, 577: 8, 578: 8, 594: 8, 647: 3, 707: 8, 711: 6, 717: 5, 761: 7, 800: 6, 810: 8, 821: 4, 823: 7, 832: 8, 840: 5, 842: 6, 844: 8, 866: 4, 869: 4, 961: 8, 969: 8, 977: 8, 979: 7, 988: 6, 989: 8, 995: 7, 1001: 5, 1003: 5, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1187: 4, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1227: 4, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1273: 3, 1275: 3, 1280: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1417: 8, 1601: 8, 1602: 8, 1618: 8, 1906: 7, 1907: 7, 1910: 7, 1912: 7, 1922: 7, 1927: 7, 1928: 7, 1930: 7, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2024: 8, 2025: 8, 2028: 8
|
||||
},
|
||||
{
|
||||
201: 8, 493: 8, 495: 4, 193: 8, 197: 8, 209: 7, 171: 8, 456: 8, 199: 4, 489: 8, 211: 2, 499: 3, 390: 7, 532: 6, 568: 1, 761: 7, 381: 6, 485: 8, 189: 7, 479: 3, 711: 6, 501: 8, 241: 6, 717: 5, 869: 4, 389: 2, 454: 8, 170: 8, 190: 6, 497: 8, 417: 7, 419: 1, 426: 7, 451: 8, 452: 8, 453: 6, 500: 6, 508: 8, 528: 4, 647: 3, 1105: 6, 1005: 6, 481: 7, 844: 8, 866: 4, 564: 5, 969: 8, 388: 8, 352: 5, 562: 8, 961: 8, 386: 8, 707: 8, 977: 8, 979: 7, 298: 8, 840: 5, 842: 5, 988: 6, 1001: 8, 560: 8, 546: 7, 558: 8, 309: 8, 995: 7, 311: 8, 566: 5, 567:3, 989: 8, 384: 4, 800: 6, 1033: 7, 1034: 7, 313: 8, 554: 3, 810: 8, 1017: 8, 1019: 2, 1020: 8, 1217: 8, 1223: 3, 1233: 8, 1227: 4, 1417: 8, 1009: 8, 1221: 5, 1275: 3, 1225: 7, 289: 8, 550: 8, 1273: 3, 1928: 7, 1187: 4, 1265: 8, 1927: 7, 1267: 1, 1906: 7, 288: 5, 304: 1, 328: 1, 1912: 7, 320: 3, 1910: 7, 563: 5, 1249: 8, 1930: 7, 1257: 6, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 565: 5, 1280: 4, 1907: 7
|
||||
},
|
||||
# Volt Premier w/o ACC 2018 + Pedal
|
||||
{
|
||||
189: 7, 193: 8, 197: 8, 201: 8, 209: 7, 211: 2, 241: 6, 288: 5, 298: 8, 304: 1, 308: 4, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 451: 8, 452: 8, 453: 6, 479: 3, 481: 7, 485: 8, 489: 8, 493: 8, 497: 8, 500: 6, 501: 8, 513: 6, 528: 4, 532: 6, 560: 8, 562: 8, 563: 5, 565: 5, 566: 5, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 717: 5, 761: 7, 800: 6, 810: 8, 840: 5, 842: 5, 844: 8, 869: 4, 977: 8, 1001: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1922: 7, 1930: 7
|
||||
}
|
||||
],
|
||||
CAR.BUICK_REGAL: [{
|
||||
190: 8, 193: 8, 197: 8, 199: 4, 201: 8, 209: 7, 211: 8, 241: 6, 249: 8, 288: 5, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 322: 7, 328: 1, 352: 5, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 7, 413: 8, 417: 8, 419: 8, 422: 4, 426: 8, 431: 8, 442: 8, 451: 8, 452: 8, 453: 8, 455: 7, 456: 8, 463: 3, 479: 8, 481: 7, 485: 8, 487: 8, 489: 8, 495: 8, 497: 8, 499: 3, 500: 8, 501: 8, 508: 8, 528: 5, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 565: 5, 567: 5, 569: 3, 573: 1, 577: 8, 578: 8, 579: 8, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 3, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 882: 8, 884: 8, 890: 1, 892: 2, 893: 2, 894: 1, 961: 8, 967: 8, 969: 8, 977: 8, 979: 8, 985: 8, 1001: 8, 1005: 6, 1009: 8, 1011: 8, 1013: 3, 1017: 8, 1020: 8, 1024: 8, 1025: 8, 1026: 8, 1027: 8, 1028: 8, 1029: 8, 1030: 8, 1031: 8, 1032: 2, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 8, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 8, 1263: 8, 1265: 8, 1267: 8, 1271: 8, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1601: 8, 1602: 8, 1603: 7, 1611: 8, 1618: 8, 1906: 8, 1907: 7, 1912: 7, 1914: 7, 1916: 7, 1919: 7, 1930: 7, 2016: 8, 2018: 8, 2019: 8, 2024: 8, 2026: 8
|
||||
}],
|
||||
@@ -207,7 +207,6 @@ FINGERPRINTS = {
|
||||
FINGERPRINTS.update({
|
||||
CAR.CHEVROLET_VOLT_ASCM: FINGERPRINTS[CAR.CHEVROLET_VOLT],
|
||||
CAR.CHEVROLET_VOLT_CAMERA: [{**fp, CAMERA_DIAGNOSTIC_ADDRESS: 8, CAMERA_DIAGNOSTIC_RX_ADDRESS: 8} for fp in FINGERPRINTS[CAR.CHEVROLET_VOLT]],
|
||||
CAR.CHEVROLET_VOLT_CC: FINGERPRINTS[CAR.CHEVROLET_VOLT],
|
||||
CAR.GMC_ACADIA_ASCM: FINGERPRINTS[CAR.GMC_ACADIA],
|
||||
CAR.CHEVROLET_MALIBU_ASCM: FINGERPRINTS[CAR.CHEVROLET_MALIBU],
|
||||
CAR.CADILLAC_ESCALADE_ASCM: FINGERPRINTS[CAR.CADILLAC_ESCALADE],
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
from opendbc.car import DT_CTRL
|
||||
from opendbc.car import DT_CTRL, structs
|
||||
from opendbc.car.can_definitions import CanData
|
||||
from opendbc.car.common.conversions import Conversions as CV
|
||||
from opendbc.car.gm.values import CAR, CanBus, CruiseButtons, GMFlags
|
||||
@@ -420,9 +420,11 @@ def create_gm_cc_spam_command(packer, controller, CS, actuators, starpilot_toggl
|
||||
idx = (CS.buttons_counter + 1) % 4 # Need to predict the next idx for '22-23 EUV
|
||||
msgs = [create_buttons(packer, CanBus.POWERTRAIN, idx, cruise_btn)]
|
||||
|
||||
# Flashed camera-forward Volt CC installs also need the button spoof on the
|
||||
# camera side. Removed-camera installs set NO_CAMERA and keep this PT-only.
|
||||
if CS.CP.carFingerprint == CAR.CHEVROLET_VOLT_CC and not (CS.CP.flags & GMFlags.NO_CAMERA.value):
|
||||
# A camera-forward Volt CC install needs the button spoof on both sides.
|
||||
# The OBD-C/L&P gateway variant has no camera bus and remains PT-only.
|
||||
if (CS.CP.carFingerprint == CAR.CHEVROLET_VOLT_CC and
|
||||
getattr(CS.CP, "networkLocation", None) == structs.CarParams.NetworkLocation.fwdCamera and
|
||||
not (CS.CP.flags & GMFlags.NO_CAMERA.value)):
|
||||
msgs.append(create_buttons(packer, CanBus.CAMERA, idx, cruise_btn))
|
||||
return msgs
|
||||
else:
|
||||
|
||||
@@ -273,7 +273,6 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
kaofui_camera_cars = {
|
||||
CAR.CHEVROLET_VOLT_CAMERA,
|
||||
CAR.CHEVROLET_VOLT_CC,
|
||||
CAR.CHEVROLET_MALIBU_HYBRID_CC,
|
||||
}
|
||||
bolt_cc_camera_cars = {
|
||||
@@ -685,6 +684,8 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if candidate in CC_ONLY_CAR:
|
||||
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_NO_ACC.value
|
||||
if candidate == CAR.CHEVROLET_VOLT_CC and ret.networkLocation == NetworkLocation.gateway:
|
||||
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_VOLT_CC_GATEWAY.value
|
||||
|
||||
if candidate in SDGM_CAR and ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
|
||||
ret.flags |= GMFlags.FORCE_BRAKE_C9.value
|
||||
@@ -698,7 +699,7 @@ class CarInterface(CarInterfaceBase):
|
||||
|
||||
if ACCELERATOR_POS_MSG not in fingerprint[CanBus.POWERTRAIN]:
|
||||
ret.flags |= GMFlags.NO_ACCELERATOR_POS_MSG.value
|
||||
if candidate == CAR.CHEVROLET_VOLT and ret.networkLocation == NetworkLocation.gateway:
|
||||
if candidate in (CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_CC) and ret.networkLocation == NetworkLocation.gateway:
|
||||
# Reuse the no-camera safety bit as an ASCM Volt selector for the alternate EBCM brake path.
|
||||
ret.safetyConfigs[0].safetyParam |= GMSafetyFlags.FLAG_GM_NO_CAMERA.value
|
||||
|
||||
|
||||
@@ -201,6 +201,45 @@ class TestGMInterface:
|
||||
assert car_params.flags & GMFlags.NO_CAMERA.value
|
||||
assert car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_NO_CAMERA.value
|
||||
|
||||
def test_volt_cc_obd_gateway_uses_cc_long_no_camera_path(self):
|
||||
CarInterface = interfaces[CAR.CHEVROLET_VOLT_CC]
|
||||
car_params = CarInterface.get_params(
|
||||
CAR.CHEVROLET_VOLT_CC,
|
||||
_empty_fingerprint(),
|
||||
[],
|
||||
alpha_long=False,
|
||||
is_release=False,
|
||||
docs=False,
|
||||
starpilot_toggles=_test_starpilot_toggles(),
|
||||
)
|
||||
|
||||
assert car_params.networkLocation == structs.CarParams.NetworkLocation.gateway
|
||||
assert car_params.flags & GMFlags.CC_LONG.value
|
||||
assert car_params.flags & GMFlags.NO_CAMERA.value
|
||||
assert not (car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.HW_CAM.value)
|
||||
assert car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_CC_LONG.value
|
||||
assert car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_NO_ACC.value
|
||||
assert car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_NO_CAMERA.value
|
||||
|
||||
parsers = CarInterface.CarState.get_can_parsers(car_params)
|
||||
assert "ECMCruiseControl" in parsers[Bus.pt].vl
|
||||
assert not parsers[Bus.cam].vl
|
||||
|
||||
def test_other_cc_only_gateway_does_not_use_volt_cc_safety_path(self):
|
||||
CarInterface = interfaces[CAR.CHEVROLET_SILVERADO_CC]
|
||||
car_params = CarInterface.get_params(
|
||||
CAR.CHEVROLET_SILVERADO_CC,
|
||||
_empty_fingerprint(),
|
||||
[],
|
||||
alpha_long=False,
|
||||
is_release=False,
|
||||
docs=False,
|
||||
starpilot_toggles=_test_starpilot_toggles(),
|
||||
)
|
||||
|
||||
assert car_params.networkLocation == structs.CarParams.NetworkLocation.gateway
|
||||
assert not (car_params.safetyConfigs[0].safetyParam & GMSafetyFlags.FLAG_GM_VOLT_CC_GATEWAY.value)
|
||||
|
||||
def test_volt_ascm_sparse_fingerprint_without_camera_does_not_set_no_camera(self):
|
||||
CarInterface = interfaces[CAR.CHEVROLET_VOLT_ASCM]
|
||||
fingerprint = {
|
||||
@@ -533,6 +572,7 @@ class TestGMCarController:
|
||||
CP=SimpleNamespace(
|
||||
carFingerprint=CAR.CHEVROLET_VOLT_CC,
|
||||
flags=0,
|
||||
networkLocation=structs.CarParams.NetworkLocation.fwdCamera,
|
||||
minEnableSpeed=24 * CV.MPH_TO_MS,
|
||||
),
|
||||
buttons_counter=2,
|
||||
@@ -554,6 +594,7 @@ class TestGMCarController:
|
||||
CP=SimpleNamespace(
|
||||
carFingerprint=CAR.CHEVROLET_VOLT_CC,
|
||||
flags=GMFlags.NO_CAMERA.value,
|
||||
networkLocation=structs.CarParams.NetworkLocation.gateway,
|
||||
minEnableSpeed=24 * CV.MPH_TO_MS,
|
||||
),
|
||||
buttons_counter=2,
|
||||
|
||||
@@ -175,6 +175,7 @@ class GMSafetyFlags(IntFlag):
|
||||
FLAG_GM_REMOTE_START_BOOTS_COMMA = 8192
|
||||
FLAG_GM_PANDA_3D1_SCHED = 16384
|
||||
FLAG_GM_PANDA_PADDLE_SCHED = 32768
|
||||
FLAG_GM_VOLT_CC_GATEWAY = 16384
|
||||
|
||||
|
||||
class Footnote(Enum):
|
||||
@@ -247,7 +248,7 @@ class CAR(Platforms):
|
||||
dbc_dict=CHEVROLET_VOLT.dbc_dict,
|
||||
)
|
||||
CHEVROLET_VOLT_CC = GMPlatformConfig(
|
||||
[GMCarDocs("Chevrolet Volt No-ACC 2017-18", min_enable_speed=0)],
|
||||
[GMCarDocs("Chevrolet Volt No-ACC 2016-18 (OBD-C / L&P Harness)", "Redneck ACC", min_enable_speed=0)],
|
||||
CHEVROLET_VOLT.specs,
|
||||
dbc_dict=CHEVROLET_VOLT.dbc_dict,
|
||||
)
|
||||
|
||||
@@ -257,6 +257,10 @@ class CarInterfaceBase(ABC):
|
||||
if getattr(starpilot_toggles, "always_on_lateral_lkas", False):
|
||||
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
if candidate == HYUNDAI.HYUNDAI_ELANTRA_HEV_2024 and \
|
||||
getattr(starpilot_toggles, "always_on_lateral_main", False):
|
||||
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
# LKASButtonControl == 9 means BUTTON_FUNCTIONS["AOL_TOGGLE"] in starpilot_variables.
|
||||
if params.get_bool("AlwaysOnLateral") and params.get_int("LKASButtonControl") == 9:
|
||||
fp_ret.safetyConfigs[-1].safetyParam |= HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
@@ -300,6 +300,30 @@ class TestCarInterfaces:
|
||||
)
|
||||
assert fp_car_params.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
def test_hyundai_elantra_hev_auto_aol_sets_lkas_on_engage_flag(self):
|
||||
toggles = get_test_starpilot_toggles()
|
||||
toggles.always_on_lateral_main = True
|
||||
fingerprint = {bus: {} for bus in range(8)}
|
||||
|
||||
car_params = HyundaiCarInterface.get_params(
|
||||
HYUNDAI_CAR.HYUNDAI_ELANTRA_HEV_2024,
|
||||
fingerprint,
|
||||
[],
|
||||
alpha_long=True,
|
||||
is_release=False,
|
||||
docs=False,
|
||||
starpilot_toggles=toggles,
|
||||
)
|
||||
fp_car_params = HyundaiCarInterface.get_starpilot_params(
|
||||
HYUNDAI_CAR.HYUNDAI_ELANTRA_HEV_2024,
|
||||
fingerprint,
|
||||
[],
|
||||
car_params,
|
||||
toggles,
|
||||
)
|
||||
|
||||
assert fp_car_params.safetyConfigs[-1].safetyParam & HyundaiStarPilotSafetyFlags.AOL_LKAS_ON_ENGAGE.value
|
||||
|
||||
def test_toyota_disable_openpilot_long_sets_stock_long_safety_flag(self):
|
||||
CarInterface = interfaces[TOYOTA_CAR.TOYOTA_PRIUS_TSS2]
|
||||
fingerprint = {bus: {} for bus in range(8)}
|
||||
|
||||
@@ -559,6 +559,7 @@ static safety_config gm_init(uint16_t param) {
|
||||
const uint16_t GM_PARAM_REMOTE_START_BOOTS_COMMA = 8192;
|
||||
const uint16_t GM_PARAM_PANDA_3D1_SCHED = 16384;
|
||||
const uint16_t GM_PARAM_PANDA_PADDLE_SCHED = 32768U;
|
||||
const uint16_t GM_PARAM_VOLT_CC_GATEWAY = 16384U;
|
||||
|
||||
static const LongitudinalLimits GM_ASCM_LONG_LIMITS = {
|
||||
.max_gas = 8191,
|
||||
@@ -706,6 +707,11 @@ static safety_config gm_init(uint16_t param) {
|
||||
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false},
|
||||
{0x184, 2, 8, .check_relay = false}, {0x1E1, 2, 7, .check_relay = false}}; // camera bus
|
||||
|
||||
static const CanMsg GM_CC_LONG_ASCM_TX_MSGS[] = {{0x180, 0, 4, .check_relay = true}, {0x409, 0, 7, .check_relay = false},
|
||||
{0x40A, 0, 7, .check_relay = false}, {0x370, 0, 6, .check_relay = false},
|
||||
{0x1E1, 0, 7, .check_relay = false}, {0x3D1, 0, 8, .check_relay = false},
|
||||
{0xBD, 0, 7, .check_relay = false}, {0x1F5, 0, 8, .check_relay = false}};
|
||||
|
||||
gm_hw = GET_FLAG(param, GM_PARAM_HW_CAM) ? GM_CAM : GM_ASCM;
|
||||
gm_sdgm = GET_FLAG(param, GM_PARAM_HW_SDGM);
|
||||
gm_ascm_int = GET_FLAG(param, GM_PARAM_HW_ASCM_INT);
|
||||
@@ -714,6 +720,7 @@ static safety_config gm_init(uint16_t param) {
|
||||
gm_cc_long = GET_FLAG(param, GM_PARAM_CC_LONG);
|
||||
gm_has_acc = !GET_FLAG(param, GM_PARAM_NO_ACC);
|
||||
gm_pedal_long = GET_FLAG(param, GM_PARAM_PEDAL_LONG);
|
||||
const bool gm_volt_cc_gateway = GET_FLAG(param, GM_PARAM_VOLT_CC_GATEWAY) && gm_no_camera && !gm_pedal_long && !gm_has_acc;
|
||||
enable_gas_interceptor = GET_FLAG(param, GM_PARAM_PEDAL_INTERCEPTOR);
|
||||
gm_force_ascm = GET_FLAG(param, GM_PARAM_HW_ASCM_LONG);
|
||||
gm_force_brake_c9 = GET_FLAG(param, GM_PARAM_FORCE_BRAKE_C9);
|
||||
@@ -781,6 +788,8 @@ static safety_config gm_init(uint16_t param) {
|
||||
} else {
|
||||
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_SDGM_TX_MSGS);
|
||||
}
|
||||
} else if (gm_cc_long && gm_volt_cc_gateway && (gm_hw == GM_ASCM) && !gm_sdgm) {
|
||||
ret = BUILD_SAFETY_CFG(gm_rx_checks, GM_CC_LONG_ASCM_TX_MSGS);
|
||||
} else if ((gm_hw == GM_CAM) || gm_sdgm) {
|
||||
// FIXME: cppcheck thinks that gm_cam_long is always false. This is not true
|
||||
// if ALLOW_DEBUG is defined but cppcheck is run without ALLOW_DEBUG
|
||||
|
||||
@@ -59,6 +59,28 @@ def test_gm_panda_scheduler_paths():
|
||||
safety.safety_rx_hook(prndl)
|
||||
|
||||
|
||||
def test_gm_cc_longitudinal_ascm_safety_whitelist():
|
||||
safety = libsafety_py.libsafety
|
||||
flags = (GMSafetyFlags.FLAG_GM_NO_CAMERA | GMSafetyFlags.FLAG_GM_NO_ACC |
|
||||
GMSafetyFlags.FLAG_GM_CC_LONG | GMSafetyFlags.FLAG_GM_VOLT_CC_GATEWAY)
|
||||
assert safety.set_safety_hooks(CarParams.SafetyModel.gm, flags) == 0
|
||||
safety.init_tests()
|
||||
safety.set_controls_allowed(True)
|
||||
safety.set_cruise_engaged_prev(True)
|
||||
|
||||
allowed = ((0x180, 0, 4), (0x409, 0, 7), (0x40A, 0, 7), (0x370, 0, 6),
|
||||
(0x1E1, 0, 7), (0x3D1, 0, 8), (0xBD, 0, 7), (0x1F5, 0, 8))
|
||||
for addr, bus, length in allowed:
|
||||
data = b'\x00' * length
|
||||
if addr == 0x1E1:
|
||||
data = data[:5] + b'\x10' + data[6:]
|
||||
assert safety.safety_tx_hook(common.make_msg(bus, addr, length, data))
|
||||
|
||||
blocked = ((0x184, 2, 8), (0x200, 0, 6), (0x2CB, 0, 8), (0x306, 1, 8))
|
||||
for addr, bus, length in blocked:
|
||||
assert not safety.safety_tx_hook(common.make_msg(bus, addr, length))
|
||||
|
||||
|
||||
def test_gm_bolt_acc_pedal_clears_stock_cruise():
|
||||
safety = libsafety_py.libsafety
|
||||
flags = GMSafetyFlags.HW_CAM | GMSafetyFlags.FLAG_GM_GAS_INTERCEPTOR | GMSafetyFlags.FLAG_GM_BOLT_2022_PEDAL
|
||||
|
||||
@@ -260,6 +260,23 @@ def test_curve_speed_controller_learns_when_speed_is_manually_controlled(long_ac
|
||||
assert not vcruise.csc_controlling_speed
|
||||
|
||||
|
||||
def test_curve_speed_controller_learns_when_longitudinal_override_event_is_active():
|
||||
planner, vcruise = make_vcruise(road_curvature=0.02)
|
||||
sm = make_sm(standstill=False)
|
||||
sm["onroadEvents"] = [SimpleNamespace(overrideLongitudinal=True)]
|
||||
toggles = make_toggles()
|
||||
toggles.curve_speed_controller = True
|
||||
planner.driving_in_curve = True
|
||||
planner.road_curvature_detected = True
|
||||
planner.lateral_acceleration = 2.4
|
||||
vcruise.csc.training_timer = PLANNER_TIME
|
||||
|
||||
update_vcruise(vcruise, sm, toggles, now=50.0, v_ego=20.0)
|
||||
|
||||
assert vcruise.csc.enable_training
|
||||
assert vcruise.csc.curvature_data["0.02"]["count"] == 1
|
||||
|
||||
|
||||
def test_curve_speed_controller_persists_data_after_leaving_curve():
|
||||
planner, vcruise = make_vcruise(road_curvature=0.02)
|
||||
sm = make_sm(standstill=False)
|
||||
|
||||
@@ -686,12 +686,12 @@ class StarPilotLongitudinalLayout(_SettingsPage):
|
||||
self._curve_speed_controller_rows = [
|
||||
SettingRow("CalibratedLatAccel", "value", tr_noop("Calibrated Lateral Accel"),
|
||||
subtitle=tr_noop("The learned lateral acceleration from collected driving data. Higher values allow faster cornering."),
|
||||
get_value=lambda: f"{self._params_memory.get_float('CalibratedLateralAcceleration'):.2f} m/s",
|
||||
get_value=lambda: f"{self._params.get_float('CalibratedLateralAcceleration'):.2f} m/s",
|
||||
on_click=None,
|
||||
visible=csc_on),
|
||||
SettingRow("CalibrationProgress", "value", tr_noop("Calibration Progress"),
|
||||
subtitle=tr_noop("How much curve data has been collected. Normal for the value to stay low."),
|
||||
get_value=lambda: f"{self._params_memory.get_float('CalibrationProgress'):.2f}%",
|
||||
get_value=lambda: f"{self._params.get_float('CalibrationProgress'):.2f}%",
|
||||
on_click=None,
|
||||
visible=csc_on),
|
||||
SettingRow("ResetCurve", "action", tr_noop("Reset Curve Data"),
|
||||
|
||||
@@ -39,6 +39,7 @@ _GREEN = rl.Color(34, 197, 94, 255)
|
||||
_AMBER = rl.Color(251, 191, 36, 255)
|
||||
_ORANGE = rl.Color(234, 88, 12, 255)
|
||||
_RED = rl.Color(201, 34, 49, 255)
|
||||
_TRAINING = rl.Color(112, 192, 216, 255)
|
||||
|
||||
_last_was_active = False
|
||||
_activation_start = 0.0
|
||||
@@ -57,7 +58,7 @@ def _csc_state():
|
||||
|
||||
plan = sm["starpilotPlan"]
|
||||
params = ui_state.ui_params
|
||||
if plan.speedLimitChanged or not params.get_bool("ShowCSCStatus"):
|
||||
if not params.get_bool("ShowCSCStatus"):
|
||||
return None
|
||||
|
||||
car_state = sm["carState"]
|
||||
@@ -113,7 +114,8 @@ def _render_csc_glow(border_rect: rl.Rectangle, border_width: float = UI_BORDER_
|
||||
state = _csc_state()
|
||||
now = rl.get_time()
|
||||
|
||||
if state is None or not state['active']:
|
||||
visible = state is not None and (state['active'] or state['training'])
|
||||
if not visible:
|
||||
if _last_was_active:
|
||||
_fade_out_start = now
|
||||
_last_was_active = False
|
||||
@@ -131,9 +133,9 @@ def _render_csc_glow(border_rect: rl.Rectangle, border_width: float = UI_BORDER_
|
||||
_fade_out_start = 0.0
|
||||
_last_was_active = True
|
||||
|
||||
intensity = _intensity(state['curvature'])
|
||||
intensity = _intensity(state['curvature']) if state['active'] else _GLOW_BASE_INTENSITY
|
||||
period = _glow_period(intensity)
|
||||
color = _glow_color(intensity)
|
||||
color = _glow_color(intensity) if state['active'] else _TRAINING
|
||||
t_norm = max(0.0, min(1.0, (intensity - _GLOW_BASE_INTENSITY) / (1.0 - _GLOW_BASE_INTENSITY)))
|
||||
_last_state = (intensity, period, color, t_norm)
|
||||
fade = min(1.0, (now - _activation_start) / _GLOW_FADE_IN_DURATION)
|
||||
|
||||
@@ -1043,6 +1043,30 @@
|
||||
"parent_key": "CurveSpeedController",
|
||||
"settings_tier": "simple"
|
||||
},
|
||||
{
|
||||
"key": "CalibratedLateralAcceleration",
|
||||
"label": "Calibrated Lateral Accel",
|
||||
"description": "The learned lateral acceleration from collected driving data. Higher values allow faster cornering.",
|
||||
"picker_description": "Learned cornering comfort from your driving data.",
|
||||
"data_type": "float",
|
||||
"ui_type": "readout",
|
||||
"precision": 2,
|
||||
"unit": " m/s²",
|
||||
"parent_key": "CurveSpeedController",
|
||||
"settings_tier": "simple"
|
||||
},
|
||||
{
|
||||
"key": "CalibrationProgress",
|
||||
"label": "Calibration Progress",
|
||||
"description": "How much curve data has been collected. Normal for the value to stay low.",
|
||||
"picker_description": "How much curve data has been collected.",
|
||||
"data_type": "float",
|
||||
"ui_type": "readout",
|
||||
"precision": 2,
|
||||
"unit": "%",
|
||||
"parent_key": "CurveSpeedController",
|
||||
"settings_tier": "simple"
|
||||
},
|
||||
{
|
||||
"key": "ResetCurveData",
|
||||
"label": "Reset Curve Data",
|
||||
|
||||
@@ -54,7 +54,7 @@ class CurveSpeedController:
|
||||
self.required_curvatures = [str(round(road_curvature, ROUNDING_PRECISION)) for road_curvature in np.arange(MIN_CURVATURE, MAX_CURVATURE + STEP, STEP)]
|
||||
|
||||
self.update_lateral_acceleration()
|
||||
self._publish_calibration_progress()
|
||||
self._publish_calibration_progress(persist=True)
|
||||
|
||||
@staticmethod
|
||||
def _bucket_curvature(road_curvature):
|
||||
@@ -117,8 +117,11 @@ class CurveSpeedController:
|
||||
progress += min(self.curvature_data[key]["count"] / CALIBRATION_PROGRESS_THRESHOLD, 1.0)
|
||||
return (progress / len(self.required_curvatures)) * 100
|
||||
|
||||
def _publish_calibration_progress(self):
|
||||
self._put_memory_param("CalibrationProgress", self._calibration_progress())
|
||||
def _publish_calibration_progress(self, persist=False):
|
||||
progress = self._calibration_progress()
|
||||
if persist:
|
||||
self.starpilot_planner.params.put_nonblocking("CalibrationProgress", progress)
|
||||
self._put_memory_param("CalibrationProgress", progress)
|
||||
|
||||
def _put_memory_param(self, key, value):
|
||||
params_memory = getattr(self.starpilot_planner, "params_memory", None)
|
||||
|
||||
@@ -384,6 +384,13 @@
|
||||
padding: 0.2rem 0.6rem;
|
||||
}
|
||||
|
||||
.ds-row-readout {
|
||||
background-color: transparent;
|
||||
border: none;
|
||||
color: var(--text-muted);
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
.ds-stepper-container {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,8 @@ let flmWorkspaceInflight = null
|
||||
let lastFlmWorkspaceFetch = 0
|
||||
let favoritePollInflight = null
|
||||
let favoritePollTimer = null
|
||||
let cscCalibrationPollInflight = null
|
||||
let cscCalibrationPollTimer = null
|
||||
const DYNAMIC_DEFAULT_DEP_KEYS = new Set(["AccelerationProfile", "EVTuning", "TruckTuning"])
|
||||
const PANDA_FIRMWARE_TOGGLE_KEYS = new Set(["IgnoreIgnitionLine", "RemoteStartBootsComma", "HKGRemoteStartBootsComma"])
|
||||
const FLM_ADVANCED_LATERAL_KEYS = new Set([
|
||||
@@ -479,6 +481,16 @@ function formatSliderValue(val, stepStr, precisionInt, key) {
|
||||
return Number(v.toFixed(dec)).toString()
|
||||
}
|
||||
|
||||
function formatReadoutValue(p) {
|
||||
const raw = state.values[p.key]
|
||||
const value = parseFloat(raw)
|
||||
if (raw === undefined || raw === null || Number.isNaN(value)) return "--"
|
||||
|
||||
const precision = p.precision !== undefined && p.precision !== null ? Number(p.precision) : 2
|
||||
const formatted = Number(value.toFixed(Math.max(0, precision))).toString()
|
||||
return p.unit ? `${formatted}${p.unit}` : formatted
|
||||
}
|
||||
|
||||
function formatNumericForInput(value, precision) {
|
||||
const n = Number(value)
|
||||
if (!Number.isFinite(n)) return ""
|
||||
@@ -674,6 +686,51 @@ function ensureFavoriteValuePolling() {
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
async function refreshCscCalibrationValues() {
|
||||
if (cscCalibrationPollInflight || state.loadingValues) return cscCalibrationPollInflight
|
||||
|
||||
cscCalibrationPollInflight = Promise.all(
|
||||
["CalibratedLateralAcceleration", "CalibrationProgress"].map(async key => {
|
||||
const response = await fetch(`/api/params_memory?key=${encodeURIComponent(key)}`, { cache: "no-store" })
|
||||
if (!response.ok) return [key, null]
|
||||
const raw = (await response.text()).trim()
|
||||
const value = Number(raw)
|
||||
return [key, Number.isFinite(value) && raw !== "" ? value : null]
|
||||
}),
|
||||
).then(entries => {
|
||||
const nextValues = { ...state.values }
|
||||
let changed = false
|
||||
for (const [key, value] of entries) {
|
||||
if (value === null || nextValues[key] === value) continue
|
||||
nextValues[key] = value
|
||||
changed = true
|
||||
}
|
||||
if (changed) {
|
||||
state.values = nextValues
|
||||
scheduleSyncInputs()
|
||||
}
|
||||
}).catch(() => {}).finally(() => {
|
||||
cscCalibrationPollInflight = null
|
||||
})
|
||||
|
||||
return cscCalibrationPollInflight
|
||||
}
|
||||
|
||||
function ensureCscCalibrationPolling() {
|
||||
if (cscCalibrationPollTimer !== null) return
|
||||
|
||||
cscCalibrationPollTimer = setInterval(() => {
|
||||
if (!window.location.pathname.startsWith("/device_settings")) {
|
||||
clearInterval(cscCalibrationPollTimer)
|
||||
cscCalibrationPollTimer = null
|
||||
return
|
||||
}
|
||||
if (document.visibilityState === "visible") {
|
||||
refreshCscCalibrationValues()
|
||||
}
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
async function saveFavoriteSlots(slots) {
|
||||
if (state.favoriteSaving) return
|
||||
|
||||
@@ -1493,6 +1550,7 @@ function renderSettingRow(p) {
|
||||
const isText = p.ui_type === "text"
|
||||
const isColor = p.ui_type === "color"
|
||||
const isAction = p.ui_type === "action"
|
||||
const isReadout = p.ui_type === "readout"
|
||||
const isGroup = isGroupParam(p)
|
||||
const isChild = p.parent_key ? "ds-child-modifier" : ""
|
||||
const lockReason = () => getSettingLockReason(p)
|
||||
@@ -1643,7 +1701,7 @@ function renderSettingRow(p) {
|
||||
@click="${() => resetColorParam(p)}">Stock</button>
|
||||
</div>
|
||||
`
|
||||
} else if (!isGroup) {
|
||||
} else if (!isGroup && !isReadout) {
|
||||
if (p.key === "IsRHD") {
|
||||
rowControl = html`
|
||||
<div style="display:flex; align-items:center; gap:0.75rem;">
|
||||
@@ -1713,8 +1771,9 @@ function renderSettingRow(p) {
|
||||
</div>
|
||||
` : ""}
|
||||
</div>
|
||||
${(isNumeric || isColor) ? html`<span class="ds-row-value" id="ds-display-${p.key}">${() => {
|
||||
${(isNumeric || isColor || isReadout) ? html`<span class="ds-row-value ${isReadout ? "ds-row-readout" : ""}" id="ds-display-${p.key}">${() => {
|
||||
if (isColor) return formatColorDisplayValue(p)
|
||||
if (isReadout) return formatReadoutValue(p)
|
||||
const currentValue = state.sliderPreviewValues[p.key] ?? state.values[p.key]
|
||||
const bounds = numericBounds(p)
|
||||
return currentValue !== undefined ? formatSliderValue(currentValue, String(bounds.step), p.precision, p.key) : ".."
|
||||
@@ -1769,6 +1828,7 @@ export function DeviceSettings({ params }) {
|
||||
|
||||
fetchFlmWorkspace()
|
||||
ensureFavoriteValuePolling()
|
||||
ensureCscCalibrationPolling()
|
||||
|
||||
if (!state.fetched) {
|
||||
state.fetched = true
|
||||
|
||||
@@ -135,6 +135,17 @@ def test_curve_speed_controller_no_lead_toggle_is_nested_under_csc():
|
||||
assert _declared_default("CurveSpeedControllerNoLead") == "0"
|
||||
|
||||
|
||||
def test_curve_speed_controller_readouts_are_display_only_and_nested():
|
||||
csc = _params_by_section(_layout())["Longitudinal (Speed & Following)"]
|
||||
|
||||
for key, unit in (("CalibratedLateralAcceleration", " m/s²"), ("CalibrationProgress", "%")):
|
||||
readout = csc[key]
|
||||
assert readout["ui_type"] == "readout"
|
||||
assert readout["parent_key"] == "CurveSpeedController"
|
||||
assert readout["unit"] == unit
|
||||
assert readout["settings_tier"] == "simple"
|
||||
|
||||
|
||||
def test_every_galaxy_setting_has_a_shared_settings_tier():
|
||||
layout = _layout()
|
||||
tiers = {
|
||||
|
||||
@@ -256,6 +256,27 @@ def test_device_settings_layout_asset_is_served_from_common_catalog(monkeypatch)
|
||||
assert response.get_json() == the_galaxy.load_settings_catalog()
|
||||
|
||||
|
||||
def test_params_all_exposes_curve_calibration_readouts(monkeypatch):
|
||||
client, _ = _params_client(monkeypatch, {
|
||||
"CalibratedLateralAcceleration": 2.73,
|
||||
"CalibrationProgress": 48.0,
|
||||
}, "tici")
|
||||
monkeypatch.setattr(
|
||||
the_galaxy,
|
||||
"_params_live_raw",
|
||||
WritableFakeParams({
|
||||
"CalibratedLateralAcceleration": 2.73,
|
||||
"CalibrationProgress": 48.0,
|
||||
}),
|
||||
)
|
||||
|
||||
response = client.get("/api/params/all")
|
||||
|
||||
assert response.status_code == 200
|
||||
assert response.get_json()["CalibratedLateralAcceleration"] == 2.73
|
||||
assert response.get_json()["CalibrationProgress"] == 48.0
|
||||
|
||||
|
||||
def test_ford_lateral_mode_is_editable_through_galaxy(monkeypatch):
|
||||
client, fake_params = _params_client(monkeypatch, {
|
||||
"CarMake": "Ford",
|
||||
@@ -391,6 +412,12 @@ def test_curve_speed_controller_reset_clears_learned_data_offroad(monkeypatch):
|
||||
"CalibrationProgress": 48.0,
|
||||
"CurvatureData": {"0.01": {"average": 2.73, "count": 12}},
|
||||
}, "tici")
|
||||
fake_memory = WritableFakeParams({
|
||||
"CalibratedLateralAcceleration": 2.73,
|
||||
"CalibrationProgress": 48.0,
|
||||
"CurvatureData": {"0.01": {"average": 2.73, "count": 12}},
|
||||
})
|
||||
monkeypatch.setattr(the_galaxy, "params_memory", fake_memory)
|
||||
|
||||
response = client.post("/api/curve_speed_controller/reset")
|
||||
|
||||
@@ -403,6 +430,11 @@ def test_curve_speed_controller_reset_clears_learned_data_offroad(monkeypatch):
|
||||
assert "CalibrationProgress" not in fake_params.values
|
||||
assert "CurvatureData" not in fake_params.values
|
||||
assert fake_params.removals == ["CalibrationProgress", "CurvatureData"]
|
||||
assert fake_memory.values == {
|
||||
"CalibratedLateralAcceleration": 2.0,
|
||||
"CalibrationProgress": 0.0,
|
||||
}
|
||||
assert fake_memory.removals == ["CurvatureData"]
|
||||
|
||||
|
||||
def test_curve_speed_controller_reset_rejected_onroad(monkeypatch):
|
||||
|
||||
@@ -5456,6 +5456,9 @@ def setup(app):
|
||||
params.put("CalibratedLateralAcceleration", 2.0)
|
||||
params.remove("CalibrationProgress")
|
||||
params.remove("CurvatureData")
|
||||
params_memory.put("CalibratedLateralAcceleration", 2.0)
|
||||
params_memory.put("CalibrationProgress", 0.0)
|
||||
params_memory.remove("CurvatureData")
|
||||
|
||||
return jsonify({
|
||||
"message": "Curve Speed Controller data reset. Training will restart on the next drive.",
|
||||
@@ -5484,6 +5487,12 @@ def setup(app):
|
||||
result["AlphaLongitudinalAvailable"] = _get_alpha_longitudinal_available()
|
||||
result["HasRivianAngleHarness"] = _get_has_rivian_angle_harness()
|
||||
|
||||
for key in ("CalibratedLateralAcceleration", "CalibrationProgress"):
|
||||
try:
|
||||
result[key] = _get_current_param_value(key, float, defaults_lookup)
|
||||
except Exception:
|
||||
result[key] = None
|
||||
|
||||
return jsonify(_sanitize_json_value(result)), 200
|
||||
|
||||
@app.route("/api/params/defaults", methods=["GET"])
|
||||
|
||||
Reference in New Issue
Block a user