From b1f84f94001e6c8de8bcedb72652831de01dcee4 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 10 Feb 2023 22:28:47 -0800 Subject: [PATCH 01/63] Chrysler: setup panda safety flag for old tuning's steer limits --- panda | 2 +- selfdrive/car/chrysler/interface.py | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/panda b/panda index 7d27eb10fb..b29ae782f7 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 7d27eb10fb32095e73f60c59a123cae08cc53719 +Subproject commit b29ae782f78be87e7ac1414773c6015b14eea728 diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 657b018c00..4b22c478a7 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -23,6 +23,9 @@ class CarInterface(CarInterfaceBase): elif candidate in RAM_DT: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_RAM_DT + if candidate in CHRYSLER_OLD_TUNING_BLACKLIST: + ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_LOWER_RATE + ret.minSteerSpeed = 3.8 # m/s CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) if candidate not in RAM_CARS: From 69e52f02fd21844ff068c495b7fcb01ebc53bea5 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 10 Feb 2023 22:43:19 -0800 Subject: [PATCH 02/63] bump panda --- panda | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda b/panda index b29ae782f7..d15250cb14 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit b29ae782f78be87e7ac1414773c6015b14eea728 +Subproject commit d15250cb1454292c6f1217c79642b9ffd93e7595 From 4f2134468f2b2b94daa24d9ba80cc70da0ad8224 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 10 Feb 2023 23:46:48 -0800 Subject: [PATCH 03/63] events: reword ESP off alert (#27304) * Rename event * rename to Control * rename to disabled --- selfdrive/controls/lib/events.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index 3036828662..6d5ed45076 100644 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -729,8 +729,8 @@ EVENTS: Dict[int, Dict[str, Union[Alert, AlertCallbackType]]] = { }, EventName.espDisabled: { - ET.SOFT_DISABLE: soft_disable_alert("ESP Off"), - ET.NO_ENTRY: NoEntryAlert("ESP Off"), + ET.SOFT_DISABLE: soft_disable_alert("Electronic Stability Control Disabled"), + ET.NO_ENTRY: NoEntryAlert("Electronic Stability Control Disabled"), }, EventName.lowBattery: { From ed52916d55cd802be60b9db03f3ce7fe131fcef2 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 10 Feb 2023 23:47:01 -0800 Subject: [PATCH 04/63] update chrysler test segment with new flag --- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/test/process_replay/test_processes.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 0081a20e21..10665ae18c 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -fbf92051507b7a7585907b58baadec6b8cc475af +69e52f02fd21844ff068c495b7fcb01ebc53bea5 \ No newline at end of file diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 569090f606..3ff3d36ebc 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -48,7 +48,7 @@ segments = [ ("TOYOTA3", "regen89026F6BD8D|2022-09-27--15-45-37--0"), ("HONDA", "regenC7D5645EB17|2022-09-27--15-47-29--0"), ("HONDA2", "regenCC2ECCE5742|2022-09-27--16-18-01--0"), - ("CHRYSLER", "regenC253C4DAC90|2022-09-27--15-51-03--0"), + ("CHRYSLER", "regenC253C4DAC90|2023-02-10--15-51-03--0"), ("RAM", "regen20490083AE7|2022-09-27--15-53-15--0"), ("SUBARU", "regen1E72BBDCED5|2022-09-27--15-55-31--0"), ("GM", "regen45B05A80EF6|2022-09-27--15-57-22--0"), From 7b654337d6b47e14e0df76ffa43aeac8869e8245 Mon Sep 17 00:00:00 2001 From: Kyumin Han Date: Sat, 11 Feb 2023 01:04:17 -0700 Subject: [PATCH 05/63] HKG: remove Kia Stinger 2018 from legacy safety mode (#27302) * Remove Kia stinger from legacy safety system array Enable OP long * update docs --------- Co-authored-by: Shane Smiskol --- docs/CARS.md | 2 +- selfdrive/car/hyundai/values.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/CARS.md b/docs/CARS.md index 74e64b969f..e6b6bbee7d 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -119,7 +119,7 @@ A supported vehicle is one that just works when you install a comma three. All s |Kia|Sorento Plug-in Hybrid 2022-23[5](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai A|| |Kia|Sportage 2023[5](#footnotes)|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|| |Kia|Sportage Hybrid 2023[5](#footnotes)|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai N|| -|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|Stock|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|| +|Kia|Stinger 2018-20|Smart Cruise Control (SCC)|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai C|| |Kia|Stinger 2022|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai K|| |Kia|Telluride 2020-22|All|openpilot available[1](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|Hyundai H|| |Lexus|CT Hybrid 2017-18|Lexus Safety System+|openpilot available[2](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|Toyota|| diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 2241b871a1..bde38b47cc 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1669,7 +1669,8 @@ HYBRID_CAR = {CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.KIA_NIRO_PHEV, CAR.KIA_N EV_CAR = {CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.KIA_NIRO_EV, CAR.KONA_EV_2022, CAR.KIA_EV6, CAR.IONIQ_5, CAR.GENESIS_GV60_EV_1ST_GEN} # these cars require a special panda safety mode due to missing counters and checksums in the messages -LEGACY_SAFETY_MODE_CAR = {CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_LF, CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.VELOSTER, CAR.KIA_STINGER, CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.KIA_CEED, CAR.ELANTRA, CAR.IONIQ_HEV_2022} +LEGACY_SAFETY_MODE_CAR = {CAR.HYUNDAI_GENESIS, CAR.IONIQ_EV_2020, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV, CAR.IONIQ, CAR.KONA_EV, CAR.KIA_SORENTO, CAR.SONATA_LF, CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.VELOSTER, + CAR.GENESIS_G70, CAR.GENESIS_G80, CAR.KIA_CEED, CAR.ELANTRA, CAR.IONIQ_HEV_2022} # If 0x500 is present on bus 1 it probably has a Mando radar outputting radar points. # If no points are outputted by default it might be possible to turn it on using selfdrive/debug/hyundai_enable_radar_points.py From 6474e16a720e88181f03652dcfe91306ddbdc06e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Sat, 11 Feb 2023 00:12:33 -0800 Subject: [PATCH 06/63] GM: add permanent ACC fault signal (#27306) * bump opendbc * check signal * bump opendbc --- opendbc | 2 +- selfdrive/car/gm/carstate.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/opendbc b/opendbc index 6eab6cf6ad..510bfc0695 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 6eab6cf6ad5ac69539037f4508582fbfaf239eab +Subproject commit 510bfc06954e31257f8d8de17adf92f9a68a1b71 diff --git a/selfdrive/car/gm/carstate.py b/selfdrive/car/gm/carstate.py index 90705d871e..3c7d35f2dc 100644 --- a/selfdrive/car/gm/carstate.py +++ b/selfdrive/car/gm/carstate.py @@ -100,7 +100,8 @@ class CarState(CarStateBase): ret.parkingBrake = pt_cp.vl["VehicleIgnitionAlt"]["ParkBrake"] == 1 ret.cruiseState.available = pt_cp.vl["ECMEngineStatus"]["CruiseMainOn"] != 0 ret.espDisabled = pt_cp.vl["ESPStatus"]["TractionControlOn"] != 1 - ret.accFaulted = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.FAULTED + ret.accFaulted = (pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.FAULTED or + pt_cp.vl["EBCMFrictionBrakeStatus"]["FrictionBrakeUnavailable"] == 1) ret.cruiseState.enabled = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.OFF ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL @@ -155,6 +156,7 @@ class CarState(CarStateBase): ("RLWheelSpd", "EBCMWheelSpdRear"), ("RRWheelSpd", "EBCMWheelSpdRear"), ("MovingBackward", "EBCMWheelSpdRear"), + ("FrictionBrakeUnavailable", "EBCMFrictionBrakeStatus"), ("PRNDL2", "ECMPRDNL2"), ("ManualMode", "ECMPRDNL2"), ("LKADriverAppldTrq", "PSCMStatus"), @@ -180,6 +182,7 @@ class CarState(CarStateBase): ("VehicleIgnitionAlt", 10), ("EBCMWheelSpdFront", 20), ("EBCMWheelSpdRear", 20), + ("EBCMFrictionBrakeStatus", 20), ("AcceleratorPedal2", 33), ("ASCMSteeringButton", 33), ("ECMEngineStatus", 100), From 4998b600ecebf712b127b1e132d249a1b51a90bc Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 11 Feb 2023 17:57:10 -0800 Subject: [PATCH 07/63] more release notes --- RELEASES.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index ded06346c6..f3d4cfb64f 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,12 +1,12 @@ -Version 0.9.1 (2023-2-20) +Version 0.9.1 (2023-2-23) ======================== -* Adjust alert volume using ambient noise level -* Removed driver monitoring timer resetting on interaction if face detected and distracted -* UI updates - * Driver monitoring icon shows driver's head pose - * German translation thanks to Vrabetz and CzokNorris! * New driving model * 30% improved height estimation resulting in better driving performance for tall cars +* Driver monitoring: removed timer resetting on user interaction if distracted +* UI updates + * Adjust alert volume using ambient noise level + * Driver monitoring icon shows driver's head pose + * German translation thanks to Vrabetz and CzokNorris! * Chevrolet Bolt EV 2022-23 support thanks to JasonJShuler! * Genesis GV60 2023 support thanks to sunnyhaibin! * Hyundai Tucson 2022-23 support From 341eb2e0fd46b79eeb4096b28443f304c3e71528 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 11 Feb 2023 21:12:07 -0800 Subject: [PATCH 08/63] boardd: retry on bad SPI RX data len (#27314) Co-authored-by: Comma Device --- selfdrive/boardd/spi.cc | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/selfdrive/boardd/spi.cc b/selfdrive/boardd/spi.cc index c9d4b2ea0e..9a10e30f95 100644 --- a/selfdrive/boardd/spi.cc +++ b/selfdrive/boardd/spi.cc @@ -316,7 +316,10 @@ int PandaSpiHandle::spi_transfer(uint8_t endpoint, uint8_t *tx_data, uint16_t tx goto transfer_fail; } rx_data_len = *(uint16_t *)(rx_buf+1); - assert(rx_data_len < SPI_BUF_SIZE); + if (rx_data_len >= SPI_BUF_SIZE) { + LOGE("SPI: RX data len larger than buf size %d", rx_data_len); + goto transfer_fail; + } // Read data transfer.len = rx_data_len + 1; From f71aad955ca906a69da6d24dee63d1482077de8e Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 13 Feb 2023 10:49:33 +0800 Subject: [PATCH 09/63] cabana: cancel signal highlighting on leaveEvent (#27315) cacnel signal hilighting on leaveEvent --- tools/cabana/signaledit.cc | 5 +++++ tools/cabana/signaledit.h | 1 + 2 files changed, 6 insertions(+) diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 7988037c34..0499b1be8a 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -449,3 +449,8 @@ void SignalView::signalHovered(const Signal *sig) { } } } + +void SignalView::leaveEvent(QEvent *event) { + emit highlight(nullptr); + QWidget::leaveEvent(event); +} diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index 6a904e7328..c0b649209a 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -89,6 +89,7 @@ signals: private: void rowsChanged(); + void leaveEvent(QEvent *event); QString msg_id; QTreeView *tree; From e219da29b28807a324af1e9c54a3791d8e295230 Mon Sep 17 00:00:00 2001 From: Miniz199922 <124948595+Miniz199922@users.noreply.github.com> Date: Sun, 12 Feb 2023 21:55:31 -0500 Subject: [PATCH 10/63] Chrysler: add missing 2020 Jeep SRT address (#27312) * 2020 Jeep srt fingerprint Please update to include my 2020 Jeep srt * Update selfdrive/car/chrysler/values.py * Revert "Update selfdrive/car/chrysler/values.py" This reverts commit 83fc38acbf7e7b257713a0a85096d7d34a6e0c90. * Update selfdrive/car/chrysler/values.py * rm new fp --------- Co-authored-by: Shane Smiskol --- selfdrive/car/chrysler/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 49f8a080cb..c6b8bcadb0 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -142,7 +142,7 @@ FINGERPRINTS = { }], CAR.JEEP_CHEROKEE_2019: [{ # Jeep Grand Cherokee 2019, including most 2020 models - 55: 8, 168: 8, 179: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 341: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 640: 1, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 840: 8, 844: 5, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 960: 4, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 8, 1225: 8, 1227: 8, 1235: 8, 1242: 8, 1250: 8, 1251: 8, 1252: 8, 1254: 8, 1264: 8, 1284: 8, 1536: 8, 1537: 8, 1543: 8, 1545: 8, 1562: 8, 1568: 8, 1570: 8, 1572: 8, 1593: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1867: 8, 1875: 8, 1882: 8, 1890: 8, 1891: 8, 1892: 8, 1894: 8, 1896: 8, 1904: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8 + 55: 8, 168: 8, 179: 8, 181: 8, 256: 4, 257: 5, 258: 8, 264: 8, 268: 8, 272: 6, 273: 6, 274: 2, 280: 8, 284: 8, 288: 7, 290: 6, 292: 8, 300: 8, 308: 8, 320: 8, 324: 8, 331: 8, 332: 8, 341: 8, 344: 8, 352: 8, 362: 8, 368: 8, 376: 3, 384: 8, 388: 4, 416: 7, 448: 6, 456: 4, 464: 8, 500: 8, 501: 8, 512: 8, 514: 8, 520: 8, 530: 8, 532: 8, 544: 8, 557: 8, 559: 8, 560: 8, 564: 8, 571: 3, 579: 8, 584: 8, 608: 8, 618: 8, 624: 8, 625: 8, 632: 8, 639: 8, 640: 1, 656: 4, 658: 6, 660: 8, 671: 8, 672: 8, 676: 8, 678: 8, 680: 8, 683: 8, 684: 8, 703: 8, 705: 8, 706: 8, 709: 8, 710: 8, 719: 8, 720: 6, 729: 5, 736: 8, 737: 8, 738: 8, 746: 5, 752: 2, 754: 8, 760: 8, 761: 8, 764: 8, 766: 8, 773: 8, 776: 8, 779: 8, 782: 8, 783: 8, 784: 8, 785: 8, 792: 8, 799: 8, 800: 8, 804: 8, 806: 2, 808: 8, 810: 8, 816: 8, 817: 8, 820: 8, 825: 2, 826: 8, 831: 6, 832: 8, 838: 2, 840: 8, 844: 5, 847: 1, 848: 8, 853: 8, 856: 4, 860: 6, 863: 8, 874: 2, 882: 8, 897: 8, 906: 8, 924: 8, 937: 8, 938: 8, 939: 8, 940: 8, 941: 8, 942: 8, 943: 8, 947: 8, 948: 8, 960: 4, 968: 8, 969: 4, 970: 8, 973: 8, 974: 5, 976: 8, 977: 4, 979: 8, 980: 8, 981: 8, 982: 8, 983: 8, 984: 8, 992: 8, 993: 7, 995: 8, 996: 8, 1000: 8, 1001: 8, 1002: 8, 1003: 8, 1008: 8, 1009: 8, 1010: 8, 1011: 8, 1012: 8, 1013: 8, 1014: 8, 1015: 8, 1024: 8, 1025: 8, 1026: 8, 1031: 8, 1033: 8, 1050: 8, 1059: 8, 1062: 8, 1098: 8, 1100: 8, 1216: 8, 1218: 8, 1220: 8, 1223: 8, 1225: 8, 1227: 8, 1235: 8, 1242: 8, 1250: 8, 1251: 8, 1252: 8, 1254: 8, 1264: 8, 1284: 8, 1536: 8, 1537: 8, 1543: 8, 1545: 8, 1562: 8, 1568: 8, 1570: 8, 1572: 8, 1593: 8, 1856: 8, 1858: 8, 1860: 8, 1863: 8, 1865: 8, 1867: 8, 1875: 8, 1882: 8, 1890: 8, 1891: 8, 1892: 8, 1894: 8, 1896: 8, 1904: 8, 2015: 8, 2016: 8, 2017: 8, 2024: 8, 2025: 8 }], } From 38cf0b8382d6f41e4e9ccd2610bdabe34ff33a87 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 13 Feb 2023 12:11:32 +0800 Subject: [PATCH 11/63] cabana: fixed the buggy has_more_data, reduce unncessary calls to fetchMore (#27319) --- tools/cabana/historylog.cc | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 3a3397af42..e4ad99758b 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -81,11 +81,12 @@ void HistoryLogModel::updateState() { if (!msg_id.isEmpty()) { uint64_t current_time = (can->lastMessage(msg_id).ts + can->routeStartTime()) * 1e9 + 1; auto new_msgs = dynamic_mode ? fetchData(current_time, last_fetch_time) : fetchData(0); - if ((has_more_data = !new_msgs.empty())) { + if (!new_msgs.empty()) { beginInsertRows({}, 0, new_msgs.size() - 1); messages.insert(messages.begin(), std::move_iterator(new_msgs.begin()), std::move_iterator(new_msgs.end())); endInsertRows(); } + has_more_data = new_msgs.size() >= batch_size; last_fetch_time = current_time; } } @@ -93,11 +94,12 @@ void HistoryLogModel::updateState() { void HistoryLogModel::fetchMore(const QModelIndex &parent) { if (!messages.empty()) { auto new_msgs = fetchData(messages.back().mono_time); - if ((has_more_data = !new_msgs.empty())) { + if (!new_msgs.empty()) { beginInsertRows({}, messages.size(), messages.size() + new_msgs.size() - 1); messages.insert(messages.end(), std::move_iterator(new_msgs.begin()), std::move_iterator(new_msgs.end())); endInsertRows(); } + has_more_data = new_msgs.size() >= batch_size; } } From fff6e8baf6791382fc350950ee02e2ab0db78e44 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Mon, 13 Feb 2023 12:11:55 +0800 Subject: [PATCH 12/63] cabana: fix crash in BinaryView::refresh (#27318) --- tools/cabana/binaryview.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index a46c25bdfa..52b31b3559 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -143,8 +143,8 @@ void BinaryView::refresh() { anchor_index = QModelIndex(); resize_sig = nullptr; hovered_sig = nullptr; - highlightPosition(QCursor::pos()); model->refresh(); + highlightPosition(QCursor::pos()); } QSet BinaryView::getOverlappingSignals() const { From e952ad2c66ccaf68027509f5da6b310ddb9c35db Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 14 Feb 2023 02:44:44 +0800 Subject: [PATCH 13/63] cabana: draw borders around signals (#27307) * cabana: draw borders around signals * add padding * merge #27294 * add comment * typo * fix alpha * cleanup * spacing =2 --------- Co-authored-by: Willem Melching --- tools/cabana/binaryview.cc | 86 +++++++++++++++++++++++++++++++------- tools/cabana/binaryview.h | 2 + 2 files changed, 74 insertions(+), 14 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 52b31b3559..6f62a04871 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -1,5 +1,7 @@ #include "tools/cabana/binaryview.h" +#include + #include #include #include @@ -7,8 +9,6 @@ #include #include -#include - #include "tools/cabana/commands.h" #include "tools/cabana/streams/abstractstream.h" @@ -83,7 +83,7 @@ void BinaryView::mousePressEvent(QMouseEvent *event) { if (bit_idx == s->lsb || bit_idx == s->msb) { anchor_index = model->bitIndex(bit_idx == s->lsb ? s->msb : s->lsb, true); resize_sig = s; - delegate->selection_color = item->bg_color; + delegate->selection_color = getColor(s); break; } } @@ -266,6 +266,17 @@ BinaryItemDelegate::BinaryItemDelegate(QObject *parent) : QStyledItemDelegate(pa hex_font.setBold(true); } +bool BinaryItemDelegate::isSameColor(const QModelIndex &index, int dx, int dy) const { + QModelIndex index2 = index.sibling(index.row() + dy, index.column() + dx); + if (!index2.isValid()) { + return false; + } + auto color1 = ((const BinaryViewModel::Item *)index.internalPointer())->bg_color; + auto color2 = ((const BinaryViewModel::Item *)index2.internalPointer())->bg_color; + // Ignore alpha + return (color1.red() == color2.red()) && (color2.green() == color2.green()) && (color1.blue() == color2.blue()); +} + void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { auto item = (const BinaryViewModel::Item *)index.internalPointer(); BinaryView *bin_view = (BinaryView *)parent(); @@ -277,24 +288,71 @@ void BinaryItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op } else if (option.state & QStyle::State_Selected) { painter->fillRect(option.rect, selection_color); painter->setPen(option.palette.color(QPalette::BrightText)); - } else if (!item->sigs.isEmpty() && (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig))) { - bool sig_hovered = item->sigs.contains(bin_view->hovered_sig); - int min_alpha = item->sigs.contains(bin_view->hovered_sig) ? 255 : 50; + } else if (!bin_view->selectionModel()->hasSelection() || !item->sigs.contains(bin_view->resize_sig)) { // not resizing QColor bg = item->bg_color; - if (bg.alpha() < min_alpha) { - bg.setAlpha(min_alpha); + if (bin_view->hovered_sig && item->sigs.contains(bin_view->hovered_sig)) { + bg.setAlpha(255); + painter->fillRect(option.rect, bg.darker(125)); // 4/5x brightness + painter->setPen(option.palette.color(QPalette::BrightText)); + } else { + if (item->sigs.size() > 0) { + drawBorder(painter, option, index); + bg.setAlpha(std::max(50, bg.alpha())); + } + painter->fillRect(option.rect, bg); + painter->setPen(Qt::black); } - painter->fillRect(option.rect, sig_hovered ? bg.darker(125) : bg); // 4/5x brightness - painter->setPen(sig_hovered ? option.palette.color(QPalette::BrightText) : Qt::black); - } else { - painter->fillRect(option.rect, item->bg_color); } - painter->drawText(option.rect, Qt::AlignCenter, item->val); if (item->is_msb || item->is_lsb) { painter->setFont(small_font); - painter->drawText(option.rect, Qt::AlignHCenter | Qt::AlignBottom, item->is_msb ? "MSB" : "LSB"); + painter->drawText(option.rect.adjusted(8, 0, -8, -3), Qt::AlignRight | Qt::AlignBottom, item->is_msb ? "M" : "L"); } painter->restore(); } + +// Draw border on edge of signal +void BinaryItemDelegate::drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { + auto item = (const BinaryViewModel::Item *)index.internalPointer(); + QColor border_color = item->bg_color; + border_color.setAlphaF(1.0); + + bool draw_left = !isSameColor(index, -1, 0); + bool draw_top = !isSameColor(index, 0, -1); + bool draw_right = !isSameColor(index, 1, 0); + bool draw_bottom = !isSameColor(index, 0, 1); + + const int spacing = 2; + QRect rc = option.rect.adjusted(draw_left * 3, draw_top * spacing, draw_right * -3, draw_bottom * -spacing); + QRegion subtract; + if (!draw_top) { + if (!draw_left && !isSameColor(index, -1, -1)) { + subtract += QRect{rc.left(), rc.top(), 3, spacing}; + } else if (!draw_right && !isSameColor(index, 1, -1)) { + subtract += QRect{rc.right() - 2, rc.top(), 3, spacing}; + } + } + if (!draw_bottom) { + if (!draw_left && !isSameColor(index, -1, 1)) { + subtract += QRect{rc.left(), rc.bottom() - (spacing - 1), 3, spacing}; + } else if (!draw_right && !isSameColor(index, 1, 1)) { + subtract += QRect{rc.right() - 2, rc.bottom() - (spacing - 1), 3, spacing}; + } + } + + painter->setPen(QPen(border_color, 1)); + if (draw_left) painter->drawLine(rc.topLeft(), rc.bottomLeft()); + if (draw_right) painter->drawLine(rc.topRight(), rc.bottomRight()); + if (draw_bottom) painter->drawLine(rc.bottomLeft(), rc.bottomRight()); + if (draw_top) painter->drawLine(rc.topLeft(), rc.topRight()); + + painter->setClipRegion(QRegion(rc).subtracted(subtract)); + if (!subtract.isEmpty()) { + // fill gaps inside corners. + painter->setPen(QPen(border_color, 2)); + for (auto &r : subtract) { + painter->drawRect(r); + } + } +} diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index d006672793..18d87bdd57 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -13,6 +13,8 @@ public: BinaryItemDelegate(QObject *parent); void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const override; void setSelectionColor(const QColor &color) { selection_color = color; } + bool isSameColor(const QModelIndex &index, int dx, int dy) const; + void drawBorder(QPainter* painter, const QStyleOptionViewItem &option, const QModelIndex &index) const; QFont small_font, hex_font; QColor selection_color; From 507badb11717e23681ddaf7a3f54ebe348978aef Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 14 Feb 2023 06:40:47 +0800 Subject: [PATCH 14/63] cabana: set legend marker shape by the series type (#27296) set legend marker shape by the series type --- tools/cabana/chartswidget.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 5063ec9dea..aceef40556 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -780,8 +780,10 @@ QXYSeries *ChartView::createSeries(QAbstractSeries::SeriesType type, QColor colo QXYSeries *series = nullptr; if (type == QAbstractSeries::SeriesTypeLine) { series = new QLineSeries(this); + chart()->legend()->setMarkerShape(QLegend::MarkerShapeRectangle); } else { series = new QScatterSeries(this); + chart()->legend()->setMarkerShape(QLegend::MarkerShapeCircle); } series->setColor(color); // TODO: Due to a bug in CameraWidget the camera frames From e3de6b88342f050edc0eb89d65b55de0fe2f1a8c Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Mon, 13 Feb 2023 16:15:59 -0800 Subject: [PATCH 15/63] Chrysler: revert torque tuning (#27327) * Chrysler: revert torque tuning * update refs * update refs + route --- panda | 2 +- selfdrive/car/chrysler/interface.py | 23 ++++++++----------- selfdrive/car/chrysler/values.py | 11 ++------- selfdrive/test/process_replay/ref_commit | 2 +- .../test/process_replay/test_processes.py | 2 +- 5 files changed, 14 insertions(+), 26 deletions(-) diff --git a/panda b/panda index d15250cb14..14051f9ce3 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit d15250cb1454292c6f1217c79642b9ffd93e7595 +Subproject commit 14051f9ce3c9cbaf7044c81c9902dd0f1cea3980 diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 4b22c478a7..961684f398 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -2,7 +2,7 @@ from cereal import car from panda import Panda from selfdrive.car import STD_CARGO_KG, get_safety_config -from selfdrive.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, CHRYSLER_OLD_TUNING_BLACKLIST, ChryslerFlags +from selfdrive.car.chrysler.values import CAR, RAM_HD, RAM_DT, RAM_CARS, ChryslerFlags from selfdrive.car.interfaces import CarInterfaceBase @@ -23,9 +23,6 @@ class CarInterface(CarInterfaceBase): elif candidate in RAM_DT: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_RAM_DT - if candidate in CHRYSLER_OLD_TUNING_BLACKLIST: - ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_LOWER_RATE - ret.minSteerSpeed = 3.8 # m/s CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) if candidate not in RAM_CARS: @@ -41,11 +38,10 @@ class CarInterface(CarInterfaceBase): ret.wheelbase = 3.089 ret.steerRatio = 16.2 # Pacifica Hybrid 2017 - if candidate in CHRYSLER_OLD_TUNING_BLACKLIST: - ret.lateralTuning.init('pid') - ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] - ret.lateralTuning.pid.kf = 0.00006 + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] + ret.lateralTuning.pid.kf = 0.00006 # Jeep elif candidate in (CAR.JEEP_CHEROKEE, CAR.JEEP_CHEROKEE_2019): @@ -54,11 +50,10 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 16.7 ret.steerActuatorDelay = 0.2 - if candidate in CHRYSLER_OLD_TUNING_BLACKLIST: - ret.lateralTuning.init('pid') - ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] - ret.lateralTuning.pid.kf = 0.00006 + ret.lateralTuning.init('pid') + ret.lateralTuning.pid.kpBP, ret.lateralTuning.pid.kiBP = [[9., 20.], [9., 20.]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.15, 0.30], [0.03, 0.05]] + ret.lateralTuning.pid.kf = 0.00006 # Ram elif candidate == CAR.RAM_1500: diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index c6b8bcadb0..16ebb4fa11 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -46,12 +46,8 @@ class CarControllerParams: self.STEER_DELTA_DOWN = 6 self.STEER_MAX = 261 # EPS allows more, up to 350? else: - if CP.carFingerprint in CHRYSLER_OLD_TUNING_BLACKLIST: - self.STEER_DELTA_UP = 3 - self.STEER_DELTA_DOWN = 3 - else: - self.STEER_DELTA_UP = 6 - self.STEER_DELTA_DOWN = 6 + self.STEER_DELTA_UP = 3 + self.STEER_DELTA_DOWN = 3 self.STEER_MAX = 261 # higher than this faults the EPS STEER_THRESHOLD = 120 @@ -60,9 +56,6 @@ RAM_DT = {CAR.RAM_1500, } RAM_HD = {CAR.RAM_HD, } RAM_CARS = RAM_DT | RAM_HD -# the increased steer rate hasn't been verified on these cars. -# remove from this list once it's been tested and confirmed to not fault -CHRYSLER_OLD_TUNING_BLACKLIST = {CAR.PACIFICA_2017_HYBRID, CAR.PACIFICA_2018_HYBRID, CAR.PACIFICA_2020, CAR.JEEP_CHEROKEE} @dataclass class ChryslerCarInfo(CarInfo): diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 10665ae18c..98c78d3be3 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -69e52f02fd21844ff068c495b7fcb01ebc53bea5 \ No newline at end of file +5244c5fea84822bdbcd899a280090e47fb0581b7 \ No newline at end of file diff --git a/selfdrive/test/process_replay/test_processes.py b/selfdrive/test/process_replay/test_processes.py index 3ff3d36ebc..569090f606 100755 --- a/selfdrive/test/process_replay/test_processes.py +++ b/selfdrive/test/process_replay/test_processes.py @@ -48,7 +48,7 @@ segments = [ ("TOYOTA3", "regen89026F6BD8D|2022-09-27--15-45-37--0"), ("HONDA", "regenC7D5645EB17|2022-09-27--15-47-29--0"), ("HONDA2", "regenCC2ECCE5742|2022-09-27--16-18-01--0"), - ("CHRYSLER", "regenC253C4DAC90|2023-02-10--15-51-03--0"), + ("CHRYSLER", "regenC253C4DAC90|2022-09-27--15-51-03--0"), ("RAM", "regen20490083AE7|2022-09-27--15-53-15--0"), ("SUBARU", "regen1E72BBDCED5|2022-09-27--15-55-31--0"), ("GM", "regen45B05A80EF6|2022-09-27--15-57-22--0"), From fe6dc7842ec6ffe7a79c98d3dfe701bd101032c6 Mon Sep 17 00:00:00 2001 From: Nelson Chen Date: Mon, 13 Feb 2023 17:06:43 -0800 Subject: [PATCH 16/63] Make the latest month in releases.md consistent with 0-padding (#27330) --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f3d4cfb64f..ceae8d10cb 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,4 +1,4 @@ -Version 0.9.1 (2023-2-23) +Version 0.9.1 (2023-02-23) ======================== * New driving model * 30% improved height estimation resulting in better driving performance for tall cars From d5d19978ad9de0066be943019bd5b7fd89af3487 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 14 Feb 2023 10:25:59 +0800 Subject: [PATCH 17/63] cabana: add name validation when editing message (#27316) * check duplicate name * cant use ' untitled' as msg name * const QString UNTITLED --- tools/cabana/dbcmanager.h | 6 ++++-- tools/cabana/detailwidget.cc | 35 ++++++++++++++++++++++++++--------- tools/cabana/detailwidget.h | 5 +++++ 3 files changed, 35 insertions(+), 11 deletions(-) diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 41471a6169..7571d1c44e 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -54,6 +54,8 @@ private: std::map msgs; }; +const QString UNTITLED = "untitled"; + // TODO: Add helper function in dbc.h double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig); bool operator==(const Signal &l, const Signal &r); @@ -63,7 +65,7 @@ int bigEndianBitIndex(int index); void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size); std::pair getSignalRange(const Signal *s); DBCManager *dbc(); -inline QString msgName(const QString &id, const char *def = "untitled") { +inline QString msgName(const QString &id) { auto msg = dbc()->msg(id); - return msg ? msg->name : def; + return msg ? msg->name : UNTITLED; } diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 25d9b3b9ca..27c8cbccc9 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -1,6 +1,5 @@ #include "tools/cabana/detailwidget.h" -#include #include #include #include @@ -190,11 +189,13 @@ void DetailWidget::removeMsg() { // EditMessageDialog -EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) : QDialog(parent) { - setWindowTitle(tr("Edit message")); +EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) + : original_name(title), QDialog(parent) { + setWindowTitle(tr("Edit message: %1").arg(msg_id)); QFormLayout *form_layout = new QFormLayout(this); - form_layout->addRow("ID", new QLabel(msg_id)); + form_layout->addRow("", error_label = new QLabel); + error_label->setVisible(false); name_edit = new QLineEdit(title, this); name_edit->setValidator(new NameValidator(name_edit)); form_layout->addRow(tr("Name"), name_edit); @@ -205,12 +206,28 @@ EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title size_spin->setValue(size); form_layout->addRow(tr("Size"), size_spin); - auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); - form_layout->addRow(buttonBox); - setFixedWidth(parent->width() * 0.9); + btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + btn_box->button(QDialogButtonBox::Ok)->setEnabled(false); + form_layout->addRow(btn_box); - connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); - connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); + setFixedWidth(parent->width() * 0.9); + connect(name_edit, &QLineEdit::textEdited, this, &EditMessageDialog::validateName); + connect(btn_box, &QDialogButtonBox::accepted, this, &QDialog::accept); + connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject); +} + +void EditMessageDialog::validateName(const QString &text) { + bool valid = false; + error_label->setVisible(false); + if (!text.isEmpty() && text != original_name && text.compare(UNTITLED, Qt::CaseInsensitive) != 0) { + valid = std::none_of(dbc()->messages().begin(), dbc()->messages().end(), + [&text](auto &m) { return m.second.name == text; }); + if (!valid) { + error_label->setText(tr("Name already exists")); + error_label->setVisible(true); + } + } + btn_box->button(QDialogButtonBox::Ok)->setEnabled(valid); } // WelcomeWidget diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 0983f49924..c5d5fe9a4d 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include #include @@ -14,8 +15,12 @@ class EditMessageDialog : public QDialog { public: EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent); + void validateName(const QString &text); + QString original_name; + QDialogButtonBox *btn_box; QLineEdit *name_edit; + QLabel *error_label; QSpinBox *size_spin; }; From 65a9843ff9bbdf224d539655ea2658101df4da19 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 13 Feb 2023 21:12:13 -0800 Subject: [PATCH 18/63] Hyundai: detect LFA HDA message (#27323) * detect lfa message * comment * ? * fix * Update ref_commit --- selfdrive/car/hyundai/carcontroller.py | 6 +----- selfdrive/car/hyundai/interface.py | 4 ++++ selfdrive/car/hyundai/values.py | 3 +-- selfdrive/test/process_replay/ref_commit | 2 +- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index 7c31a48ba5..516666eff1 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -178,11 +178,7 @@ class CarController: hud_control.leadVisible, set_speed_in_units, stopping, CC.cruiseControl.override)) # 20 Hz LFA MFA message - if self.frame % 5 == 0 and self.car_fingerprint in (CAR.SONATA, CAR.PALISADE, CAR.IONIQ, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, - CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KIA_CEED, CAR.KIA_SELTOS, CAR.KONA_EV, CAR.KONA_EV_2022, - CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.SANTA_FE_2022, - CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.GENESIS_G70_2020, CAR.SANTA_FE_PHEV_2022, - CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020): + if self.frame % 5 == 0 and self.CP.flags & HyundaiFlags.SEND_LFA.value: can_sends.append(hyundaican.create_lfahda_mfc(self.packer, CC.enabled)) # 5 Hz ACC options diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index b746680930..ae0f26274c 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -43,6 +43,10 @@ class CarInterface(CarInterfaceBase): ret.flags |= HyundaiFlags.CANFD_ALT_GEARS.value if candidate not in CANFD_RADAR_SCC_CAR: ret.flags |= HyundaiFlags.CANFD_CAMERA_SCC.value + else: + # Send LFA message on cars with HDA + if 0x485 in fingerprint[2]: + ret.flags |= HyundaiFlags.SEND_LFA.value ret.steerActuatorDelay = 0.1 # Default delay ret.steerLimitTimer = 0.4 diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index bde38b47cc..261f98f38e 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -58,10 +58,9 @@ class HyundaiFlags(IntFlag): CANFD_CAMERA_SCC = 8 ALT_LIMITS = 16 - ENABLE_BLINKERS = 32 - CANFD_ALT_GEARS_2 = 64 + SEND_LFA = 128 class CAR: diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 98c78d3be3..a4811375e4 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -5244c5fea84822bdbcd899a280090e47fb0581b7 \ No newline at end of file +3629f9d22d0bd70cc9ac19cf2045a6cd47b21fdb From b536b9c4c07742a035723c3a0e1aeb646db6555a Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Mon, 13 Feb 2023 21:39:06 -0800 Subject: [PATCH 19/63] process replay: don't upload if diff doesn't exist (#27333) * fail the replay, successfully print * should still run * debug * outside? * don't fail * don't fail * don't fail * test * test * test * try this now * clean up, works! --- .github/workflows/selfdrive_tests.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/selfdrive_tests.yaml b/.github/workflows/selfdrive_tests.yaml index 834b2141d0..efddde720d 100644 --- a/.github/workflows/selfdrive_tests.yaml +++ b/.github/workflows/selfdrive_tests.yaml @@ -250,6 +250,7 @@ jobs: ${{ env.RUN }} "CI=1 coverage run selfdrive/test/process_replay/test_processes.py -j$(nproc) && \ coverage xml" - name: Print diff + id: print-diff if: always() run: cat selfdrive/test/process_replay/diff.txt - uses: actions/upload-artifact@v2 @@ -259,7 +260,7 @@ jobs: name: process_replay_diff.txt path: selfdrive/test/process_replay/diff.txt - name: Upload reference logs - if: ${{ failure() && github.event_name == 'pull_request' && github.repository == 'commaai/openpilot' && env.AZURE_TOKEN != '' }} + if: ${{ failure() && steps.print-diff.outcome == 'success' && github.event_name == 'pull_request' && github.repository == 'commaai/openpilot' && env.AZURE_TOKEN != '' }} run: | ${{ env.RUN }} "CI=1 AZURE_TOKEN='$AZURE_TOKEN' python selfdrive/test/process_replay/test_processes.py -j$(nproc) --upload-only" - name: "Upload coverage to Codecov" From a6bf26f5eb5a3cb4059783ce538901b7562a96db Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Tue, 14 Feb 2023 16:46:13 +0800 Subject: [PATCH 20/63] cabana: fix two bugs in chart (#27336) fix two bugs --- tools/cabana/chartswidget.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index aceef40556..ec54d7f06a 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -364,6 +364,8 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) { } void ChartView::addSeries(const QString &msg_id, const Signal *sig) { + if (hasSeries(msg_id, sig)) return; + QXYSeries *series = createSeries(series_type, getColor(sig)); chart()->addSeries(series); series->attachAxis(axis_x); @@ -438,9 +440,7 @@ void ChartView::manageSeries() { emit remove(); } else { for (auto s : items) { - if (!hasSeries(s->msg_id, s->sig)) { - addSeries(s->msg_id, s->sig); - } + addSeries(s->msg_id, s->sig); } for (auto it = sigs.begin(); it != sigs.end(); /**/) { bool exists = std::any_of(items.cbegin(), items.cend(), [&](auto &s) { @@ -852,7 +852,9 @@ SeriesSelector::SeriesSelector(QString title, QWidget *parent) : QDialog(parent) // buttons QVBoxLayout *btn_layout = new QVBoxLayout(); QPushButton *add_btn = new QPushButton(utils::icon("chevron-right"), "", this); + add_btn->setEnabled(false); QPushButton *remove_btn = new QPushButton(utils::icon("chevron-left"), "", this); + remove_btn->setEnabled(false); btn_layout->addStretch(0); btn_layout->addWidget(add_btn); btn_layout->addWidget(remove_btn); From 286e42948e7cd6da66bc6a6c48aedc7ff88fd9eb Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Tue, 14 Feb 2023 19:46:29 +0100 Subject: [PATCH 21/63] cabana: add keyboard shortcuts to binary view (#27338) * cabana: add keyboard shortcuts to binary view * typo * whitespace * keep signal highlighted --- tools/cabana/binaryview.cc | 59 ++++++++++++++++++++++++++++++++++++ tools/cabana/binaryview.h | 4 +++ tools/cabana/detailwidget.cc | 3 ++ 3 files changed, 66 insertions(+) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 6f62a04871..16df867d56 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -7,9 +7,11 @@ #include #include #include +#include #include #include "tools/cabana/commands.h" +#include "tools/cabana/signaledit.h" #include "tools/cabana/streams/abstractstream.h" // BinaryView @@ -38,6 +40,63 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { QObject::connect(dbc(), &DBCManager::DBCFileChanged, this, &BinaryView::refresh); QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &BinaryView::refresh); + + addShortcuts(); +} + +void BinaryView::addShortcuts() { + // Delete (x, backspace, delete) + QShortcut *shortcut_delete_x = new QShortcut(QKeySequence(Qt::Key_X), this); + QShortcut *shortcut_delete_backspace = new QShortcut(QKeySequence(Qt::Key_Backspace), this); + QShortcut *shortcut_delete_delete = new QShortcut(QKeySequence(Qt::Key_Delete), this); + QObject::connect(shortcut_delete_delete, &QShortcut::activated, shortcut_delete_x, &QShortcut::activated); + QObject::connect(shortcut_delete_backspace, &QShortcut::activated, shortcut_delete_x, &QShortcut::activated); + QObject::connect(shortcut_delete_x, &QShortcut::activated, [=]{ + if (hovered_sig != nullptr) { + emit removeSignal(hovered_sig); + hovered_sig = nullptr; + } + }); + + // Change endianness (e) + QShortcut *shortcut_endian = new QShortcut(QKeySequence(Qt::Key_E), this); + QObject::connect(shortcut_endian, &QShortcut::activated, [=]{ + if (hovered_sig != nullptr) { + const Signal *hovered_sig_prev = hovered_sig; + Signal s = *hovered_sig; + s.is_little_endian = !s.is_little_endian; + emit editSignal(hovered_sig, s); + + hovered_sig = nullptr; + highlight(hovered_sig_prev); + } + }); + + // Change signedness (s) + QShortcut *shortcut_sign = new QShortcut(QKeySequence(Qt::Key_S), this); + QObject::connect(shortcut_sign, &QShortcut::activated, [=]{ + if (hovered_sig != nullptr) { + const Signal *hovered_sig_prev = hovered_sig; + Signal s = *hovered_sig; + s.is_signed = !s.is_signed; + emit editSignal(hovered_sig, s); + + hovered_sig = nullptr; + highlight(hovered_sig_prev); + } + }); + + // Open chart (c, p, g) + QShortcut *shortcut_plot = new QShortcut(QKeySequence(Qt::Key_P), this); + QShortcut *shortcut_plot_g = new QShortcut(QKeySequence(Qt::Key_G), this); + QShortcut *shortcut_plot_c = new QShortcut(QKeySequence(Qt::Key_C), this); + QObject::connect(shortcut_plot_g, &QShortcut::activated, shortcut_plot, &QShortcut::activated); + QObject::connect(shortcut_plot_c, &QShortcut::activated, shortcut_plot, &QShortcut::activated); + QObject::connect(shortcut_plot, &QShortcut::activated, [=]{ + if (hovered_sig != nullptr) { + emit showChart(model->msg_id, hovered_sig, true, false); + } + }); } QSize BinaryView::minimumSizeHint() const { diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 18d87bdd57..7cf9a8081c 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -68,8 +68,12 @@ signals: void signalHovered(const Signal *sig); void addSignal(int start_bit, int size, bool little_endian); void resizeSignal(const Signal *sig, int from, int size); + void removeSignal(const Signal *sig); + void editSignal(const Signal *origin_s, Signal &s); + void showChart(const QString &name, const Signal *sig, bool show, bool merge); private: + void addShortcuts(); void refresh(); std::tuple getSelection(QModelIndex index); void setSelection(const QRect &rect, QItemSelectionModel::SelectionFlags flags) override; diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 27c8cbccc9..2036912344 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -74,6 +74,9 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(binary_view, &BinaryView::addSignal, signal_view->model, &SignalModel::addSignal); QObject::connect(binary_view, &BinaryView::signalHovered, signal_view, &SignalView::signalHovered); QObject::connect(binary_view, &BinaryView::signalClicked, signal_view, &SignalView::expandSignal); + QObject::connect(binary_view, &BinaryView::editSignal, signal_view->model, &SignalModel::saveSignal); + QObject::connect(binary_view, &BinaryView::removeSignal, signal_view->model, &SignalModel::removeSignal); + QObject::connect(binary_view, &BinaryView::showChart, charts, &ChartsWidget::showChart); QObject::connect(signal_view, &SignalView::showChart, charts, &ChartsWidget::showChart); QObject::connect(signal_view, &SignalView::highlight, binary_view, &BinaryView::highlight); QObject::connect(tab_widget, &QTabWidget::currentChanged, [this]() { updateState(); }); From b3f327d273c42b4852d00ded35984b833a966a2b Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 14 Feb 2023 12:51:24 -0800 Subject: [PATCH 22/63] HKG: log AEB/FCW for Optima G4 FL (#27337) FL uses FCA --- selfdrive/car/hyundai/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 261f98f38e..4ff944cebd 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1653,7 +1653,7 @@ FEATURES = { "use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022, CAR.KIA_K5_HEV_2020}, # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 - "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020}, + "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, } CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_4TH_GEN, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN, CAR.KIA_SORENTO_PHEV_4TH_GEN, CAR.GENESIS_GV60_EV_1ST_GEN, CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_NIRO_HEV_2ND_GEN} From e7786738c45aa325d2c4a3649e9b485171e18306 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 14 Feb 2023 13:14:32 -0800 Subject: [PATCH 23/63] Hyundai: temporarily remove Tucson FW that requires different tuning (#27340) --- selfdrive/car/hyundai/values.py | 1 - 1 file changed, 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 4ff944cebd..a6842ddb1d 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1562,7 +1562,6 @@ FW_VERSIONS = { CAR.TUCSON_4TH_GEN: { (Ecu.fwdCamera, 0x7c4, None): [ b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.01 99211-N9240 14T', - b'\xf1\x00NX4 FR_CMR AT USA LHD 1.00 1.00 99211-CW010 14X', ], (Ecu.fwdRadar, 0x7d0, None): [ b'\xf1\x00NX4__ 1.01 1.00 99110-N9100 ', From 1cdf80003dcaea79375cf398ec65849424f2f44b Mon Sep 17 00:00:00 2001 From: Vivek Aithal Date: Tue, 14 Feb 2023 13:22:49 -0800 Subject: [PATCH 24/63] GM: update steering limits (#27331) * reduce steer down limit, driver allowance * update refs * update refs --- panda | 2 +- selfdrive/car/gm/values.py | 4 ++-- selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/panda b/panda index 14051f9ce3..0d2ee00921 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 14051f9ce3c9cbaf7044c81c9902dd0f1cea3980 +Subproject commit 0d2ee009218009173f26c73a16aefa12dd169de8 diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 7628d8420b..1c956192eb 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -14,8 +14,8 @@ class CarControllerParams: STEER_STEP = 3 # Active control frames per command (~33hz) INACTIVE_STEER_STEP = 10 # Inactive control frames per command (10hz) STEER_DELTA_UP = 10 # Delta rates require review due to observed EPS weakness - STEER_DELTA_DOWN = 25 - STEER_DRIVER_ALLOWANCE = 50 + STEER_DELTA_DOWN = 15 + STEER_DRIVER_ALLOWANCE = 65 STEER_DRIVER_MULTIPLIER = 4 STEER_DRIVER_FACTOR = 100 NEAR_STOP_BRAKE_PHASE = 0.5 # m/s diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index a4811375e4..85c7d8e80b 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -3629f9d22d0bd70cc9ac19cf2045a6cd47b21fdb +f4efbb65a7eb9a8f4e23492372e707674f80114e \ No newline at end of file From 62b233369bed7a156a019adc5f856f913a50ce61 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 14 Feb 2023 13:27:24 -0800 Subject: [PATCH 25/63] HKG: log AEB/FCW for Kia Niro Hybrid 2021 (#27341) Kia Niro Hybrid uses FCA too --- selfdrive/car/hyundai/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index a6842ddb1d..9067299473 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1652,7 +1652,7 @@ FEATURES = { "use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022, CAR.KIA_K5_HEV_2020}, # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 - "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, + "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, } CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_4TH_GEN, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN, CAR.KIA_SORENTO_PHEV_4TH_GEN, CAR.GENESIS_GV60_EV_1ST_GEN, CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_NIRO_HEV_2ND_GEN} From 5af5f02ba82a0094c7f721ad8dd6138f503455d8 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 14 Feb 2023 13:29:23 -0800 Subject: [PATCH 26/63] better min enable speed alert (#27317) --- selfdrive/controls/lib/events.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/controls/lib/events.py b/selfdrive/controls/lib/events.py index 6d5ed45076..a85e48649f 100644 --- a/selfdrive/controls/lib/events.py +++ b/selfdrive/controls/lib/events.py @@ -230,7 +230,7 @@ def startup_master_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubM return StartupAlert("WARNING: This branch is not tested", branch, alert_status=AlertStatus.userPrompt) def below_engage_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert: - return NoEntryAlert(f"Speed Below {get_display_speed(CP.minEnableSpeed, metric)}") + return NoEntryAlert(f"Drive above {get_display_speed(CP.minEnableSpeed, metric)} to engage") def below_steer_speed_alert(CP: car.CarParams, CS: car.CarState, sm: messaging.SubMaster, metric: bool, soft_disable_time: int) -> Alert: From 6f1d5edab832487c1b11d5e36ec077fdc3def560 Mon Sep 17 00:00:00 2001 From: Mitchell Goff Date: Tue, 14 Feb 2023 14:32:08 -0800 Subject: [PATCH 27/63] Add osmnx to xx packages (#27342) --- .pre-commit-config.yaml | 2 +- poetry.lock | 269 +++++++++++++++++++++++++++++++++++++--- pyproject.toml | 3 +- 3 files changed, 254 insertions(+), 20 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index edbca52fed..1779947ff9 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: rev: v2.2.1 hooks: - id: codespell - exclude: '^(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/ui/translations/.*.ts)' + exclude: '^(third_party/)|(body/)|(cereal/)|(rednose/)|(panda/)|(laika/)|(opendbc/)|(laika_repo/)|(rednose_repo/)|(selfdrive/ui/translations/.*.ts)|(poetry.lock)' args: # if you've got a short variable name that's getting flagged, add it here - -L bu,ro,te,ue,alo,hda,ois,nam,nams,ned,som,parm,setts,inout,warmup diff --git a/poetry.lock b/poetry.lock index 8edfbb868c..91e1b5c826 100644 --- a/poetry.lock +++ b/poetry.lock @@ -564,6 +564,34 @@ python-versions = ">=3.7" [package.dependencies] colorama = {version = "*", markers = "platform_system == \"Windows\""} +[[package]] +name = "click-plugins" +version = "1.1.1" +description = "An extension module for click to enable registering CLI commands via setuptools entry-points." +category = "dev" +optional = false +python-versions = "*" + +[package.dependencies] +click = ">=4.0" + +[package.extras] +dev = ["coveralls", "pytest (>=3.6)", "pytest-cov", "wheel"] + +[[package]] +name = "cligj" +version = "0.7.2" +description = "Click params for commmand line interfaces to GeoJSON" +category = "dev" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, <4" + +[package.dependencies] +click = ">=4.0" + +[package.extras] +test = ["pytest-cov"] + [[package]] name = "cloudpickle" version = "2.2.0" @@ -959,6 +987,29 @@ python-versions = ">=3.7" docs = ["furo (>=2022.6.21)", "sphinx (>=5.1.1)", "sphinx-autodoc-typehints (>=1.19.1)"] testing = ["covdefaults (>=2.2)", "coverage (>=6.4.2)", "pytest (>=7.1.2)", "pytest-cov (>=3)", "pytest-timeout (>=2.1)"] +[[package]] +name = "fiona" +version = "1.9.1" +description = "Fiona reads and writes spatial data files" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +attrs = ">=19.2.0" +certifi = "*" +click = ">=8.0,<9.0" +click-plugins = ">=1.0" +cligj = ">=0.5" +munch = ">=2.3.2" +setuptools = "*" + +[package.extras] +all = ["Fiona[calc,s3,test]"] +calc = ["shapely"] +s3 = ["boto3 (>=1.3.1)"] +test = ["Fiona[s3]", "pytest (>=7)", "pytest-cov", "pytz"] + [[package]] name = "flake8" version = "4.0.1" @@ -1092,6 +1143,21 @@ python-versions = ">=3.7" packaging = "*" SQLAlchemy = ">=1.4" +[[package]] +name = "geopandas" +version = "0.12.2" +description = "Geographic pandas extensions" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +fiona = ">=1.8" +packaging = "*" +pandas = ">=1.0.0" +pyproj = ">=2.6.1.post1" +shapely = ">=1.7" + [[package]] name = "gevent" version = "22.10.1" @@ -2325,27 +2391,18 @@ python-versions = ">=3.5" [[package]] name = "networkx" -version = "2.3" +version = "2.8.8" description = "Python package for creating and manipulating graphs and networks" category = "dev" optional = false -python-versions = ">=3.5" - -[package.dependencies] -decorator = ">=4.3.0" +python-versions = ">=3.8" [package.extras] -all = ["gdal", "lxml", "matplotlib", "nose", "numpy", "pandas", "pydot", "pygraphviz", "pyyaml", "scipy"] -gdal = ["gdal"] -lxml = ["lxml"] -matplotlib = ["matplotlib"] -nose = ["nose"] -numpy = ["numpy"] -pandas = ["pandas"] -pydot = ["pydot"] -pygraphviz = ["pygraphviz"] -pyyaml = ["pyyaml"] -scipy = ["scipy"] +default = ["matplotlib (>=3.4)", "numpy (>=1.19)", "pandas (>=1.3)", "scipy (>=1.8)"] +developer = ["mypy (>=0.982)", "pre-commit (>=2.20)"] +doc = ["nb2plots (>=0.6)", "numpydoc (>=1.5)", "pillow (>=9.2)", "pydata-sphinx-theme (>=0.11)", "sphinx (>=5.2)", "sphinx-gallery (>=0.11)", "texext (>=0.6.6)"] +extra = ["lxml (>=4.6)", "pydot (>=1.4.2)", "pygraphviz (>=1.9)", "sympy (>=1.10)"] +test = ["codecov (>=2.1)", "pytest (>=7.2)", "pytest-cov (>=4.0)"] [[package]] name = "nodeenv" @@ -2542,6 +2599,31 @@ python-versions = ">=3.6" [package.dependencies] requests = "*" +[[package]] +name = "osmnx" +version = "1.2.2" +description = "Retrieve, model, analyze, and visualize OpenStreetMap street networks and other spatial data" +category = "dev" +optional = false +python-versions = ">=3.8" + +[package.dependencies] +geopandas = ">=0.11" +matplotlib = ">=3.5" +networkx = ">=2.8" +numpy = ">=1.22" +pandas = ">=1.4" +pyproj = ">=3.3" +requests = ">=2.28" +Rtree = ">=1.0" +Shapely = ">=1.8,<2.0" + +[package.extras] +entropy = ["scipy"] +nearest-neighbor = ["scikit-learn", "scipy"] +raster = ["gdal", "rasterio"] +web-map = ["folium"] + [[package]] name = "packaging" version = "21.3" @@ -3486,6 +3568,14 @@ python-versions = "*" numpy = ">=1.11.0" scipy = ">=0.17.1" +[[package]] +name = "rtree" +version = "1.0.1" +description = "R-Tree spatial index for Python GIS" +category = "dev" +optional = false +python-versions = ">=3.7" + [[package]] name = "s2sphere" version = "0.2.5" @@ -3688,6 +3778,19 @@ typing-extensions = "*" test = ["pytest (>=6.2)", "virtualenv (>20)"] toml = ["setuptools (>=42)"] +[[package]] +name = "shapely" +version = "1.8.5.post1" +description = "Geometric objects, predicates, and operations" +category = "dev" +optional = false +python-versions = ">=3.6" + +[package.extras] +all = ["numpy", "pytest", "pytest-cov"] +test = ["pytest", "pytest-cov"] +vectorized = ["numpy"] + [[package]] name = "shellingham" version = "1.5.0" @@ -4464,7 +4567,7 @@ testing = ["coverage (>=5.0.3)", "zope.event", "zope.testing"] [metadata] lock-version = "1.1" python-versions = "~3.8" -content-hash = "3c2597d2199a29ef79dd4d5fbc5e2350d86c82a3fe6716d13b93ebc268053eb9" +content-hash = "9e9495c896e6fd0855803aeaf46513c6c22424b86be820759a8baf27d44e73ee" [metadata.files] adal = [ @@ -4917,6 +5020,14 @@ click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] +click-plugins = [ + {file = "click-plugins-1.1.1.tar.gz", hash = "sha256:46ab999744a9d831159c3411bb0c79346d94a444df9a3a3742e9ed63645f264b"}, + {file = "click_plugins-1.1.1-py2.py3-none-any.whl", hash = "sha256:5d262006d3222f5057fd81e1623d4443e41dcda5dc815c06b442aa3c02889fc8"}, +] +cligj = [ + {file = "cligj-0.7.2-py3-none-any.whl", hash = "sha256:c1ca117dbce1fe20a5809dc96f01e1c2840f6dcc939b3ddbb1111bf330ba82df"}, + {file = "cligj-0.7.2.tar.gz", hash = "sha256:a4bc13d623356b373c2c27c53dbd9c68cae5d526270bfa71f6c6fa69669c6b27"}, +] cloudpickle = [ {file = "cloudpickle-2.2.0-py3-none-any.whl", hash = "sha256:7428798d5926d8fcbfd092d18d01a2a03daf8237d8fcdc8095d256b8490796f0"}, {file = "cloudpickle-2.2.0.tar.gz", hash = "sha256:3f4219469c55453cfe4737e564b67c2a149109dabf7f242478948b895f61106f"}, @@ -5339,6 +5450,28 @@ filelock = [ {file = "filelock-3.8.0-py3-none-any.whl", hash = "sha256:617eb4e5eedc82fc5f47b6d61e4d11cb837c56cb4544e39081099fa17ad109d4"}, {file = "filelock-3.8.0.tar.gz", hash = "sha256:55447caa666f2198c5b6b13a26d2084d26fa5b115c00d065664b2124680c4edc"}, ] +fiona = [ + {file = "Fiona-1.9.1-cp310-cp310-macosx_10_15_x86_64.whl", hash = "sha256:902b67b2d012c5797b5d7d3cb3b46dcf9a342cf90a7f7e53fb12c83738d19926"}, + {file = "Fiona-1.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e2f4535ae2c8446e6b328745a44567478d5a077ed63c888b8c212dddb1e11925"}, + {file = "Fiona-1.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c3d7f3286fb59b93cefefb89014b6fa8413126e180e15c576db859ba936cf334"}, + {file = "Fiona-1.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:692fe64c0f3a39742d6f7a8e420a8387f6aec3b6818b727d2dfc98a0c40e992d"}, + {file = "Fiona-1.9.1-cp311-cp311-macosx_10_15_x86_64.whl", hash = "sha256:a017a39650df0cc541c57cf7de450bb4cee6fd9760eb716323b594c1074634a2"}, + {file = "Fiona-1.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c3b52d49bc379fdcfd1250b38e7e00ab24ee14eb765376c793bbe251ffd09d6a"}, + {file = "Fiona-1.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5dbb0ae851cd4417104c469335a01f938251a8639317f93d422c5c808150bd27"}, + {file = "Fiona-1.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:4a6d8fcbbdafa8af8ac1904628b0267382ed9f9921933d061d7bfc5d3f3daf99"}, + {file = "Fiona-1.9.1-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:74f056a84dc52a0b21a2cf024601a69105596f06f28d40b45049948be17b4df2"}, + {file = "Fiona-1.9.1-cp37-cp37m-manylinux2014_x86_64.whl", hash = "sha256:5b9f3f6c782bb4ae2c924eefd373cabdeaaa99f86477b9c7c71eb20c052ee7c5"}, + {file = "Fiona-1.9.1-cp37-cp37m-win_amd64.whl", hash = "sha256:5d6183189a7e05e2498d38a1df3ab07e1353fa48e977cbc3a31203927bd06bca"}, + {file = "Fiona-1.9.1-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:5f2c14beec98a330aee1fd81fa0447a6aa1d5e0a75d000c0052dbe1f23dd6cfd"}, + {file = "Fiona-1.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:585a47ec21f2d198abc112158eaf12a6587a272beb7f001162d8c3b262676666"}, + {file = "Fiona-1.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd4368b4054f21518a19dea54ce9ac445c40418c6331c0c99d1531c3ddff05da"}, + {file = "Fiona-1.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:839ed0db23198bb754f0d655d4eeaf5f9c141bef734557e77e95e4dc83e42e7f"}, + {file = "Fiona-1.9.1-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:decca3956032ae2d2c19d2f7fa8a4553c43a6e66eb5abe9a05f6ddadcb1bfe5c"}, + {file = "Fiona-1.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cb827fa0030d03d8080723137c74b865ec18dbade87c02ed60215491a315c6be"}, + {file = "Fiona-1.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7e0f36484757baa8cd1c0602941e029ff992282776f9afae4c5b90f501ff005"}, + {file = "Fiona-1.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:f98933b552adf0506799097934a6950de412288e7a50466144d04874d6f63fbc"}, + {file = "Fiona-1.9.1.tar.gz", hash = "sha256:3a3725e94840a387fef48726d60db6a6791563f366939d22378a4661f8941be7"}, +] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, {file = "flake8-4.0.1.tar.gz", hash = "sha256:806e034dda44114815e23c16ef92f95c91e4c71100ff52813adf7132a6ad870d"}, @@ -5463,6 +5596,10 @@ geoalchemy2 = [ {file = "GeoAlchemy2-0.12.5-py2.py3-none-any.whl", hash = "sha256:3a59eb651df95b3dfee8e1d82f4d18c80b75f712860a0a3080defc6b0435070d"}, {file = "GeoAlchemy2-0.12.5.tar.gz", hash = "sha256:31c2502dce317b57b335e4eb87562d501fa39e46c728be514d9b86091e08dd67"}, ] +geopandas = [ + {file = "geopandas-0.12.2-py3-none-any.whl", hash = "sha256:0a470e4bf6f5367e6fd83ab6b40405e0b805c8174665bbcb7c4077ed90202912"}, + {file = "geopandas-0.12.2.tar.gz", hash = "sha256:0acdacddefa176525e4da6d9aeeece225da26055c4becdc6e97cf40fa97c27f4"}, +] gevent = [ {file = "gevent-22.10.1-cp27-cp27m-win32.whl", hash = "sha256:702a51b8f21bad1976b0893f90ade466e8c27039b846b611ad2beb8c6e6ac701"}, {file = "gevent-22.10.1-cp27-cp27m-win_amd64.whl", hash = "sha256:af7baec79a5f8ad1cc132d3b14edd12661c628d8094e501b089b1fe2d3df7f6e"}, @@ -6393,7 +6530,8 @@ nest-asyncio = [ {file = "nest_asyncio-1.5.6.tar.gz", hash = "sha256:d267cc1ff794403f7df692964d1d2a3fa9418ffea2a3f6859a439ff482fef290"}, ] networkx = [ - {file = "networkx-2.3.zip", hash = "sha256:8311ddef63cf5c5c5e7c1d0212dd141d9a1fe3f474915281b73597ed5f1d4e3d"}, + {file = "networkx-2.8.8-py3-none-any.whl", hash = "sha256:e435dfa75b1d7195c7b8378c3859f0445cd88c6b0375c181ed66823a9ceb7524"}, + {file = "networkx-2.8.8.tar.gz", hash = "sha256:230d388117af870fce5647a3c52401fcf753e94720e6ea6b4197a5355648885e"}, ] nodeenv = [ {file = "nodeenv-1.7.0-py2.py3-none-any.whl", hash = "sha256:27083a7b96a25f2f5e1d8cb4b6317ee8aeda3bdd121394e5ac54e498028a042e"}, @@ -6521,6 +6659,10 @@ osmium = [ {file = "osmium-3.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:e45b7c54ac756e9cb40e2ba68691df635804eb6aa2023088af66936a9c8e3782"}, {file = "osmium-3.4.1.tar.gz", hash = "sha256:575dad72ab169cf585b9aeefb4f5f99ac250bf7da1986992afcbf169dc70c381"}, ] +osmnx = [ + {file = "osmnx-1.2.2-py2.py3-none-any.whl", hash = "sha256:94f2a3929e857d8c0da39ae552c6da3b1a3f4bcfea6de108696bda5ee3a7689d"}, + {file = "osmnx-1.2.2.tar.gz", hash = "sha256:30924452ca02758ece3301f9fcfb1b80edf31e2be7abe7fa7e0fefddb5050408"}, +] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, @@ -7362,6 +7504,53 @@ requests-toolbelt = [ reverse-geocoder = [ {file = "reverse_geocoder-1.5.1.tar.gz", hash = "sha256:2a2e781b5f69376d922b78fe8978f1350c84fce0ddb07e02c834ecf98b57c75c"}, ] +rtree = [ + {file = "Rtree-1.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9855b8f11cdad99c56eb361b7b632a4fbd3d8cbe3f2081426b445f0cfb7fdca9"}, + {file = "Rtree-1.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:18ce7e4d04b85c48f2d364835620b3b20e38e199639746e7b12f07a2303e18ff"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:784efa6b7be9e99b33613ae8495931032689441eabb6120c9b3eb91188c33794"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:157207191aebdacbbdbb369e698cfbfebce53bc97114e96c8af5bed3126475f1"}, + {file = "Rtree-1.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c5fb3671a8d440c24b1dd29ec621d4345ced7185e26f02abe98e85a6629fcb50"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:11d16f51cf9205cd6995af36e24efe8f184270f667fb49bb69b09fc46b97e7d4"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6db6a0a93e41594ffc14b053f386dd414ab5a82535bbd9aedafa6ac8dc0650d8"}, + {file = "Rtree-1.0.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c6e29e5eb3083ad12ac5c1ce6e37465ea3428d894d3466cc9c9e2ee4bf768e53"}, + {file = "Rtree-1.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:656b148589c0b5bab4a7db4d033634329f42a5feaac10ca40aceeca109d83c1f"}, + {file = "Rtree-1.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7b2c15f9373ba314c83a8df5cb6d99b4e3af23c376c6b1317add995432dd0970"}, + {file = "Rtree-1.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93c5e0bf31e76b4f92a6eec3d2891e938408774c75a8ed6ac3d2c8db04a2be33"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6792de0e3c2fd3ad7e069445027603bec7a47000432f49c80246886311f4f152"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:004e131b570dc360a49e7f3b60e7bc6517943a54df056587964d1cb903889e7e"}, + {file = "Rtree-1.0.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:becd711fe97c2e09b1b7969e83080a3c8012bce2d30f6db879aade255fcba5c1"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:015df09e1bc55ddf7c88799bf1515d058cd0ee78eacf4cd443a32876d3b3a863"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c2973b76f61669a85e160b4ad09879c4089fc0e3f20fd99adf161ca298fe8374"}, + {file = "Rtree-1.0.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e4335e131a58952635560a003458011d97f9ea6f3c010dc24906050b42ee2c03"}, + {file = "Rtree-1.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:e7ca5d743f6a1dc62653dfac8ee7ce2e1ba91be7cf97916a7f60b7cbe48fb48d"}, + {file = "Rtree-1.0.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2ee7165e9872a026ccb868c021711eba39cedf7d1820763c9de52d5324691a92"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8de99f28af0f1783eefb80918959903b4b18112f6a12b48f296ecb162804e69d"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1a94e2f4bf74bd202ea8b67ea3d7c71e763ad41f79be1d6b72aa2c8d5a8e92c4"}, + {file = "Rtree-1.0.1-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f5120da3a1b96f3a7a17dd6af0afdd4e6f3cc9baa87e9ee0a272882f01f980bb"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:7e3d5f0e7b28250afbb290ab88b49aa0f121c9714d0da2080581783690347507"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:296203e933b6ec0dd07f6a7456c4f1492def95b6993f20cc61c92b0fee0aecc5"}, + {file = "Rtree-1.0.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:77908cd7acdd519a731979ebf5baff8afd102109c2f52864c1e6ee75d3ea2d87"}, + {file = "Rtree-1.0.1-cp37-cp37m-win_amd64.whl", hash = "sha256:1a213e5d385278ca7668bc5b27083f8d6e39996a9bd59b6528f3a30009dae4ed"}, + {file = "Rtree-1.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cfa8cffec5cb9fed494c4bb335ebdb69b3c26178b0b685f67f79296c6b3d800c"}, + {file = "Rtree-1.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b31fd22d214160859d038da7cb2aaa27acb71efc24a7bcc75c84b5e502721549"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d68a81ad419d5c2ea5fecc677e6c178666c057e2c7b24100a6c48392196f1e9"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62f38020af47b765adc6b0bc7c4e810c6c3d1eab44ba339b592ff25a4c0dc0a7"}, + {file = "Rtree-1.0.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:50b658a6707f215a0056d52e9f83a97148c0af62dea07cf29b3789a2c429e78a"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:3573cbb0de872f54d0a0c29596a84e8ac3939c47ca3bece4a82e92775730a0d0"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d5abe5a19d943a88bea14901970e4c53e4579fc2662404cdea6163bf4c04d49a"}, + {file = "Rtree-1.0.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:1e894112cef4de6c518bdea0b43eada65f12888c3645cc437c3a677aa023039f"}, + {file = "Rtree-1.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:582854252b8fd5c8472478af060635434931fb55edd269bac128cbf2eef43620"}, + {file = "Rtree-1.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b54057e8a8ad92c1d8e9eaa5cf32aad70dde454abbf9b638e9d6024520a52c02"}, + {file = "Rtree-1.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:698de8ce6c62e159d93b35bacf64bcf3619077b5367bc88cd2cff5e0bc36169b"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:273ee61783de3a1664e5f868feebf5eea4629447137751bfa4087b0f82093082"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16900ee02cf5c198a42b03635268a80f606aa102f3f7618b89f75023d406da1c"}, + {file = "Rtree-1.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6ce4a6fdb63254a4c1efebe7a4f7a59b1c333c703bde4ae715d9ad88c833e10b"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5b20f69e040a05503b22297af223f336fe7047909b57e4b207b98292f33a229f"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:57128293dd625cb1f07726f32208097953e8854d70ab1fc55d6858733618b9ed"}, + {file = "Rtree-1.0.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e898d7409ab645c25e06d4e058f99271182601d70b2887aba3351bf08e09a0c6"}, + {file = "Rtree-1.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ad9912faeddb1ddcec5e26b33089166d58a107af6862d8b7f1bb2b7c0002ab39"}, + {file = "Rtree-1.0.1.tar.gz", hash = "sha256:222121699c303a64065d849bf7038b1ecabc37b65c7fa340bedb38ef0e805429"}, +] s2sphere = [ {file = "s2sphere-0.2.5-py2.py3-none-any.whl", hash = "sha256:d2340c9cf458ddc9a89afd1d8048a4195ce6fa6b0095ab900d4be5271e537401"}, {file = "s2sphere-0.2.5.tar.gz", hash = "sha256:c2478c1ff7c601a59a7151a57b605435897514578fa6bdb8730721c182adbbaf"}, @@ -7539,6 +7728,50 @@ setuptools-scm = [ {file = "setuptools_scm-7.0.5-py3-none-any.whl", hash = "sha256:7930f720905e03ccd1e1d821db521bff7ec2ac9cf0ceb6552dd73d24a45d3b02"}, {file = "setuptools_scm-7.0.5.tar.gz", hash = "sha256:031e13af771d6f892b941adb6ea04545bbf91ebc5ce68c78aaf3fff6e1fb4844"}, ] +shapely = [ + {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d048f93e42ba578b82758c15d8ae037d08e69d91d9872bca5a1895b118f4e2b0"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:99ab0ddc05e44acabdbe657c599fdb9b2d82e86c5493bdae216c0c4018a82dee"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:99a2f0da0109e81e0c101a2b4cd8412f73f5f299e7b5b2deaf64cd2a100ac118"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:6fe855e7d45685926b6ba00aaeb5eba5862611f7465775dacd527e081a8ced6d"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:ec14ceca36f67cb48b34d02d7f65a9acae15cd72b48e303531893ba4a960f3ea"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8a2b2a65fa7f97115c1cd989fe9d6f39281ca2a8a014f1d4904c1a6e34d7f25"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-win32.whl", hash = "sha256:21776184516a16bf82a0c3d6d6a312b3cd15a4cabafc61ee01cf2714a82e8396"}, + {file = "Shapely-1.8.5.post1-cp310-cp310-win_amd64.whl", hash = "sha256:a354199219c8d836f280b88f2c5102c81bb044ccea45bd361dc38a79f3873714"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:783bad5f48e2708a0e2f695a34ed382e4162c795cb2f0368b39528ac1d6db7ed"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a23ef3882d6aa203dd3623a3d55d698f59bfbd9f8a3bfed52c2da05a7f0f8640"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ab38f7b5196ace05725e407cb8cab9ff66edb8e6f7bb36a398e8f73f52a7aaa2"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8d086591f744be483b34628b391d741e46f2645fe37594319e0a673cc2c26bcf"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4728666fff8cccc65a07448cae72c75a8773fea061c3f4f139c44adc429b18c3"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-win32.whl", hash = "sha256:84010db15eb364a52b74ea8804ef92a6a930dfc1981d17a369444b6ddec66efd"}, + {file = "Shapely-1.8.5.post1-cp311-cp311-win_amd64.whl", hash = "sha256:48dcfffb9e225c0481120f4bdf622131c8c95f342b00b158cdbe220edbbe20b6"}, + {file = "Shapely-1.8.5.post1-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:2fd15397638df291c427a53d641d3e6fd60458128029c8c4f487190473a69a91"}, + {file = "Shapely-1.8.5.post1-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:a74631e511153366c6dbe3229fa93f877e3c87ea8369cd00f1d38c76b0ed9ace"}, + {file = "Shapely-1.8.5.post1-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:66bdac74fbd1d3458fa787191a90fa0ae610f09e2a5ec398c36f968cc0ed743f"}, + {file = "Shapely-1.8.5.post1-cp36-cp36m-win32.whl", hash = "sha256:6d388c0c1bd878ed1af4583695690aa52234b02ed35f93a1c8486ff52a555838"}, + {file = "Shapely-1.8.5.post1-cp36-cp36m-win_amd64.whl", hash = "sha256:be9423d5a3577ac2e92c7e758bd8a2b205f5e51a012177a590bc46fc51eb4834"}, + {file = "Shapely-1.8.5.post1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:5d7f85c2d35d39ff53c9216bc76b7641c52326f7e09aaad1789a3611a0f812f2"}, + {file = "Shapely-1.8.5.post1-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:adcf8a11b98af9375e32bff91de184f33a68dc48b9cb9becad4f132fa25cfa3c"}, + {file = "Shapely-1.8.5.post1-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:753ed0e21ab108bd4282405b9b659f2e985e8502b1a72b978eaa51d3496dee19"}, + {file = "Shapely-1.8.5.post1-cp37-cp37m-win32.whl", hash = "sha256:65b21243d8f6bcd421210daf1fabb9de84de2c04353c5b026173b88d17c1a581"}, + {file = "Shapely-1.8.5.post1-cp37-cp37m-win_amd64.whl", hash = "sha256:370b574c78dc5af3a198a6da5d9b3d7c04654bd2ef7e80e80a3a0992dfb2d9cd"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:532a55ee2a6c52d23d6f7d1567c8f0473635f3b270262c44e1b0c88096827e22"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:3480657460e939f45a7d359ef0e172a081f249312557fe9aa78c4fd3a362d993"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b65f5d530ba91e49ffc7c589255e878d2506a8b96ffce69d3b7c4500a9a9eaf8"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:147066da0be41b147a61f8eb805dea3b13709dbc873a431ccd7306e24d712bc0"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c2822111ddc5bcfb116e6c663e403579d0fe3f147d2a97426011a191c43a7458"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4b47bb6f9369e8bf3e6dbd33e6a25a47ee02b2874792a529fe04a49bf8bc0df6"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-win32.whl", hash = "sha256:2e0a8c2e55f1be1312b51c92b06462ea89e6bb703fab4b114e7a846d941cfc40"}, + {file = "Shapely-1.8.5.post1-cp38-cp38-win_amd64.whl", hash = "sha256:0d885cb0cf670c1c834df3f371de8726efdf711f18e2a75da5cfa82843a7ab65"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0b4ee3132ee90f07d63db3aea316c4c065ed7a26231458dda0874414a09d6ba3"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:02dd5d7dc6e46515d88874134dc8fcdc65826bca93c3eecee59d1910c42c1b17"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c6a9a4a31cd6e86d0fbe8473ceed83d4fe760b19d949fb557ef668defafea0f6"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.whl", hash = "sha256:38f0fbbcb8ca20c16451c966c1f527cc43968e121c8a048af19ed3e339a921cd"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:78fb9d929b8ee15cfd424b6c10879ce1907f24e05fb83310fc47d2cd27088e40"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:89164e7a9776a19e29f01369a98529321994e2e4d852b92b7e01d4d9804c55bf"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-win32.whl", hash = "sha256:8e59817b0fe63d34baedaabba8c393c0090f061917d18fc0bcc2f621937a8f73"}, + {file = "Shapely-1.8.5.post1-cp39-cp39-win_amd64.whl", hash = "sha256:e9c30b311de2513555ab02464ebb76115d242842b29c412f5a9aa0cac57be9f6"}, + {file = "Shapely-1.8.5.post1.tar.gz", hash = "sha256:ef3be705c3eac282a28058e6c6e5503419b250f482320df2172abcbea642c831"}, +] shellingham = [ {file = "shellingham-1.5.0-py2.py3-none-any.whl", hash = "sha256:a8f02ba61b69baaa13facdba62908ca8690a94b8119b69f5ec5873ea85f7391b"}, {file = "shellingham-1.5.0.tar.gz", hash = "sha256:72fb7f5c63103ca2cb91b23dee0c71fe8ad6fbfd46418ef17dbe40db51592dad"}, diff --git a/pyproject.toml b/pyproject.toml index ed3a821e29..6b4b0bb5fa 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -145,7 +145,7 @@ jupyterlab = "^3.4.4" jupyterlab-vim = "^0.15.1" Markdown = "^3.4.1" msgpack-python = "^0.5.6" -networkx = "~2.3" +networkx = "~2.8" nvidia-ml-py3 = "^7.352.0" onnx2torch = "^1.5.4" onnxoptimizer = "^0.3.1" @@ -172,6 +172,7 @@ triton = "^1.1.1" Werkzeug = "^2.1.2" zerorpc = { git = "https://github.com/commaai/zerorpc-python.git", branch = "master" } omegaconf = "^2.3.0" +osmnx = "==1.2.2" [build-system] From e49748d571d06a65a4361dde1f2f63c7294da13a Mon Sep 17 00:00:00 2001 From: Vivek Aithal Date: Tue, 14 Feb 2023 16:20:28 -0800 Subject: [PATCH 28/63] Chevrolet Bolt: Non-linear torque tune (#27344) * add non linear tune * update refs * rerun tests --- selfdrive/car/gm/interface.py | 44 ++++++++++++++++++++- selfdrive/car/interfaces.py | 4 +- selfdrive/controls/lib/latcontrol_torque.py | 4 +- selfdrive/test/process_replay/ref_commit | 2 +- 4 files changed, 47 insertions(+), 7 deletions(-) diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 8bfc067b48..9a165cf067 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -1,12 +1,15 @@ #!/usr/bin/env python3 +import numpy as np from cereal import car from math import fabs from panda import Panda +from common.numpy_fast import interp from common.conversions import Conversions as CV from selfdrive.car import STD_CARGO_KG, create_button_event, scale_tire_stiffness, get_safety_config from selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR -from selfdrive.car.interfaces import CarInterfaceBase +from selfdrive.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD +from selfdrive.controls.lib.drive_helpers import apply_center_deadzone ButtonType = car.CarState.ButtonEvent.Type EventName = car.CarEvent.EventName @@ -43,6 +46,43 @@ class CarInterface(CarInterfaceBase): else: return CarInterfaceBase.get_steer_feedforward_default + @staticmethod + def torque_from_lateral_accel_bolt(lateral_accel_value, torque_params, lateral_accel_error, lateral_accel_deadzone, vego, friction_compensation): + friction_interp = interp( + apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone), + [-FRICTION_THRESHOLD, FRICTION_THRESHOLD], + [-torque_params.friction, torque_params.friction] + ) + friction = friction_interp if friction_compensation else 0.0 + steer_torque = lateral_accel_value / torque_params.latAccelFactor + + # TODO: + # 1. Learn the correction factors from data + # 2. Generalize the logic to other GM torque control platforms + steer_break_pts = np.array([-1.0, -0.9, -0.75, -0.5, 0.0, 0.5, 0.75, 0.9, 1.0]) + steer_lataccel_factors = np.array([1.5, 1.15, 1.02, 1.0, 1.0, 1.0, 1.02, 1.15, 1.5]) + steer_correction_factor = np.interp( + steer_torque, + steer_break_pts, + steer_lataccel_factors + ) + + vego_break_pts = np.array([0.0, 10.0, 15.0, 20.0, 100.0]) + vego_lataccel_factors = np.array([1.5, 1.5, 1.25, 1.0, 1.0]) + vego_correction_factor = np.interp( + vego, + vego_break_pts, + vego_lataccel_factors, + ) + + return float((steer_torque + friction) / (steer_correction_factor * vego_correction_factor)) + + def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType: + if self.CP.carFingerprint == CAR.BOLT_EUV: + return self.torque_from_lateral_accel_bolt + else: + return self.torque_from_lateral_accel_linear + @staticmethod def _get_params(ret, candidate, fingerprint, car_fw, experimental_long): ret.carName = "gm" @@ -176,7 +216,7 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 16.8 ret.centerToFront = 2.15 # measured tire_stiffness_factor = 1.0 - ret.steerActuatorDelay = 0.2 + ret.steerActuatorDelay = 0.12 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) elif candidate == CAR.SILVERADO: diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 249818369c..f1e2081d05 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -18,7 +18,7 @@ from selfdrive.controls.lib.vehicle_model import VehicleModel ButtonType = car.CarState.ButtonEvent.Type GearShifter = car.CarState.GearShifter EventName = car.CarEvent.EventName -TorqueFromLateralAccelCallbackType = Callable[[float, car.CarParams.LateralTorqueTuning, float, float, bool], float] +TorqueFromLateralAccelCallbackType = Callable[[float, car.CarParams.LateralTorqueTuning, float, float, float, bool], float] MAX_CTRL_SPEED = (V_CRUISE_MAX + 4) * CV.KPH_TO_MS ACCEL_MAX = 2.0 @@ -131,7 +131,7 @@ class CarInterfaceBase(ABC): return self.get_steer_feedforward_default @staticmethod - def torque_from_lateral_accel_linear(lateral_accel_value, torque_params, lateral_accel_error, lateral_accel_deadzone, friction_compensation): + def torque_from_lateral_accel_linear(lateral_accel_value, torque_params, lateral_accel_error, lateral_accel_deadzone, vego, friction_compensation): # The default is a linear relationship between torque and lateral acceleration (accounting for road roll and steering friction) friction_interp = interp( apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone), diff --git a/selfdrive/controls/lib/latcontrol_torque.py b/selfdrive/controls/lib/latcontrol_torque.py index 2f56094379..9129693e5a 100644 --- a/selfdrive/controls/lib/latcontrol_torque.py +++ b/selfdrive/controls/lib/latcontrol_torque.py @@ -64,10 +64,10 @@ class LatControlTorque(LatControl): error = setpoint - measurement gravity_adjusted_lateral_accel = desired_lateral_accel - params.roll * ACCELERATION_DUE_TO_GRAVITY pid_log.error = self.torque_from_lateral_accel(error, self.torque_params, error, - lateral_accel_deadzone, friction_compensation=False) + lateral_accel_deadzone, CS.vEgo, friction_compensation=False) ff = self.torque_from_lateral_accel(gravity_adjusted_lateral_accel, self.torque_params, desired_lateral_accel - actual_lateral_accel, - lateral_accel_deadzone, friction_compensation=True) + lateral_accel_deadzone, CS.vEgo, friction_compensation=True) freeze_integrator = steer_limited or CS.steeringPressed or CS.vEgo < 5 output_torque = self.pid.update(pid_log.error, diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 85c7d8e80b..ed1875dcbe 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -f4efbb65a7eb9a8f4e23492372e707674f80114e \ No newline at end of file +3e53ce81f1ce26409fdc4479e650ef5626130876 \ No newline at end of file From f29e19cf4238199eec142f9c7eab5936874e04de Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 14 Feb 2023 16:59:20 -0800 Subject: [PATCH 29/63] FPv2: log responses from data collection queries (#27345) * log responses from logging/debugging queries * don't add logging FW to FW dict for fingerprinting * flip? * fine before * log if extra in debug ecus * clean up * test extra ecus too * Revert "test extra ecus too" This reverts commit 8f7867844db95f48631348551551148bf504e37b. * bump to master --- cereal | 2 +- selfdrive/car/fw_query_definitions.py | 2 ++ selfdrive/car/fw_versions.py | 17 +++++++++++------ selfdrive/car/honda/values.py | 2 ++ 4 files changed, 16 insertions(+), 7 deletions(-) diff --git a/cereal b/cereal index fa3e77b7c8..162a26ca2d 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit fa3e77b7c8eee8752f19427b34adcb1ae5c70ec5 +Subproject commit 162a26ca2d7e5bc9a42bb5ea11e98194f722027b diff --git a/selfdrive/car/fw_query_definitions.py b/selfdrive/car/fw_query_definitions.py index a1695733fa..2ee0e9b4c6 100755 --- a/selfdrive/car/fw_query_definitions.py +++ b/selfdrive/car/fw_query_definitions.py @@ -57,6 +57,8 @@ class Request: whitelist_ecus: List[int] = field(default_factory=list) rx_offset: int = 0x8 bus: int = 1 + # FW responses from these queries will not be used for fingerprinting + logging: bool = False @dataclass diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 0db260abbd..8bf4b74e0f 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -29,10 +29,9 @@ def chunks(l, n=128): def build_fw_dict(fw_versions, filter_brand=None): fw_versions_dict = defaultdict(set) for fw in fw_versions: - if filter_brand is None or fw.brand == filter_brand: - addr = fw.address + if (filter_brand is None or fw.brand == filter_brand) and not fw.logging: sub_addr = fw.subAddress if fw.subAddress != 0 else None - fw_versions_dict[(addr, sub_addr)].add(fw.fwVersion) + fw_versions_dict[(fw.address, sub_addr)].add(fw.fwVersion) return dict(fw_versions_dict) @@ -232,15 +231,19 @@ def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, # ECUs using a subaddress need be queried one by one, the rest can be done in parallel addrs = [] parallel_addrs = [] + logging_addrs = [] ecu_types = {} for brand, brand_versions in versions.items(): - for c in brand_versions.values(): - for ecu_type, addr, sub_addr in c.keys(): + for candidate, ecu in brand_versions.items(): + for ecu_type, addr, sub_addr in ecu.keys(): a = (brand, addr, sub_addr) if a not in ecu_types: ecu_types[a] = ecu_type + if a not in logging_addrs and candidate == "debug": + logging_addrs.append(a) + if sub_addr is None: if a not in parallel_addrs: parallel_addrs.append(a) @@ -269,13 +272,15 @@ def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, for (tx_addr, sub_addr), version in query.get_data(timeout).items(): f = car.CarParams.CarFw.new_message() - f.ecu = ecu_types.get((brand, tx_addr, sub_addr), Ecu.unknown) + ecu_key = (brand, tx_addr, sub_addr) + f.ecu = ecu_types.get(ecu_key, Ecu.unknown) f.fwVersion = version f.address = tx_addr f.responseAddress = uds.get_rx_addr_for_tx_addr(tx_addr, r.rx_offset) f.request = r.request f.brand = brand f.bus = r.bus + f.logging = r.logging or ecu_key in logging_addrs if sub_addr is not None: f.subAddress = sub_addr diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 3d1c006aaa..a4ddd84ead 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -171,12 +171,14 @@ FW_QUERY_CONFIG = FwQueryConfig( [HONDA_VERSION_REQUEST], [HONDA_VERSION_RESPONSE], bus=1, + logging=True ), # Query Nidec PT bus from camera for data collection Request( [StdQueries.UDS_VERSION_REQUEST], [StdQueries.UDS_VERSION_RESPONSE], bus=0, + logging=True ), ], extra_ecus=[ From c4b84783a003479bc105e2f7a93d5e71c2e1c38f Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 14 Feb 2023 17:55:41 -0800 Subject: [PATCH 30/63] Honda Bosch: gather available ECUs from camera (#27180) * add flag * actually use in fw_versions.py * simpler * not here * Comment * better name * add param and block * keys keys * block * with a value with a value * add query for bosch PT bus * different name * fix * . * fix test fix test * add cloulogs * mark as logging --- common/params.cc | 1 + selfdrive/boardd/boardd.cc | 2 ++ selfdrive/car/car_helpers.py | 1 - selfdrive/car/fw_query_definitions.py | 2 ++ selfdrive/car/fw_versions.py | 22 ++++++++++++++++++++-- selfdrive/car/honda/values.py | 14 +++++++++++--- selfdrive/controls/tests/test_startup.py | 1 + 7 files changed, 37 insertions(+), 6 deletions(-) diff --git a/common/params.cc b/common/params.cc index db5e5e700d..5e3361a70f 100644 --- a/common/params.cc +++ b/common/params.cc @@ -155,6 +155,7 @@ std::unordered_map keys = { {"NavSettingTime24h", PERSISTENT}, {"NavSettingLeftSide", PERSISTENT}, {"NavdRender", PERSISTENT}, + {"ObdMultiplexingDisabled", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_ON}, {"OpenpilotEnabledToggle", PERSISTENT}, {"PandaHeartbeatLost", CLEAR_ON_MANAGER_START | CLEAR_ON_IGNITION_OFF}, {"PandaSignatures", CLEAR_ON_MANAGER_START}, diff --git a/selfdrive/boardd/boardd.cc b/selfdrive/boardd/boardd.cc index 0473d3488c..5d885c2c79 100644 --- a/selfdrive/boardd/boardd.cc +++ b/selfdrive/boardd/boardd.cc @@ -137,6 +137,8 @@ bool safety_setter_thread(std::vector pandas) { panda->set_safety_model(cereal::CarParams::SafetyModel::ELM327, 1U); } + p.putBool("ObdMultiplexingDisabled", true); + std::string params; LOGW("waiting for params to set safety model"); while (true) { diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index 4ccce979d3..ae19fd6248 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -116,7 +116,6 @@ def fingerprint(logcan, sendcan, num_pandas): params = Params() params.put("CarVin", vin) - params.put_bool("FirmwareObdQueryDone", True) finger = gen_empty_fingerprint() candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 diff --git a/selfdrive/car/fw_query_definitions.py b/selfdrive/car/fw_query_definitions.py index 2ee0e9b4c6..dd3b19f6de 100755 --- a/selfdrive/car/fw_query_definitions.py +++ b/selfdrive/car/fw_query_definitions.py @@ -59,6 +59,8 @@ class Request: bus: int = 1 # FW responses from these queries will not be used for fingerprinting logging: bool = False + # These requests are done once OBD multiplexing is disabled, after all others + non_obd: bool = False @dataclass diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 8bf4b74e0f..23b0fcc6d1 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -5,6 +5,7 @@ from tqdm import tqdm import panda.python.uds as uds from cereal import car +from common.params import Params from selfdrive.car.ecu_addrs import get_ecu_addrs from selfdrive.car.interfaces import get_interface_attr from selfdrive.car.fingerprints import FW_VERSIONS @@ -89,7 +90,7 @@ def match_fw_to_car_fuzzy(fw_versions_dict, log=True, exclude=None): return set() -def match_fw_to_car_exact(fw_versions_dict): +def match_fw_to_car_exact(fw_versions_dict) -> Set[str]: """Do an exact FW match. Returns all cars that match the given FW versions for a list of "essential" ECUs. If an ECU is not considered essential the FW version can be missing to get a fingerprint, but if it's present it @@ -202,6 +203,7 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pand all_car_fw = [] brand_matches = get_brand_ecu_matches(ecu_rx_addrs) + matched_brand: Optional[str] = None for brand in sorted(brand_matches, key=lambda b: len(brand_matches[b]), reverse=True): car_fw = get_fw_versions(logcan, sendcan, query_brand=brand, timeout=timeout, num_pandas=num_pandas, debug=debug, progress=progress) @@ -209,12 +211,25 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pand # Try to match using FW returned from this brand only matches = match_fw_to_car_exact(build_fw_dict(car_fw)) if len(matches) == 1: + matched_brand = brand break + # Do non-OBD queries for matched brand, or all if no match is found + params = Params() + params.put_bool("FirmwareObdQueryDone", True) + + cloudlog.warning("Waiting for OBD multiplexing to be disabled") + params.get_bool("ObdMultiplexingDisabled", block=True) + cloudlog.warning("OBD multiplexing disabled") + + for brand in FW_QUERY_CONFIGS.keys(): + if brand == matched_brand or matched_brand is None: + all_car_fw.extend(get_fw_versions(logcan, sendcan, query_brand=brand, timeout=timeout, num_pandas=num_pandas, obd_multiplexed=False, debug=debug, progress=progress)) + return all_car_fw -def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, num_pandas=1, debug=False, progress=False): +def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, num_pandas=1, obd_multiplexed=True, debug=False, progress=False): versions = VERSIONS.copy() # Each brand can define extra ECUs to query for data collection @@ -262,6 +277,9 @@ def get_fw_versions(logcan, sendcan, query_brand=None, extra=None, timeout=0.1, # Skip query if no panda available if r.bus > num_pandas * 4 - 1: continue + # Or if request is not designated for current multiplexing mode + elif r.non_obd == obd_multiplexed: + continue try: addrs = [(a, s) for (b, a, s) in addr_chunk if b in (brand, 'any') and diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index a4ddd84ead..c085c3fe80 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -171,14 +171,22 @@ FW_QUERY_CONFIG = FwQueryConfig( [HONDA_VERSION_REQUEST], [HONDA_VERSION_RESPONSE], bus=1, - logging=True + logging=True, ), - # Query Nidec PT bus from camera for data collection + # Nidec PT bus Request( [StdQueries.UDS_VERSION_REQUEST], [StdQueries.UDS_VERSION_RESPONSE], bus=0, - logging=True + logging=True, + ), + # Bosch PT bus + Request( + [StdQueries.UDS_VERSION_REQUEST], + [StdQueries.UDS_VERSION_RESPONSE], + bus=1, + logging=True, + non_obd=True, ), ], extra_ecus=[ diff --git a/selfdrive/controls/tests/test_startup.py b/selfdrive/controls/tests/test_startup.py index ba2d2f5c02..92fc2468bb 100755 --- a/selfdrive/controls/tests/test_startup.py +++ b/selfdrive/controls/tests/test_startup.py @@ -72,6 +72,7 @@ class TestStartup(unittest.TestCase): params.clear_all() params.put_bool("Passive", False) params.put_bool("OpenpilotEnabledToggle", True) + params.put_bool("ObdMultiplexingDisabled", True) # Build capnn version of FW array if fw_versions is not None: From 8c099dd4e5adf040f7f454714cf729725bee7f91 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 14 Feb 2023 22:06:23 -0800 Subject: [PATCH 31/63] GM: cleanup torque feedforward function (#27347) no numpy --- selfdrive/car/gm/interface.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 9a165cf067..104cb8fbd8 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -import numpy as np from cereal import car from math import fabs from panda import Panda @@ -59,23 +58,23 @@ class CarInterface(CarInterfaceBase): # TODO: # 1. Learn the correction factors from data # 2. Generalize the logic to other GM torque control platforms - steer_break_pts = np.array([-1.0, -0.9, -0.75, -0.5, 0.0, 0.5, 0.75, 0.9, 1.0]) - steer_lataccel_factors = np.array([1.5, 1.15, 1.02, 1.0, 1.0, 1.0, 1.02, 1.15, 1.5]) - steer_correction_factor = np.interp( + steer_break_pts = [-1.0, -0.9, -0.75, -0.5, 0.0, 0.5, 0.75, 0.9, 1.0] + steer_lataccel_factors = [1.5, 1.15, 1.02, 1.0, 1.0, 1.0, 1.02, 1.15, 1.5] + steer_correction_factor = interp( steer_torque, steer_break_pts, steer_lataccel_factors ) - vego_break_pts = np.array([0.0, 10.0, 15.0, 20.0, 100.0]) - vego_lataccel_factors = np.array([1.5, 1.5, 1.25, 1.0, 1.0]) - vego_correction_factor = np.interp( + vego_break_pts = [0.0, 10.0, 15.0, 20.0, 100.0] + vego_lataccel_factors = [1.5, 1.5, 1.25, 1.0, 1.0] + vego_correction_factor = interp( vego, vego_break_pts, vego_lataccel_factors, ) - return float((steer_torque + friction) / (steer_correction_factor * vego_correction_factor)) + return (steer_torque + friction) / (steer_correction_factor * vego_correction_factor) def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType: if self.CP.carFingerprint == CAR.BOLT_EUV: From d4c5b8d6f4ba7606f6823ce523c66a7e270b924b Mon Sep 17 00:00:00 2001 From: Rob Chouinard Date: Wed, 15 Feb 2023 01:24:13 -0500 Subject: [PATCH 32/63] Allow Honda Nidec vehicles with comma pedal to drive at max speed. (#26902) Without this Honda Nidec vehicles with the comma pedal will drive around 2 mph under the max speed. --- selfdrive/car/honda/interface.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 66c0ce4275..d3cf9fa891 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -21,6 +21,8 @@ class CarInterface(CarInterfaceBase): def get_pid_accel_limits(CP, current_speed, cruise_speed): if CP.carFingerprint in HONDA_BOSCH: return CarControllerParams.BOSCH_ACCEL_MIN, CarControllerParams.BOSCH_ACCEL_MAX + elif CP.enableGasInterceptor: + return CarControllerParams.NIDEC_ACCEL_MIN, CarControllerParams.NIDEC_ACCEL_MAX else: # NIDECs don't allow acceleration near cruise_speed, # so limit limits of pid to prevent windup From e4d0ee8716c382e90fd725998216a2f7deafc592 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Thu, 16 Feb 2023 02:59:57 +0800 Subject: [PATCH 33/63] cabana: cleanup code for charts (#27350) --- tools/cabana/chartswidget.cc | 123 ++++++++++++++--------------------- tools/cabana/chartswidget.h | 14 ++-- 2 files changed, 54 insertions(+), 83 deletions(-) diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index ec54d7f06a..3f12c55ffc 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -11,9 +11,11 @@ #include #include #include +#include #include #include +const int MAX_COLUMN_COUNT = 4; // ChartsWidget ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { @@ -23,14 +25,17 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QToolBar *toolbar = new QToolBar(tr("Charts"), this); toolbar->setIconSize({16, 16}); - QAction *new_plot_btn = toolbar->addAction(utils::icon("file-plus"), ""); - new_plot_btn->setToolTip(tr("New Plot")); + QAction *new_plot_btn = toolbar->addAction(utils::icon("file-plus"), tr("New Plot")); toolbar->addWidget(title_label = new QLabel()); title_label->setContentsMargins(0, 0, 12, 0); - columns_cb = new QComboBox(this); - columns_cb->addItems({"1", "2", "3", "4"}); - columns_lb_action = toolbar->addWidget(new QLabel(tr("Columns:"))); - columns_cb_action = toolbar->addWidget(columns_cb); + + QMenu *menu = new QMenu(this); + for (int i = 0; i < MAX_COLUMN_COUNT; ++i) { + menu->addAction(tr("%1").arg(i + 1), [=]() { setColumnCount(i + 1); }); + } + columns_action = toolbar->addAction(""); + columns_action->setMenu(menu); + qobject_cast(toolbar->widgetForAction(columns_action))->setPopupMode(QToolButton::InstantPopup); QLabel *stretch_label = new QLabel(this); stretch_label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred); @@ -44,13 +49,10 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { range_slider->setPageStep(60); // 1 min range_slider_action = toolbar->addWidget(range_slider); - reset_zoom_action = toolbar->addWidget(reset_zoom_btn = new QToolButton()); - reset_zoom_btn->setIcon(utils::icon("zoom-out")); - reset_zoom_btn->setToolTip(tr("Reset zoom")); - reset_zoom_btn->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + reset_zoom_action = toolbar->addAction(utils::icon("zoom-out"), tr("Reset Zoom")); + qobject_cast(toolbar->widgetForAction(reset_zoom_action))->setToolButtonStyle(Qt::ToolButtonTextBesideIcon); - remove_all_btn = toolbar->addAction(utils::icon("x"), ""); - remove_all_btn->setToolTip(tr("Remove all charts")); + remove_all_btn = toolbar->addAction(utils::icon("x"), tr("Remove all charts")); dock_btn = toolbar->addAction(""); main_layout->addWidget(toolbar); @@ -73,10 +75,9 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { // init settings use_dark_theme = QApplication::style()->standardPalette().color(QPalette::WindowText).value() > QApplication::style()->standardPalette().color(QPalette::Background).value(); - column_count = std::clamp(settings.chart_column_count, 1, columns_cb->count()); + column_count = std::clamp(settings.chart_column_count, 1, MAX_COLUMN_COUNT); max_chart_range = std::clamp(settings.chart_range, 1, settings.max_cached_minutes * 60); display_range = {0, max_chart_range}; - columns_cb->setCurrentIndex(column_count - 1); range_slider->setValue(max_chart_range); updateToolBar(); @@ -86,8 +87,7 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { QObject::connect(range_slider, &QSlider::valueChanged, this, &ChartsWidget::setMaxChartRange); QObject::connect(new_plot_btn, &QAction::triggered, this, &ChartsWidget::newChart); QObject::connect(remove_all_btn, &QAction::triggered, this, &ChartsWidget::removeAll); - QObject::connect(reset_zoom_btn, &QToolButton::clicked, this, &ChartsWidget::zoomReset); - QObject::connect(columns_cb, SIGNAL(activated(int)), SLOT(setColumnCount(int))); + QObject::connect(reset_zoom_action, &QAction::triggered, this, &ChartsWidget::zoomReset); QObject::connect(&settings, &Settings::changed, this, &ChartsWidget::settingChanged); QObject::connect(dock_btn, &QAction::triggered, [this]() { emit dock(!docking); @@ -162,11 +162,12 @@ void ChartsWidget::setMaxChartRange(int value) { void ChartsWidget::updateToolBar() { title_label->setText(tr("Charts: %1").arg(charts.size())); + columns_action->setText(tr("Column: %1").arg(column_count)); range_lb->setText(QString("Range: %1:%2 ").arg(max_chart_range / 60, 2, 10, QLatin1Char('0')).arg(max_chart_range % 60, 2, 10, QLatin1Char('0'))); range_lb_action->setVisible(!is_zoomed); range_slider_action->setVisible(!is_zoomed); reset_zoom_action->setVisible(is_zoomed); - reset_zoom_btn->setText(is_zoomed ? tr("Zoomin: %1-%2").arg(zoomed_range.first, 0, 'f', 1).arg(zoomed_range.second, 0, 'f', 1) : ""); + reset_zoom_action->setText(is_zoomed ? tr("Zoomin: %1-%2").arg(zoomed_range.first, 0, 'f', 1).arg(zoomed_range.second, 0, 'f', 1) : ""); remove_all_btn->setEnabled(!charts.isEmpty()); dock_btn->setIcon(utils::icon(docking ? "arrow-up-right-square" : "arrow-down-left-square")); dock_btn->setToolTip(docking ? tr("Undock charts") : tr("Dock charts")); @@ -211,29 +212,29 @@ void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bo chart->addSeries(id, sig); updateState(); } else if (!show && chart) { - chart->removeSeries(id, sig); + chart->removeIf([&](auto &s) { return s.msg_id == id && s.sig == sig; }); } updateToolBar(); setUpdatesEnabled(true); } void ChartsWidget::setColumnCount(int n) { - n = std::clamp(n + 1, 1, columns_cb->count()); + n = std::clamp(n, 1, MAX_COLUMN_COUNT); if (column_count != n) { column_count = settings.chart_column_count = n; + updateToolBar(); updateLayout(); } } void ChartsWidget::updateLayout() { - int n = columns_cb->count(); + int n = MAX_COLUMN_COUNT; for (; n > 1; --n) { if ((n * CHART_MIN_WIDTH + (n - 1) * charts_layout->spacing()) < charts_layout->geometry().width()) break; } bool show_column_cb = n > 1; - columns_lb_action->setVisible(show_column_cb); - columns_cb_action->setVisible(show_column_cb); + columns_action->setVisible(show_column_cb); n = std::min(column_count, n); if (charts.size() != charts_layout->count() || n != current_column_count) { @@ -305,7 +306,6 @@ bool ChartsWidget::eventFilter(QObject *obj, QEvent *event) { ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) { series_type = settings.chart_series_type == 0 ? QAbstractSeries::SeriesTypeLine : QAbstractSeries::SeriesTypeScatter; - QChart *chart = new QChart(); chart->setBackgroundVisible(false); axis_x = new QValueAxis(this); @@ -367,9 +367,6 @@ void ChartView::addSeries(const QString &msg_id, const Signal *sig) { if (hasSeries(msg_id, sig)) return; QXYSeries *series = createSeries(series_type, getColor(sig)); - chart()->addSeries(series); - series->attachAxis(axis_x); - series->attachAxis(axis_y); auto [source, address] = DBCManager::parseId(msg_id); sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series}); updateTitle(); @@ -378,30 +375,29 @@ void ChartView::addSeries(const QString &msg_id, const Signal *sig) { emit seriesAdded(msg_id, sig); } -void ChartView::removeSeries(const QString &msg_id, const Signal *sig) { - auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); - if (it != sigs.end()) { - it = removeItem(it); - } -} - bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const { return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); } -QList::iterator ChartView::removeItem(const QList::iterator &it) { - chart()->removeSeries(it->series); - it->series->deleteLater(); - QString msg_id = it->msg_id; - const Signal *sig = it->sig; - auto ret = sigs.erase(it); - emit seriesRemoved(msg_id, sig); - if (!sigs.isEmpty()) { +void ChartView::removeIf(std::function predicate) { + int prev_size = sigs.size(); + for (auto it = sigs.begin(); it != sigs.end(); /**/) { + if (predicate(*it)) { + chart()->removeSeries(it->series); + it->series->deleteLater(); + auto msg_id = it->msg_id; + auto sig = it->sig; + it = sigs.erase(it); + emit seriesRemoved(msg_id, sig); + } else { + ++it; + } + } + if (sigs.empty()) { + emit remove(); + } else if (sigs.size() != prev_size) { updateAxisY(); - } else { - emit remove(); } - return ret; } void ChartView::signalUpdated(const Signal *sig) { @@ -412,23 +408,11 @@ void ChartView::signalUpdated(const Signal *sig) { } } -void ChartView::signalRemoved(const Signal *sig) { - for (auto it = sigs.begin(); it != sigs.end(); /**/) { - it = (it->sig == sig) ? removeItem(it) : ++it; - } -} - void ChartView::msgUpdated(uint32_t address) { if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; })) updateTitle(); } -void ChartView::msgRemoved(uint32_t address) { - for (auto it = sigs.begin(); it != sigs.end(); /**/) { - it = (it->address == address) ? removeItem(it) : ++it; - } -} - void ChartView::manageSeries() { SeriesSelector dlg(tr("Mange Chart"), this); for (auto &s : sigs) { @@ -436,19 +420,12 @@ void ChartView::manageSeries() { } if (dlg.exec() == QDialog::Accepted) { auto items = dlg.seletedItems(); - if (items.isEmpty()) { - emit remove(); - } else { - for (auto s : items) { - addSeries(s->msg_id, s->sig); - } - for (auto it = sigs.begin(); it != sigs.end(); /**/) { - bool exists = std::any_of(items.cbegin(), items.cend(), [&](auto &s) { - return s->msg_id == it->msg_id && s->sig == it->sig; - }); - it = exists ? ++it : removeItem(it); - } + for (auto s : items) { + addSeries(s->msg_id, s->sig); } + removeIf([&](auto &s) { + return std::none_of(items.cbegin(), items.cend(), [&](auto &it) { return s.msg_id == it->msg_id && s.sig == it->sig; }); + }); } } @@ -503,7 +480,7 @@ void ChartView::updateSeriesPoints() { int pixels_per_point = width() / num_points; if (series_type == QAbstractSeries::SeriesTypeScatter) { - ((QScatterSeries *)s.series)->setMarkerSize(std::clamp(pixels_per_point / 3, 1, 8)); + ((QScatterSeries *)s.series)->setMarkerSize(std::clamp(pixels_per_point / 3, 2, 8)); } else { s.series->setPointsVisible(pixels_per_point > 20); } @@ -698,7 +675,7 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) { text_list.push_front(QString::number(chart()->mapToValue(pt).x(), 'f', 3)); QPointF tooltip_pt(pt.x() + 12, plot_area.top() - 20); QToolTip::showText(mapToGlobal(tooltip_pt.toPoint()), pt.isNull() ? "" : text_list.join("
"), this, plot_area.toRect()); - scene()->update(); + scene()->invalidate({}, QGraphicsScene::ForegroundLayer); } else { QToolTip::hideText(); } @@ -795,6 +772,9 @@ QXYSeries *ChartView::createSeries(QAbstractSeries::SeriesType type, QColor colo pen.setWidth(2.0 * qApp->devicePixelRatio()); series->setPen(pen); #endif + chart()->addSeries(series); + series->attachAxis(axis_x); + series->attachAxis(axis_y); return series; } @@ -809,9 +789,6 @@ void ChartView::setSeriesType(QAbstractSeries::SeriesType type) { } for (auto &s : sigs) { auto series = createSeries(series_type, getColor(s.sig)); - chart()->addSeries(series); - series->attachAxis(axis_x); - series->attachAxis(axis_y); series->replace(s.vals); s.series = series; } diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 25949dd654..58ae7e3b4c 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -1,6 +1,5 @@ #pragma once -#include #include #include #include @@ -8,7 +7,6 @@ #include #include #include -#include #include #include #include @@ -28,7 +26,6 @@ class ChartView : public QChartView { public: ChartView(QWidget *parent = nullptr); void addSeries(const QString &msg_id, const Signal *sig); - void removeSeries(const QString &msg_id, const Signal *sig); bool hasSeries(const QString &msg_id, const Signal *sig) const; void updateSeries(const Signal *sig = nullptr, const std::vector *events = nullptr, bool clear = true); void updatePlot(double cur, double min, double max); @@ -54,15 +51,14 @@ signals: void axisYLabelWidthChanged(int w); private slots: - void msgRemoved(uint32_t address); void msgUpdated(uint32_t address); void signalUpdated(const Signal *sig); - void signalRemoved(const Signal *sig); void manageSeries(); void handleMarkerClicked(); + void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.address == address; }); } + void signalRemoved(const Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: - QList::iterator removeItem(const QList::iterator &it); void mousePressEvent(QMouseEvent *event) override; void mouseReleaseEvent(QMouseEvent *event) override; void mouseMoveEvent(QMouseEvent *ev) override; @@ -78,6 +74,7 @@ private: qreal niceNumber(qreal x, bool ceiling); QXYSeries *createSeries(QAbstractSeries::SeriesType type, QColor color); void updateSeriesPoints(); + void removeIf(std::function predicate); int y_label_width = 0; int align_to = 0; @@ -139,7 +136,6 @@ private: bool docking = true; QAction *dock_btn; QAction *reset_zoom_action; - QToolButton *reset_zoom_btn; QAction *remove_all_btn; QGridLayout *charts_layout; QList charts; @@ -148,9 +144,7 @@ private: std::pair display_range; std::pair zoomed_range; bool use_dark_theme = false; - QAction *columns_lb_action; - QAction *columns_cb_action; - QComboBox *columns_cb; + QAction *columns_action; int column_count = 1; int current_column_count = 0; }; From 00513f10011ad6ad693fbbc9b4b5dc7df36f9a79 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 15 Feb 2023 11:28:47 -0800 Subject: [PATCH 34/63] locationd: adjust GPS alive check for QCOM GPS (#27339) * locationd: adjust GPS alive check for QCOM GPS * update refs * update refs --- selfdrive/locationd/locationd.cc | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/locationd/locationd.cc b/selfdrive/locationd/locationd.cc index 8941b50248..307626506a 100755 --- a/selfdrive/locationd/locationd.cc +++ b/selfdrive/locationd/locationd.cc @@ -619,7 +619,7 @@ kj::ArrayPtr Localizer::get_message_bytes(MessageBuilder& msg_build } bool Localizer::is_gps_ok() { - return (this->kf->get_filter_time() - this->last_gps_msg) < 1.0; + return (this->kf->get_filter_time() - this->last_gps_msg) < 2.0; } bool Localizer::critical_services_valid(std::map critical_services) { diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index ed1875dcbe..85eada072e 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -3e53ce81f1ce26409fdc4479e650ef5626130876 \ No newline at end of file +c7bb411b37ab7ff573402b6e4fa24f796cbb2ee8 \ No newline at end of file From 5078c918056c189a3ec84bc63231fbae75c57eda Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Wed, 15 Feb 2023 21:39:03 +0100 Subject: [PATCH 35/63] cabana: refactor message id from QString to struct (#27352) * cabana: refactor message id from QString to struct * fix tabbar * fix findsimilarbits * optimize hash function * cleanup sorting * use in updateLastMsgsTo --- tools/cabana/binaryview.cc | 12 +++--- tools/cabana/binaryview.h | 8 ++-- tools/cabana/chartswidget.cc | 27 +++++++------- tools/cabana/chartswidget.h | 28 +++++++------- tools/cabana/commands.cc | 18 ++++----- tools/cabana/commands.h | 20 +++++----- tools/cabana/dbcmanager.cc | 34 ++++++++--------- tools/cabana/dbcmanager.h | 44 ++++++++++++++++++---- tools/cabana/detailwidget.cc | 51 +++++++++++++++----------- tools/cabana/detailwidget.h | 9 +++-- tools/cabana/historylog.cc | 17 ++++----- tools/cabana/historylog.h | 8 ++-- tools/cabana/messageswidget.cc | 22 +++++------ tools/cabana/messageswidget.h | 14 ++++--- tools/cabana/signaledit.cc | 10 ++--- tools/cabana/signaledit.h | 12 +++--- tools/cabana/streams/abstractstream.cc | 19 +++++----- tools/cabana/streams/abstractstream.h | 17 +++++---- tools/cabana/tools/findsimilarbits.cc | 8 ++-- tools/cabana/tools/findsimilarbits.h | 4 +- 20 files changed, 209 insertions(+), 173 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 16df867d56..9085bf310a 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -94,7 +94,7 @@ void BinaryView::addShortcuts() { QObject::connect(shortcut_plot_c, &QShortcut::activated, shortcut_plot, &QShortcut::activated); QObject::connect(shortcut_plot, &QShortcut::activated, [=]{ if (hovered_sig != nullptr) { - emit showChart(model->msg_id, hovered_sig, true, false); + emit showChart(*model->msg_id, hovered_sig, true, false); } }); } @@ -189,14 +189,14 @@ void BinaryView::leaveEvent(QEvent *event) { QTableView::leaveEvent(event); } -void BinaryView::setMessage(const QString &message_id) { +void BinaryView::setMessage(const MessageId &message_id) { model->msg_id = message_id; verticalScrollBar()->setValue(0); refresh(); } void BinaryView::refresh() { - if (model->msg_id.isEmpty()) return; + if (!model->msg_id) return; clearSelection(); anchor_index = QModelIndex(); @@ -231,7 +231,7 @@ std::tuple BinaryView::getSelection(QModelIndex index) { void BinaryViewModel::refresh() { beginResetModel(); items.clear(); - if ((dbc_msg = dbc()->msg(msg_id))) { + if ((dbc_msg = dbc()->msg(*msg_id))) { row_count = dbc_msg->size; items.resize(row_count * column_count); for (auto sig : dbc_msg->getSignals()) { @@ -250,7 +250,7 @@ void BinaryViewModel::refresh() { } } } else { - row_count = can->lastMessage(msg_id).dat.size(); + row_count = can->lastMessage(*msg_id).dat.size(); items.resize(row_count * column_count); } endResetModel(); @@ -259,7 +259,7 @@ void BinaryViewModel::refresh() { void BinaryViewModel::updateState() { auto prev_items = items; - const auto &last_msg = can->lastMessage(msg_id); + const auto &last_msg = can->lastMessage(*msg_id); const auto &binary = last_msg.dat; // data size may changed. diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 7cf9a8081c..6743b6cfac 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -46,7 +48,7 @@ public: }; std::vector items; - QString msg_id; + std::optional msg_id; const DBCMsg *dbc_msg = nullptr; int row_count = 0; const int column_count = 9; @@ -57,7 +59,7 @@ class BinaryView : public QTableView { public: BinaryView(QWidget *parent = nullptr); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void highlight(const Signal *sig); QSet getOverlappingSignals() const; inline void updateState() { model->updateState(); } @@ -70,7 +72,7 @@ signals: void resizeSignal(const Signal *sig, int from, int size); void removeSignal(const Signal *sig); void editSignal(const Signal *origin_s, Signal &s); - void showChart(const QString &name, const Signal *sig, bool show, bool merge); + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); private: void addShortcuts(); diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 3f12c55ffc..9a085ec732 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -181,7 +181,7 @@ void ChartsWidget::settingChanged() { } } -ChartView *ChartsWidget::findChart(const QString &id, const Signal *sig) { +ChartView *ChartsWidget::findChart(const MessageId &id, const Signal *sig) { for (auto c : charts) if (c->hasSeries(id, sig)) return c; return nullptr; @@ -204,7 +204,7 @@ ChartView *ChartsWidget::createChart() { return chart; } -void ChartsWidget::showChart(const QString &id, const Signal *sig, bool show, bool merge) { +void ChartsWidget::showChart(const MessageId &id, const Signal *sig, bool show, bool merge) { setUpdatesEnabled(false); ChartView *chart = findChart(id, sig); if (show && !chart) { @@ -363,19 +363,18 @@ ChartView::ChartView(QWidget *parent) : QChartView(nullptr, parent) { QObject::connect(remove_btn, &QToolButton::clicked, this, &ChartView::remove); } -void ChartView::addSeries(const QString &msg_id, const Signal *sig) { +void ChartView::addSeries(const MessageId &msg_id, const Signal *sig) { if (hasSeries(msg_id, sig)) return; QXYSeries *series = createSeries(series_type, getColor(sig)); - auto [source, address] = DBCManager::parseId(msg_id); - sigs.push_back({.msg_id = msg_id, .address = address, .source = source, .sig = sig, .series = series}); + sigs.push_back({.msg_id = msg_id, .sig = sig, .series = series}); updateTitle(); updateSeries(sig); updateSeriesPoints(); emit seriesAdded(msg_id, sig); } -bool ChartView::hasSeries(const QString &msg_id, const Signal *sig) const { +bool ChartView::hasSeries(const MessageId &msg_id, const Signal *sig) const { return std::any_of(sigs.begin(), sigs.end(), [&](auto &s) { return s.msg_id == msg_id && s.sig == sig; }); } @@ -409,7 +408,7 @@ void ChartView::signalUpdated(const Signal *sig) { } void ChartView::msgUpdated(uint32_t address) { - if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.address == address; })) + if (std::any_of(sigs.begin(), sigs.end(), [=](auto &s) { return s.msg_id.address == address; })) updateTitle(); } @@ -455,7 +454,7 @@ void ChartView::updateTitle() { } for (auto &s : sigs) { auto decoration = s.series->isVisible() ? "none" : "line-through"; - s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id)); + s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id.toString())); } } @@ -517,7 +516,7 @@ void ChartView::updateSeries(const Signal *sig, const std::vector *even for (auto it = chunk.first; it != chunk.second; ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - if (s.address == c.getAddress() && s.source == c.getSrc()) { + if (s.msg_id.address == c.getAddress() && s.msg_id.source == c.getSrc()) { auto dat = c.getDat(); double value = get_raw_value((uint8_t *)dat.begin(), dat.size(), *s.sig); double ts = ((*it)->mono_time / (double)1e9) - route_start_time; // seconds @@ -847,7 +846,7 @@ SeriesSelector::SeriesSelector(QString title, QWidget *parent) : QDialog(parent) for (auto it = can->can_msgs.cbegin(); it != can->can_msgs.cend(); ++it) { if (auto m = dbc()->msg(it.key())) { - msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key()), it.key()); + msgs_combo->addItem(QString("%1 (%2)").arg(m->name).arg(it.key().toString()), QVariant::fromValue(it.key())); } } msgs_combo->model()->sort(0); @@ -872,7 +871,7 @@ void SeriesSelector::add(QListWidgetItem *item) { void SeriesSelector::remove(QListWidgetItem *item) { auto it = (ListItem *)item; - if (it->msg_id == msgs_combo->currentData().toString()) { + if (it->msg_id == msgs_combo->currentData().value()) { addItemToList(available_list, it->msg_id, it->sig); } delete item; @@ -881,7 +880,7 @@ void SeriesSelector::remove(QListWidgetItem *item) { void SeriesSelector::updateAvailableList(int index) { if (index == -1) return; available_list->clear(); - QString msg_id = msgs_combo->itemData(index).toString(); + MessageId msg_id = msgs_combo->itemData(index).value(); auto selected_items = seletedItems(); for (auto &[name, s] : dbc()->msg(msg_id)->sigs) { bool is_selected = std::any_of(selected_items.begin(), selected_items.end(), [=, sig=&s](auto it) { return it->msg_id == msg_id && it->sig == sig; }); @@ -891,9 +890,9 @@ void SeriesSelector::updateAvailableList(int index) { } } -void SeriesSelector::addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name) { +void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name) { QString text = QString("■ %1").arg(getColor(sig).name(), sig->name.c_str()); - if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id); + if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id.toString()); QLabel *label = new QLabel(text); label->setContentsMargins(5, 0, 5, 0); diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 58ae7e3b4c..7569155d39 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -25,17 +25,15 @@ class ChartView : public QChartView { public: ChartView(QWidget *parent = nullptr); - void addSeries(const QString &msg_id, const Signal *sig); - bool hasSeries(const QString &msg_id, const Signal *sig) const; + void addSeries(const MessageId &msg_id, const Signal *sig); + bool hasSeries(const MessageId &msg_id, const Signal *sig) const; void updateSeries(const Signal *sig = nullptr, const std::vector *events = nullptr, bool clear = true); void updatePlot(double cur, double min, double max); void setSeriesType(QAbstractSeries::SeriesType type); void updatePlotArea(int left); struct SigItem { - QString msg_id; - uint8_t source = 0; - uint32_t address = 0; + MessageId msg_id; const Signal *sig = nullptr; QXYSeries *series = nullptr; QVector vals; @@ -43,8 +41,8 @@ public: }; signals: - void seriesRemoved(const QString &id, const Signal *sig); - void seriesAdded(const QString &id, const Signal *sig); + void seriesRemoved(const MessageId &id, const Signal *sig); + void seriesAdded(const MessageId &id, const Signal *sig); void zoomIn(double min, double max); void zoomReset(); void remove(); @@ -55,7 +53,7 @@ private slots: void signalUpdated(const Signal *sig); void manageSeries(); void handleMarkerClicked(); - void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.address == address; }); } + void msgRemoved(uint32_t address) { removeIf([=](auto &s) { return s.msg_id.address == address; }); } void signalRemoved(const Signal *sig) { removeIf([=](auto &s) { return s.sig == sig; }); } private: @@ -99,8 +97,8 @@ class ChartsWidget : public QWidget { public: ChartsWidget(QWidget *parent = nullptr); - void showChart(const QString &id, const Signal *sig, bool show, bool merge); - inline bool hasSignal(const QString &id, const Signal *sig) { return findChart(id, sig) != nullptr; } + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); + inline bool hasSignal(const MessageId &id, const Signal *sig) { return findChart(id, sig) != nullptr; } public slots: void setColumnCount(int n); @@ -126,7 +124,7 @@ private: void updateLayout(); void settingChanged(); bool eventFilter(QObject *obj, QEvent *event) override; - ChartView *findChart(const QString &id, const Signal *sig); + ChartView *findChart(const MessageId &id, const Signal *sig); QLabel *title_label; QLabel *range_lb; @@ -152,18 +150,18 @@ private: class SeriesSelector : public QDialog { public: struct ListItem : public QListWidgetItem { - ListItem(const QString &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} - QString msg_id; + ListItem(const MessageId &msg_id, const Signal *sig, QListWidget *parent) : msg_id(msg_id), sig(sig), QListWidgetItem(parent) {} + MessageId msg_id; const Signal *sig; }; SeriesSelector(QString title, QWidget *parent); QList seletedItems(); - inline void addSelected(const QString &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); } + inline void addSelected(const MessageId &id, const Signal *sig) { addItemToList(selected_list, id, sig, true); } private: void updateAvailableList(int index); - void addItemToList(QListWidget *parent, const QString id, const Signal *sig, bool show_msg_name = false); + void addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name = false); void add(QListWidgetItem *item); void remove(QListWidgetItem *item); diff --git a/tools/cabana/commands.cc b/tools/cabana/commands.cc index e4bf999062..b03f46b5d2 100644 --- a/tools/cabana/commands.cc +++ b/tools/cabana/commands.cc @@ -4,13 +4,13 @@ // EditMsgCommand -EditMsgCommand::EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent) +EditMsgCommand::EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent) : id(id), new_title(title), new_size(size), QUndoCommand(parent) { if (auto msg = dbc()->msg(id)) { old_title = msg->name; old_size = msg->size; } - setText(QObject::tr("Edit message %1:%2").arg(DBCManager::parseId(id).second).arg(title)); + setText(QObject::tr("Edit message %1:%2").arg(id.address).arg(title)); } void EditMsgCommand::undo() { @@ -26,10 +26,10 @@ void EditMsgCommand::redo() { // RemoveMsgCommand -RemoveMsgCommand::RemoveMsgCommand(const QString &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) { +RemoveMsgCommand::RemoveMsgCommand(const MessageId &id, QUndoCommand *parent) : id(id), QUndoCommand(parent) { if (auto msg = dbc()->msg(id)) { message = *msg; - setText(QObject::tr("Remove message %1:%2").arg(DBCManager::parseId(id).second).arg(message.name)); + setText(QObject::tr("Remove message %1:%2").arg(id.address).arg(message.name)); } } @@ -48,9 +48,9 @@ void RemoveMsgCommand::redo() { // AddSigCommand -AddSigCommand::AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent) +AddSigCommand::AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent) : id(id), signal(sig), QUndoCommand(parent) { - setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(DBCManager::parseId(id).second)); + setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(id.address)); } void AddSigCommand::undo() { dbc()->removeSignal(id, signal.name.c_str()); } @@ -58,9 +58,9 @@ void AddSigCommand::redo() { dbc()->addSignal(id, signal); } // RemoveSigCommand -RemoveSigCommand::RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent) +RemoveSigCommand::RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent) : id(id), signal(*sig), QUndoCommand(parent) { - setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(DBCManager::parseId(id).second)); + setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(id.address)); } void RemoveSigCommand::undo() { dbc()->addSignal(id, signal); } @@ -68,7 +68,7 @@ void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name.c_str()); } // EditSignalCommand -EditSignalCommand::EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) +EditSignalCommand::EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) : id(id), old_signal(*sig), new_signal(new_sig), QUndoCommand(parent) { setText(QObject::tr("Edit signal %1").arg(old_signal.name.c_str())); } diff --git a/tools/cabana/commands.h b/tools/cabana/commands.h index c07a00b760..46e9f0a030 100644 --- a/tools/cabana/commands.h +++ b/tools/cabana/commands.h @@ -7,57 +7,57 @@ class EditMsgCommand : public QUndoCommand { public: - EditMsgCommand(const QString &id, const QString &title, int size, QUndoCommand *parent = nullptr); + EditMsgCommand(const MessageId &id, const QString &title, int size, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; QString old_title, new_title; int old_size = 0, new_size = 0; }; class RemoveMsgCommand : public QUndoCommand { public: - RemoveMsgCommand(const QString &id, QUndoCommand *parent = nullptr); + RemoveMsgCommand(const MessageId &id, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; DBCMsg message; }; class AddSigCommand : public QUndoCommand { public: - AddSigCommand(const QString &id, const Signal &sig, QUndoCommand *parent = nullptr); + AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal signal = {}; }; class RemoveSigCommand : public QUndoCommand { public: - RemoveSigCommand(const QString &id, const Signal *sig, QUndoCommand *parent = nullptr); + RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal signal = {}; }; class EditSignalCommand : public QUndoCommand { public: - EditSignalCommand(const QString &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr); + EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent = nullptr); void undo() override; void redo() override; private: - const QString id; + const MessageId id; Signal old_signal = {}; Signal new_signal = {}; }; diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 3d565e7067..27f16c71e5 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -4,6 +4,10 @@ #include #include +uint qHash(const MessageId &item) { + return qHash(item.source) ^ qHash(item.address); +} + DBCManager::DBCManager(QObject *parent) : QObject(parent) {} DBCManager::~DBCManager() {} @@ -56,29 +60,27 @@ QString DBCManager::generateDBC() { return dbc_string; } -void DBCManager::updateMsg(const QString &id, const QString &name, uint32_t size) { - auto [_, address] = parseId(id); - auto &m = msgs[address]; +void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size) { + auto &m = msgs[id.address]; m.name = name; m.size = size; - emit msgUpdated(address); + emit msgUpdated(id.address); } -void DBCManager::removeMsg(const QString &id) { - uint32_t address = parseId(id).second; - msgs.erase(address); - emit msgRemoved(address); +void DBCManager::removeMsg(const MessageId &id) { + msgs.erase(id.address); + emit msgRemoved(id.address); } -void DBCManager::addSignal(const QString &id, const Signal &sig) { - if (auto m = const_cast(msg(id))) { +void DBCManager::addSignal(const MessageId &id, const Signal &sig) { + if (auto m = const_cast(msg(id.address))) { auto &s = m->sigs[sig.name.c_str()]; s = sig; - emit signalAdded(parseId(id).second, &s); + emit signalAdded(id.address, &s); } } -void DBCManager::updateSignal(const QString &id, const QString &sig_name, const Signal &sig) { +void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig) { if (auto m = const_cast(msg(id))) { // change key name QString new_name = QString::fromStdString(sig.name); @@ -91,7 +93,7 @@ void DBCManager::updateSignal(const QString &id, const QString &sig_name, const } } -void DBCManager::removeSignal(const QString &id, const QString &sig_name) { +void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { if (auto m = const_cast(msg(id))) { auto it = m->sigs.find(sig_name); if (it != m->sigs.end()) { @@ -101,12 +103,6 @@ void DBCManager::removeSignal(const QString &id, const QString &sig_name) { } } -std::pair DBCManager::parseId(const QString &id) { - const auto list = id.split(':'); - if (list.size() != 2) return {0, 0}; - return {list[0].toInt(), list[1].toUInt(nullptr, 16)}; -} - DBCManager *dbc() { static DBCManager dbc_manager(nullptr); return &dbc_manager; diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index 7571d1c44e..b766c837b6 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -5,6 +5,35 @@ #include #include "opendbc/can/common_dbc.h" +struct MessageId { + uint8_t source; + uint32_t address; + + QString toString() const { + return QString("%1:%2").arg(source).arg(address, 1, 16); + } + + bool operator==(const MessageId &other) const { + return source == other.source && address == other.address; + } + + bool operator!=(const MessageId &other) const { + return !(*this == other); + } + + bool operator<(const MessageId &other) const { + return std::pair{source, address} < std::pair{other.source, other.address}; + } + + bool operator>(const MessageId &other) const { + return std::pair{source, address} > std::pair{other.source, other.address}; + } +}; + +Q_DECLARE_METATYPE(MessageId); + +uint qHash(const MessageId &item); + struct DBCMsg { QString name; uint32_t size; @@ -24,17 +53,16 @@ public: void open(const QString &dbc_file_name); bool open(const QString &name, const QString &content, QString *error = nullptr); QString generateDBC(); - void addSignal(const QString &id, const Signal &sig); - void updateSignal(const QString &id, const QString &sig_name, const Signal &sig); - void removeSignal(const QString &id, const QString &sig_name); + void addSignal(const MessageId &id, const Signal &sig); + void updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig); + void removeSignal(const MessageId &id, const QString &sig_name); - static std::pair parseId(const QString &id); inline static std::vector allDBCNames() { return get_dbc_names(); } inline QString name() const { return dbc ? dbc->name.c_str() : ""; } - void updateMsg(const QString &id, const QString &name, uint32_t size); - void removeMsg(const QString &id); + void updateMsg(const MessageId &id, const QString &name, uint32_t size); + void removeMsg(const MessageId &id); inline const std::map &messages() const { return msgs; } - inline const DBCMsg *msg(const QString &id) const { return msg(parseId(id).second); } + inline const DBCMsg *msg(const MessageId &id) const { return msg(id.address); } inline const DBCMsg *msg(uint32_t address) const { auto it = msgs.find(address); return it != msgs.end() ? &it->second : nullptr; @@ -65,7 +93,7 @@ int bigEndianBitIndex(int index); void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size); std::pair getSignalRange(const Signal *s); DBCManager *dbc(); -inline QString msgName(const QString &id) { +inline QString msgName(const MessageId &id) { auto msg = dbc()->msg(id); return msg ? msg->name : UNTITLED; } diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 2036912344..55ba0b9feb 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -85,11 +85,15 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &DetailWidget::refresh); QObject::connect(tabbar, &QTabBar::customContextMenuRequested, this, &DetailWidget::showTabBarContextMenu); QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) { - if (index != -1 && tabbar->tabText(index) != msg_id) { - setMessage(tabbar->tabText(index)); + if (index != -1) { + setMessage(tabbar_ids[index]); } }); - QObject::connect(tabbar, &QTabBar::tabCloseRequested, tabbar, &QTabBar::removeTab); + QObject::connect(tabbar, &QTabBar::tabCloseRequested, [this](int index) { + tabbar_ids.removeAt(index); + tabbar->removeTab(index); + assert(tabbar_ids.size() == tabbar->count()); + }); QObject::connect(charts, &ChartsWidget::seriesChanged, signal_view, &SignalView::updateChartState); } @@ -108,29 +112,32 @@ void DetailWidget::showTabBarContextMenu(const QPoint &pt) { } void DetailWidget::removeAll() { - msg_id = ""; + msg_id = std::nullopt; tabbar->blockSignals(true); while (tabbar->count() > 0) { tabbar->removeTab(0); } + tabbar_ids.clear(); tabbar->blockSignals(false); stacked_layout->setCurrentIndex(0); } -void DetailWidget::setMessage(const QString &message_id) { +void DetailWidget::setMessage(const MessageId &message_id) { msg_id = message_id; - int index = tabbar->count() - 1; - for (/**/; index >= 0 && tabbar->tabText(index) != msg_id; --index) { /**/ } + int index = tabbar_ids.indexOf(*msg_id); + if (index == -1) { - index = tabbar->addTab(message_id); + tabbar_ids.append(*msg_id); + index = tabbar->addTab(message_id.toString()); tabbar->setTabToolTip(index, msgName(message_id)); } + assert(tabbar->count() == tabbar_ids.size()); setUpdatesEnabled(false); - signal_view->setMessage(msg_id); - binary_view->setMessage(msg_id); - history_log->setMessage(msg_id); + signal_view->setMessage(*msg_id); + binary_view->setMessage(*msg_id); + history_log->setMessage(*msg_id); stacked_layout->setCurrentIndex(1); tabbar->setCurrentIndex(index); @@ -141,12 +148,12 @@ void DetailWidget::setMessage(const QString &message_id) { } void DetailWidget::refresh() { - if (msg_id.isEmpty()) return; + if (!msg_id) return; QStringList warnings; - const DBCMsg *msg = dbc()->msg(msg_id); + const DBCMsg *msg = dbc()->msg(*msg_id); if (msg) { - if (msg->size != can->lastMessage(msg_id).dat.size()) { + if (msg->size != can->lastMessage(*msg_id).dat.size()) { warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size)); } for (auto s : binary_view->getOverlappingSignals()) { @@ -156,7 +163,7 @@ void DetailWidget::refresh() { warnings.push_back(tr("Drag-Select in binary view to create new signal.")); } remove_msg_act->setEnabled(msg != nullptr); - name_label->setText(msgName(msg_id)); + name_label->setText(msgName(*msg_id)); if (!warnings.isEmpty()) { warning_label->setText(warnings.join('\n')); @@ -165,9 +172,9 @@ void DetailWidget::refresh() { warning_widget->setVisible(!warnings.isEmpty()); } -void DetailWidget::updateState(const QHash *msgs) { +void DetailWidget::updateState(const QHash *msgs) { time_label->setText(QString::number(can->currentSec(), 'f', 3)); - if (msg_id.isEmpty() || (msgs && !msgs->contains(msg_id))) + if (!msg_id || (msgs && !msgs->contains(*msg_id))) return; if (tab_widget->currentIndex() == 0) @@ -177,24 +184,24 @@ void DetailWidget::updateState(const QHash *msgs) { } void DetailWidget::editMsg() { - QString id = msg_id; + MessageId id = *msg_id; auto msg = dbc()->msg(id); int size = msg ? msg->size : can->lastMessage(id).dat.size(); EditMessageDialog dlg(id, msgName(id), size, this); if (dlg.exec()) { - UndoStack::push(new EditMsgCommand(msg_id, dlg.name_edit->text(), dlg.size_spin->value())); + UndoStack::push(new EditMsgCommand(*msg_id, dlg.name_edit->text(), dlg.size_spin->value())); } } void DetailWidget::removeMsg() { - UndoStack::push(new RemoveMsgCommand(msg_id)); + UndoStack::push(new RemoveMsgCommand(*msg_id)); } // EditMessageDialog -EditMessageDialog::EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent) +EditMessageDialog::EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent) : original_name(title), QDialog(parent) { - setWindowTitle(tr("Edit message: %1").arg(msg_id)); + setWindowTitle(tr("Edit message: %1").arg(msg_id.toString())); QFormLayout *form_layout = new QFormLayout(this); form_layout->addRow("", error_label = new QLabel); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index c5d5fe9a4d..949a8c9b8d 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -14,7 +14,7 @@ class EditMessageDialog : public QDialog { public: - EditMessageDialog(const QString &msg_id, const QString &title, int size, QWidget *parent); + EditMessageDialog(const MessageId &msg_id, const QString &title, int size, QWidget *parent); void validateName(const QString &text); QString original_name; @@ -34,7 +34,7 @@ class DetailWidget : public QWidget { public: DetailWidget(ChartsWidget *charts, QWidget *parent); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void refresh(); void removeAll(); QSize minimumSizeHint() const override { return binary_view->minimumSizeHint(); } @@ -43,13 +43,14 @@ private: void showTabBarContextMenu(const QPoint &pt); void editMsg(); void removeMsg(); - void updateState(const QHash * msgs = nullptr); + void updateState(const QHash * msgs = nullptr); - QString msg_id; + std::optional msg_id; QLabel *time_label, *warning_icon, *warning_label; ElidedLabel *name_label; QWidget *warning_widget; QTabBar *tabbar; + QList tabbar_ids; QTabWidget *tab_widget; QAction *remove_msg_act; LogsWidget *history_log; diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index e4ad99758b..f7f02b06d8 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -22,14 +22,14 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const { return {}; } -void HistoryLogModel::setMessage(const QString &message_id) { +void HistoryLogModel::setMessage(const MessageId &message_id) { msg_id = message_id; } void HistoryLogModel::refresh() { beginResetModel(); sigs.clear(); - if (auto dbc_msg = dbc()->msg(msg_id)) { + if (auto dbc_msg = dbc()->msg(*msg_id)) { sigs = dbc_msg->getSignals(); } last_fetch_time = 0; @@ -78,8 +78,8 @@ void HistoryLogModel::setFilter(int sig_idx, const QString &value, std::function } void HistoryLogModel::updateState() { - if (!msg_id.isEmpty()) { - uint64_t current_time = (can->lastMessage(msg_id).ts + can->routeStartTime()) * 1e9 + 1; + if (msg_id) { + uint64_t current_time = (can->lastMessage(*msg_id).ts + can->routeStartTime()) * 1e9 + 1; auto new_msgs = dynamic_mode ? fetchData(current_time, last_fetch_time) : fetchData(0); if (!new_msgs.empty()) { beginInsertRows({}, 0, new_msgs.size() - 1); @@ -106,12 +106,11 @@ void HistoryLogModel::fetchMore(const QModelIndex &parent) { template std::deque HistoryLogModel::fetchData(InputIt first, InputIt last, uint64_t min_time) { std::deque msgs; - const auto [src, address] = DBCManager::parseId(msg_id); QVector values(sigs.size()); for (auto it = first; it != last && (*it)->mono_time > min_time; ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - if (address == c.getAddress() && src == c.getSrc()) { + if (msg_id->address == c.getAddress() && msg_id->source == c.getSrc()) { const auto dat = c.getDat(); for (int i = 0; i < sigs.size(); ++i) { values[i] = get_raw_value((uint8_t *)dat.begin(), dat.size(), *(sigs[i])); @@ -136,7 +135,7 @@ template std::deque HistoryLogModel::fetchData<>(std:: std::deque HistoryLogModel::fetchData(uint64_t from_time, uint64_t min_time) { auto events = can->events(); - const auto freq = can->lastMessage(msg_id).freq; + const auto freq = can->lastMessage(*msg_id).freq; const bool update_colors = !display_signals_mode || sigs.empty(); if (dynamic_mode) { @@ -241,13 +240,13 @@ LogsWidget::LogsWidget(QWidget *parent) : QWidget(parent) { QObject::connect(can, &AbstractStream::eventsMerged, model, &HistoryLogModel::segmentsMerged); } -void LogsWidget::setMessage(const QString &message_id) { +void LogsWidget::setMessage(const MessageId &message_id) { model->setMessage(message_id); refresh(); } void LogsWidget::refresh() { - if (model->msg_id.isEmpty()) return; + if (!model->msg_id) return; model->setFilter(0, "", nullptr); model->refresh(); diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index 2458fc1c31..00a8f73836 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -1,6 +1,8 @@ #pragma once #include +#include + #include #include #include @@ -22,7 +24,7 @@ class HistoryLogModel : public QAbstractTableModel { public: HistoryLogModel(QObject *parent) : QAbstractTableModel(parent) {} - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void updateState(); void setFilter(int sig_idx, const QString &value, std::function cmp); QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override; @@ -52,7 +54,7 @@ public: std::deque fetchData(InputIt first, InputIt last, uint64_t min_time); std::deque fetchData(uint64_t from_time, uint64_t min_time = 0); - QString msg_id; + std::optional msg_id; ChangeTracker hex_colors; bool has_more_data = true; const int batch_size = 50; @@ -71,7 +73,7 @@ class LogsWidget : public QWidget { public: LogsWidget(QWidget *parent); - void setMessage(const QString &message_id); + void setMessage(const MessageId &message_id); void updateState() {if (dynamic_mode->isChecked()) model->updateState(); } void showEvent(QShowEvent *event) override { if (dynamic_mode->isChecked()) model->refresh(); } diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 8279d08a5c..4f6bb92375 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -46,12 +46,12 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { QObject::connect(dbc(), &DBCManager::DBCFileChanged, model, &MessageListModel::sortMessages); QObject::connect(dbc(), &DBCManager::msgUpdated, model, &MessageListModel::sortMessages); QObject::connect(dbc(), &DBCManager::msgRemoved, model, &MessageListModel::sortMessages); - QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(current_msg_id); }); + QObject::connect(model, &MessageListModel::modelReset, [this]() { selectMessage(*current_msg_id); }); QObject::connect(table_widget->selectionModel(), &QItemSelectionModel::currentChanged, [=](const QModelIndex ¤t, const QModelIndex &previous) { if (current.isValid() && current.row() < model->msgs.size()) { - if (model->msgs[current.row()] != current_msg_id) { + if (model->msgs[current.row()] != *current_msg_id) { current_msg_id = model->msgs[current.row()]; - emit msgSelectionChanged(current_msg_id); + emit msgSelectionChanged(*current_msg_id); } } }); @@ -67,7 +67,7 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { updateSuppressedButtons(); } -void MessagesWidget::selectMessage(const QString &msg_id) { +void MessagesWidget::selectMessage(const MessageId &msg_id) { if (int row = model->msgs.indexOf(msg_id); row != -1) { table_widget->selectionModel()->setCurrentIndex(model->index(row, 0), QItemSelectionModel::Rows | QItemSelectionModel::ClearAndSelect); } @@ -86,7 +86,7 @@ void MessagesWidget::updateSuppressedButtons() { void MessagesWidget::reset() { model->reset(); filter->clear(); - current_msg_id = ""; + current_msg_id = std::nullopt; updateSuppressedButtons(); } @@ -106,7 +106,7 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { if (role == Qt::DisplayRole) { switch (index.column()) { case 0: return msgName(id); - case 1: return id; + case 1: return id.toString(); // TODO: put source and address in separate columns case 2: return can_data.freq; case 3: return can_data.count; case 4: return toHex(can_data.dat); @@ -128,9 +128,9 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { } void MessageListModel::setFilterString(const QString &string) { - auto contains = [](const QString &id, const QString &txt) { + auto contains = [](const MessageId &id, const QString &txt) { auto cs = Qt::CaseInsensitive; - if (id.contains(txt, cs) || msgName(id).contains(txt, cs)) return true; + if (id.toString().contains(txt, cs) || msgName(id).contains(txt, cs)) return true; // Search by signal name if (const auto msg = dbc()->msg(id)) { for (auto &signal : msg->getSignals()) { @@ -160,9 +160,7 @@ void MessageListModel::sortMessages() { }); } else if (sort_column == 1) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { - auto ll = DBCManager::parseId(l); - auto rr = DBCManager::parseId(r); - return sort_order == Qt::AscendingOrder ? ll < rr : ll > rr; + return sort_order == Qt::AscendingOrder ? l < r : l > r; }); } else if (sort_column == 2) { std::sort(msgs.begin(), msgs.end(), [this](auto &l, auto &r) { @@ -180,7 +178,7 @@ void MessageListModel::sortMessages() { endResetModel(); } -void MessageListModel::msgsReceived(const QHash *new_msgs) { +void MessageListModel::msgsReceived(const QHash *new_msgs) { int prev_row_count = msgs.size(); if (filter_str.isEmpty() && msgs.size() != can->can_msgs.size()) { msgs = can->can_msgs.keys(); diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 81ee36cd6f..562069c3ae 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -1,5 +1,7 @@ #pragma once +#include + #include #include #include @@ -20,13 +22,13 @@ public: int rowCount(const QModelIndex &parent = QModelIndex()) const override { return msgs.size(); } void sort(int column, Qt::SortOrder order = Qt::AscendingOrder) override; void setFilterString(const QString &string); - void msgsReceived(const QHash *new_msgs = nullptr); + void msgsReceived(const QHash *new_msgs = nullptr); void sortMessages(); void suppress(); void clearSuppress(); void reset(); - QStringList msgs; - QSet> suppressed_bytes; + QList msgs; + QSet> suppressed_bytes; private: QString filter_str; @@ -39,18 +41,18 @@ class MessagesWidget : public QWidget { public: MessagesWidget(QWidget *parent); - void selectMessage(const QString &message_id); + void selectMessage(const MessageId &message_id); QByteArray saveHeaderState() const { return table_widget->horizontalHeader()->saveState(); } bool restoreHeaderState(const QByteArray &state) const { return table_widget->horizontalHeader()->restoreState(state); } void updateSuppressedButtons(); void reset(); signals: - void msgSelectionChanged(const QString &message_id); + void msgSelectionChanged(const MessageId &message_id); protected: QTableView *table_widget; - QString current_msg_id; + std::optional current_msg_id; QLineEdit *filter; MessageListModel *model; QPushButton *suppress_add; diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 0499b1be8a..98dd39204f 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -31,7 +31,7 @@ void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Sign } } -void SignalModel::setMessage(const QString &id) { +void SignalModel::setMessage(const MessageId &id) { msg_id = id; filter_str = ""; refresh(); @@ -56,7 +56,7 @@ void SignalModel::refresh() { endResetModel(); } -void SignalModel::updateState(const QHash *msgs) { +void SignalModel::updateState(const QHash *msgs) { if (!msgs || (msgs->contains(msg_id))) { auto &dat = can->lastMessage(msg_id).dat; int row = 0; @@ -230,13 +230,13 @@ void SignalModel::removeSignal(const Signal *sig) { } void SignalModel::handleMsgChanged(uint32_t address) { - if (address == DBCManager::parseId(msg_id).second) { + if (address == msg_id.address) { refresh(); } } void SignalModel::handleSignalAdded(uint32_t address, const Signal *sig) { - if (address == DBCManager::parseId(msg_id).second) { + if (address == msg_id.address) { int i = 0; for (; i < root->children.size(); ++i) { if (sig->start_bit < root->children[i]->sig->start_bit) break; @@ -367,7 +367,7 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { expandSignal(sig); }); } -void SignalView::setMessage(const QString &id) { +void SignalView::setMessage(const MessageId &id) { msg_id = id; filter_edit->clear(); model->setMessage(id); diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index c0b649209a..7e5015f707 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -37,7 +37,7 @@ public: QModelIndex parent(const QModelIndex &index) const override; Qt::ItemFlags flags(const QModelIndex &index) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - void setMessage(const QString &id); + void setMessage(const MessageId &id); void setFilter(const QString &txt); void addSignal(int start_bit, int size, bool little_endian); bool saveSignal(const Signal *origin_s, Signal &s); @@ -54,9 +54,9 @@ private: void handleSignalRemoved(const Signal *sig); void handleMsgChanged(uint32_t address); void refresh(); - void updateState(const QHash *msgs); + void updateState(const QHash *msgs); - QString msg_id; + MessageId msg_id; QString filter_str; std::unique_ptr root; friend class SignalView; @@ -76,7 +76,7 @@ class SignalView : public QWidget { public: SignalView(ChartsWidget *charts, QWidget *parent); - void setMessage(const QString &id); + void setMessage(const MessageId &id); void signalHovered(const Signal *sig); void updateChartState(); void expandSignal(const Signal *sig); @@ -85,13 +85,13 @@ public: signals: void highlight(const Signal *sig); - void showChart(const QString &name, const Signal *sig, bool show, bool merge); + void showChart(const MessageId &id, const Signal *sig, bool show, bool merge); private: void rowsChanged(); void leaveEvent(QEvent *event); - QString msg_id; + MessageId msg_id; QTreeView *tree; QLineEdit *filter_edit; ChartsWidget *charts; diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 13b154a7ea..5f12e0c42f 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -4,12 +4,12 @@ AbstractStream *can = nullptr; AbstractStream::AbstractStream(QObject *parent, bool is_live_streaming) : is_live_streaming(is_live_streaming), QObject(parent) { can = this; - new_msgs = std::make_unique>(); + new_msgs = std::make_unique>(); QObject::connect(this, &AbstractStream::received, this, &AbstractStream::process, Qt::QueuedConnection); QObject::connect(this, &AbstractStream::seekedTo, this, &AbstractStream::updateLastMsgsTo); } -void AbstractStream::process(QHash *messages) { +void AbstractStream::process(QHash *messages) { for (auto it = messages->begin(); it != messages->end(); ++it) { can_msgs[it.key()] = it.value(); } @@ -25,7 +25,7 @@ bool AbstractStream::updateEvent(const Event *event) { if (event->which == cereal::Event::Which::CAN) { double current_sec = event->mono_time / 1e9 - routeStartTime(); for (const auto &c : event->event.getCan()) { - QString id = QString("%1:%2").arg(c.getSrc()).arg(c.getAddress(), 1, 16); + MessageId id = {.source = c.getSrc(), .address = c.getAddress()}; CanData &data = (*new_msgs)[id]; data.ts = current_sec; data.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); @@ -44,21 +44,21 @@ bool AbstractStream::updateEvent(const Event *event) { prev_update_ts = ts; // use pointer to avoid data copy in queued connection. emit received(new_msgs.release()); - new_msgs.reset(new QHash); + new_msgs.reset(new QHash); new_msgs->reserve(100); } } return true; } -const CanData &AbstractStream::lastMessage(const QString &id) { +const CanData &AbstractStream::lastMessage(const MessageId &id) { static CanData empty_data; auto it = can_msgs.find(id); return it != can_msgs.end() ? it.value() : empty_data; } void AbstractStream::updateLastMsgsTo(double sec) { - QHash, CanData> last_msgs; // Much faster than QHash + QHash last_msgs; last_msgs.reserve(can_msgs.size()); double route_start_time = routeStartTime(); uint64_t last_ts = (sec + route_start_time) * 1e9; @@ -66,7 +66,7 @@ void AbstractStream::updateLastMsgsTo(double sec) { for (auto it = last; it != events()->rend(); ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { - auto &m = last_msgs[{c.getSrc(), c.getAddress()}]; + auto &m = last_msgs[{.source = c.getSrc(), .address = c.getAddress()}]; if (++m.count == 1) { m.ts = ((*it)->mono_time / 1e9) - route_start_time; m.dat = QByteArray((char *)c.getDat().begin(), c.getDat().size()); @@ -87,9 +87,8 @@ void AbstractStream::updateLastMsgsTo(double sec) { counters.clear(); can_msgs.clear(); for (auto it = last_msgs.cbegin(); it != last_msgs.cend(); ++it) { - QString msg_id = QString("%1:%2").arg(it.key().first).arg(it.key().second, 1, 16); - can_msgs[msg_id] = it.value(); - counters[msg_id] = it.value().count; + can_msgs[it.key()] = it.value(); + counters[it.key()] = it.value().count; } emit updated(); emit msgsReceived(&can_msgs); diff --git a/tools/cabana/streams/abstractstream.h b/tools/cabana/streams/abstractstream.h index 8c10d959cb..e582682971 100644 --- a/tools/cabana/streams/abstractstream.h +++ b/tools/cabana/streams/abstractstream.h @@ -5,6 +5,7 @@ #include #include +#include "tools/cabana/dbcmanager.h" #include "tools/cabana/settings.h" #include "tools/cabana/util.h" #include "tools/replay/replay.h" @@ -33,7 +34,7 @@ public: virtual double routeStartTime() const { return 0; } virtual double currentSec() const = 0; virtual QDateTime currentDateTime() const { return {}; } - virtual const CanData &lastMessage(const QString &id); + virtual const CanData &lastMessage(const MessageId &id); virtual VisionStreamType visionStreamType() const { return VISION_STREAM_ROAD; } virtual const Route *route() const { return nullptr; } virtual const std::vector *events() const = 0; @@ -49,22 +50,22 @@ signals: void streamStarted(); void eventsMerged(); void updated(); - void msgsReceived(const QHash *); - void received(QHash *); + void msgsReceived(const QHash *); + void received(QHash *); public: - QHash can_msgs; + QHash can_msgs; protected: - void process(QHash *); + void process(QHash *); bool updateEvent(const Event *event); void updateLastMsgsTo(double sec); bool is_live_streaming = false; std::atomic processing = false; - QHash counters; - std::unique_ptr> new_msgs; - QHash change_trackers; + QHash counters; + std::unique_ptr> new_msgs; + QHash change_trackers; }; // A global pointer referring to the unique AbstractStream object diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index 63d01b152d..ffb0e54b0e 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -20,10 +20,10 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi bus_combo = new QComboBox(this); QSet bus_set; for (auto it = can->can_msgs.begin(); it != can->can_msgs.end(); ++it) { - bus_set << DBCManager::parseId(it.key()).first; + bus_set << it.key().source; } for (uint8_t bus : bus_set) { - bus_combo->addItem(QString::number(bus)); + bus_combo->addItem(QString::number(bus), bus); } bus_combo->model()->sort(0); bus_combo->setCurrentIndex(0); @@ -69,9 +69,11 @@ FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::Wi setMinimumSize({700, 500}); QObject::connect(search_btn, &QPushButton::clicked, this, &FindSimilarBitsDlg::find); + QObject::connect(table, &QTableWidget::doubleClicked, [this](const QModelIndex &index) { if (index.isValid()) { - emit openMessage(bus_combo->currentText() + ":" + table->item(index.row(), 0)->text()); + MessageId msg_id = {.source = (uint8_t)bus_combo->currentData().toUInt(), .address = table->item(index.row(), 0)->text().toUInt(0, 16)}; + emit openMessage(msg_id); } }); } diff --git a/tools/cabana/tools/findsimilarbits.h b/tools/cabana/tools/findsimilarbits.h index 30d78f0dea..53d7806a8f 100644 --- a/tools/cabana/tools/findsimilarbits.h +++ b/tools/cabana/tools/findsimilarbits.h @@ -6,6 +6,8 @@ #include #include +#include "tools/cabana/dbcmanager.h" + class FindSimilarBitsDlg : public QDialog { Q_OBJECT @@ -13,7 +15,7 @@ public: FindSimilarBitsDlg(QWidget *parent); signals: - void openMessage(const QString &msg_id); + void openMessage(const MessageId &msg_id); private: struct mismatched_struct { From 5dde8f2c8436df9a11bfb11cf86dcfbf3f1ee874 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 15 Feb 2023 15:52:10 -0800 Subject: [PATCH 36/63] Write boardd param to continue startup (#27354) disable at the bottom --- selfdrive/car/car_helpers.py | 3 ++- selfdrive/car/fw_versions.py | 18 +++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/car_helpers.py b/selfdrive/car/car_helpers.py index ae19fd6248..370772c902 100644 --- a/selfdrive/car/car_helpers.py +++ b/selfdrive/car/car_helpers.py @@ -8,7 +8,7 @@ from system.version import is_comma_remote, is_tested_branch from selfdrive.car.interfaces import get_interface_attr from selfdrive.car.fingerprints import eliminate_incompatible_cars, all_legacy_fingerprint_cars from selfdrive.car.vin import get_vin, is_valid_vin, VIN_UNKNOWN -from selfdrive.car.fw_versions import get_fw_versions_ordered, match_fw_to_car, get_present_ecus +from selfdrive.car.fw_versions import disable_obd_multiplexing, get_fw_versions_ordered, match_fw_to_car, get_present_ecus from system.swaglog import cloudlog import cereal.messaging as messaging from selfdrive.car import gen_empty_fingerprint @@ -116,6 +116,7 @@ def fingerprint(logcan, sendcan, num_pandas): params = Params() params.put("CarVin", vin) + disable_obd_multiplexing(params) finger = gen_empty_fingerprint() candidate_cars = {i: all_legacy_fingerprint_cars() for i in [0, 1]} # attempt fingerprint on both bus 0 and 1 diff --git a/selfdrive/car/fw_versions.py b/selfdrive/car/fw_versions.py index 23b0fcc6d1..8092ac0b76 100755 --- a/selfdrive/car/fw_versions.py +++ b/selfdrive/car/fw_versions.py @@ -198,6 +198,15 @@ def get_brand_ecu_matches(ecu_rx_addrs): return brand_matches +def disable_obd_multiplexing(params): + if not params.get_bool("ObdMultiplexingDisabled"): + params.put_bool("FirmwareObdQueryDone", True) + + cloudlog.warning("Waiting for OBD multiplexing to be disabled") + params.get_bool("ObdMultiplexingDisabled", block=True) + cloudlog.warning("OBD multiplexing disabled") + + def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pandas=1, debug=False, progress=False): """Queries for FW versions ordering brands by likelihood, breaks when exact match is found""" @@ -214,14 +223,9 @@ def get_fw_versions_ordered(logcan, sendcan, ecu_rx_addrs, timeout=0.1, num_pand matched_brand = brand break + disable_obd_multiplexing(Params()) + # Do non-OBD queries for matched brand, or all if no match is found - params = Params() - params.put_bool("FirmwareObdQueryDone", True) - - cloudlog.warning("Waiting for OBD multiplexing to be disabled") - params.get_bool("ObdMultiplexingDisabled", block=True) - cloudlog.warning("OBD multiplexing disabled") - for brand in FW_QUERY_CONFIGS.keys(): if brand == matched_brand or matched_brand is None: all_car_fw.extend(get_fw_versions(logcan, sendcan, query_brand=brand, timeout=timeout, num_pandas=num_pandas, obd_multiplexed=False, debug=debug, progress=progress)) From 2bc2dbfb700e71588c998cf1dfaef10ac9d852ce Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 15 Feb 2023 15:55:08 -0800 Subject: [PATCH 37/63] process replay: fix hang --- selfdrive/test/process_replay/process_replay.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index b531cb3430..28fc9c452c 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -407,6 +407,7 @@ def setup_env(simulation=False, CP=None, cfg=None, controlsState=None): params.put_bool("WideCameraOnly", False) params.put_bool("DisableLogging", False) params.put_bool("UbloxAvailable", True) + params.put_bool("ObdMultiplexingDisabled", True) os.environ["NO_RADAR_SLEEP"] = "1" os.environ["REPLAY"] = "1" From 48b059d3670e8082eae785c850508f88b1181188 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 15 Feb 2023 15:59:23 -0800 Subject: [PATCH 38/63] CAN fingerprint script improvements (#27355) * match online logic * 0 and 2 are different buses. on gm, same address has different lengths * match fingerprint_from_route --- selfdrive/debug/fingerprint_from_route.py | 2 +- selfdrive/debug/get_fingerprint.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/selfdrive/debug/fingerprint_from_route.py b/selfdrive/debug/fingerprint_from_route.py index 326e68f8e7..b3598b105c 100755 --- a/selfdrive/debug/fingerprint_from_route.py +++ b/selfdrive/debug/fingerprint_from_route.py @@ -17,7 +17,7 @@ def get_fingerprint(lr): for c in msg.can: # read also msgs sent by EON on CAN bus 0x80 and filter out the # addr with more than 11 bits - if c.src % 0x80 == 0 and c.address < 0x800: + if c.src % 0x80 == 0 and c.address < 0x800 and c.address not in (0x7df, 0x7e0, 0x7e8): msgs[c.address] = len(c.dat) # show CAN fingerprint diff --git a/selfdrive/debug/get_fingerprint.py b/selfdrive/debug/get_fingerprint.py index e678db4f17..f7f7a1604f 100755 --- a/selfdrive/debug/get_fingerprint.py +++ b/selfdrive/debug/get_fingerprint.py @@ -22,7 +22,7 @@ while True: for c in lc.can: # read also msgs sent by EON on CAN bus 0x80 and filter out the # addr with more than 11 bits - if c.src in [0, 2] and c.address < 0x800: + if c.src % 0x80 == 0 and c.address < 0x800 and c.address not in (0x7df, 0x7e0, 0x7e8): msgs[c.address] = len(c.dat) fingerprint = ', '.join("%d: %d" % v for v in sorted(msgs.items())) From 89934b35d04291384b7a287a41ce49905f321167 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 15 Feb 2023 16:27:00 -0800 Subject: [PATCH 39/63] Car interfaces: assert reasonable centerToFront range (#27356) * assert reasonable centerToFront values * comment * fix Bolt centerToFront * Update ref_commit --- selfdrive/car/gm/interface.py | 2 +- selfdrive/car/tests/test_car_interfaces.py | 3 ++- selfdrive/test/process_replay/ref_commit | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 104cb8fbd8..71e1ad4018 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -213,7 +213,7 @@ class CarInterface(CarInterfaceBase): ret.mass = 1669. + STD_CARGO_KG ret.wheelbase = 2.63779 ret.steerRatio = 16.8 - ret.centerToFront = 2.15 # measured + ret.centerToFront = ret.wheelbase * 0.4 tire_stiffness_factor = 1.0 ret.steerActuatorDelay = 0.12 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) diff --git a/selfdrive/car/tests/test_car_interfaces.py b/selfdrive/car/tests/test_car_interfaces.py index 78ecbe425e..ac8213e4c1 100755 --- a/selfdrive/car/tests/test_car_interfaces.py +++ b/selfdrive/car/tests/test_car_interfaces.py @@ -32,7 +32,8 @@ class TestCarInterfaces(unittest.TestCase): self.assertGreater(car_params.mass, 1) self.assertGreater(car_params.wheelbase, 0) - self.assertGreater(car_params.centerToFront, 0) + # centerToFront is center of gravity to front wheels, assert a reasonable range + self.assertTrue(car_params.wheelbase * 0.3 < car_params.centerToFront < car_params.wheelbase * 0.7) self.assertGreater(car_params.maxLateralAccel, 0) # Longitudinal sanity checks diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 85eada072e..b151a6a5ae 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -c7bb411b37ab7ff573402b6e4fa24f796cbb2ee8 \ No newline at end of file +fbb99ee7dc0336062e6785814af82e359dcdd9bf From b76795d7f083c956004fefd07dbb406eeeb20584 Mon Sep 17 00:00:00 2001 From: Ricky Gilleland Date: Wed, 15 Feb 2023 20:07:24 -0500 Subject: [PATCH 40/63] GM: Escalade 2017 support (#27276) * Initial 2017 Escalade values * update docs/CARS.md * revert back to v1 fingerprint & add test route * revert bad merge * update fingerprint * update * update * Update selfdrive/car/gm/values.py * Update selfdrive/car/gm/values.py * no engine * Try global tune * pcm * Driver Assist Package has ACC, and includes LKAS from previous package * update docs * add to releases --------- Co-authored-by: Shane Smiskol --- RELEASES.md | 1 + docs/CARS.md | 3 ++- selfdrive/car/gm/interface.py | 8 ++++++++ selfdrive/car/gm/values.py | 6 ++++++ selfdrive/car/tests/routes.py | 1 + selfdrive/car/torque_data/override.yaml | 1 + 6 files changed, 19 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index ceae8d10cb..78d2e3b74b 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -7,6 +7,7 @@ Version 0.9.1 (2023-02-23) * Adjust alert volume using ambient noise level * Driver monitoring icon shows driver's head pose * German translation thanks to Vrabetz and CzokNorris! +* Cadillac Escalade 2017 support thanks to rickygilleland! * Chevrolet Bolt EV 2022-23 support thanks to JasonJShuler! * Genesis GV60 2023 support thanks to sunnyhaibin! * Hyundai Tucson 2022-23 support diff --git a/docs/CARS.md b/docs/CARS.md index e6b6bbee7d..8860299360 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -4,7 +4,7 @@ A supported vehicle is one that just works when you install a comma three. All supported cars provide a better experience than any stock system. -# 236 Supported Cars +# 237 Supported Cars |Make|Model|Supported Package|ACC|No ACC accel below|No ALC below|Steering Torque|Resume from stop|Harness|Video| |---|---|---|:---:|:---:|:---:|:---:|:---:|:---:|:---:| @@ -17,6 +17,7 @@ A supported vehicle is one that just works when you install a comma three. All s |Audi|Q3 2019-23|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| |Audi|RS3 2018|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| |Audi|S3 2015-17|Adaptive Cruise Control (ACC) & Lane Assist|openpilot available[1,9](#footnotes)|0 mph|0 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-full.svg)](##)|J533|| +|Cadillac|Escalade 2017[3](#footnotes)|Driver Assist Package|openpilot|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II|| |Cadillac|Escalade ESV 2016[3](#footnotes)|Adaptive Cruise Control (ACC) & LKAS|openpilot|0 mph|7 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|OBD-II|| |Chevrolet|Bolt EUV 2022-23|Premier or Premier Redline Trim without Super Cruise Package|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM|| |Chevrolet|Bolt EV 2022-23|2LT Trim with Adaptive Cruise Control Package|openpilot available[1](#footnotes)|3 mph|6 mph|[![star](assets/icon-star-full.svg)](##)|[![star](assets/icon-star-empty.svg)](##)|GM|| diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 71e1ad4018..c28274011e 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -198,6 +198,14 @@ class CarInterface(CarInterfaceBase): ret.steerRatio = 15.3 ret.centerToFront = ret.wheelbase * 0.5 + elif candidate == CAR.ESCALADE: + ret.minEnableSpeed = -1. # engage speed is decided by pcm + ret.mass = 5653. * CV.LB_TO_KG + STD_CARGO_KG # (5552+5815)/2 + ret.wheelbase = 2.95 # 116 inches in meters + ret.steerRatio = 17.3 + ret.centerToFront = ret.wheelbase * 0.5 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + elif candidate == CAR.ESCALADE_ESV: ret.minEnableSpeed = -1. # engage speed is decided by pcm ret.mass = 2739. + STD_CARGO_KG diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 1c956192eb..207af6bb05 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -67,6 +67,7 @@ class CAR: MALIBU = "CHEVROLET MALIBU PREMIER 2017" ACADIA = "GMC ACADIA DENALI 2018" BUICK_REGAL = "BUICK REGAL ESSENCE 2018" + ESCALADE = "CADILLAC ESCALADE 2017" ESCALADE_ESV = "CADILLAC ESCALADE ESV 2016" BOLT_EUV = "CHEVROLET BOLT EUV 2022" SILVERADO = "CHEVROLET SILVERADO 1500 2020" @@ -99,6 +100,7 @@ CAR_INFO: Dict[str, Union[GMCarInfo, List[GMCarInfo]]] = { CAR.MALIBU: GMCarInfo("Chevrolet Malibu Premier 2017"), CAR.ACADIA: GMCarInfo("GMC Acadia 2018", video_link="https://www.youtube.com/watch?v=0ZN6DdsBUZo"), CAR.BUICK_REGAL: GMCarInfo("Buick Regal Essence 2018"), + CAR.ESCALADE: GMCarInfo("Cadillac Escalade 2017", "Driver Assist Package"), CAR.ESCALADE_ESV: GMCarInfo("Cadillac Escalade ESV 2016", "Adaptive Cruise Control (ACC) & LKAS"), CAR.BOLT_EUV: [ GMCarInfo("Chevrolet Bolt EUV 2022-23", "Premier or Premier Redline Trim without Super Cruise Package", "https://youtu.be/xvwzGMUA210"), @@ -174,6 +176,10 @@ FINGERPRINTS = { { 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 313: 8, 320: 3, 322: 7, 328: 1, 338: 6, 340: 6, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 393: 8, 398: 8, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 573: 1, 577: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 753: 5, 761: 7, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1225: 8, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1328: 4, 1417: 8, 1601: 8, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1919: 7, 1920: 7, 1930: 7, 2016: 8, 2024: 8 }], + CAR.ESCALADE: [ + { + 170: 8, 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 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, 381: 6, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 407: 4, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 460: 5, 462: 4, 463: 3, 479: 3, 481: 7, 485: 8, 487: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 534: 2, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 573: 1, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 719: 5, 761: 7, 801: 8, 804: 3, 810: 8, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 967: 4, 969: 8, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1017: 8, 1019: 2, 1020: 8, 1033: 7, 1034: 7, 1105: 6, 1217: 8, 1221: 5, 1223: 2, 1225: 7, 1233: 8, 1249: 8, 1257: 6, 1265: 8, 1267: 1, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 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, 1906: 7, 1907: 7, 1912: 7, 1914: 7, 1917: 7, 1918: 7, 1919: 7, 1920: 7, 1930: 7, 1937: 8, 1953: 8, 1968: 8, 2001: 8, 2017: 8, 2018: 8, 2020: 8, 2026: 8 + }], CAR.ESCALADE_ESV: [ { 309: 1, 848: 8, 849: 8, 850: 8, 851: 8, 852: 8, 853: 8, 854: 3, 1056: 6, 1057: 8, 1058: 8, 1059: 8, 1060: 8, 1061: 8, 1062: 8, 1063: 8, 1064: 8, 1065: 8, 1066: 8, 1067: 8, 1068: 8, 1120: 8, 1121: 8, 1122: 8, 1123: 8, 1124: 8, 1125: 8, 1126: 8, 1127: 8, 1128: 8, 1129: 8, 1130: 8, 1131: 8, 1132: 8, 1133: 8, 1134: 8, 1135: 8, 1136: 8, 1137: 8, 1138: 8, 1139: 8, 1140: 8, 1141: 8, 1142: 8, 1143: 8, 1146: 8, 1147: 8, 1148: 8, 1149: 8, 1150: 8, 1151: 8, 1216: 8, 1217: 8, 1218: 8, 1219: 8, 1220: 8, 1221: 8, 1222: 8, 1223: 8, 1224: 8, 1225: 8, 1226: 8, 1232: 8, 1233: 8, 1234: 8, 1235: 8, 1236: 8, 1237: 8, 1238: 8, 1239: 8, 1240: 8, 1241: 8, 1242: 8, 1787: 8, 1788: 8 diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index a4d2f55581..02e37492d3 100644 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -50,6 +50,7 @@ routes = [ CarTestRoute("7cc2a8365b4dd8a9|2018-12-02--12-10-44", GM.ACADIA), CarTestRoute("aa20e335f61ba898|2019-02-05--16-59-04", GM.BUICK_REGAL), + CarTestRoute("ef8f2185104d862e|2023-02-09--18-37-13", GM.ESCALADE), CarTestRoute("46460f0da08e621e|2021-10-26--07-21-46", GM.ESCALADE_ESV), CarTestRoute("c950e28c26b5b168|2018-05-30--22-03-41", GM.VOLT), CarTestRoute("f08912a233c1584f|2022-08-11--18-02-41", GM.BOLT_EUV, segment=1), diff --git a/selfdrive/car/torque_data/override.yaml b/selfdrive/car/torque_data/override.yaml index 52c9e8d547..cc1681bce1 100644 --- a/selfdrive/car/torque_data/override.yaml +++ b/selfdrive/car/torque_data/override.yaml @@ -26,6 +26,7 @@ COMMA BODY: [.nan, 1000, .nan] RAM 1500 5TH GEN: [2.0, 2.0, 0.0] RAM HD 5TH GEN: [1.4, 1.4, 0.0] SUBARU OUTBACK 6TH GEN: [2.3, 2.3, 0.11] +CADILLAC ESCALADE 2017: [1.899999976158142, 1.842270016670227, 0.1120000034570694] CHEVROLET BOLT EUV 2022: [2.0, 2.0, 0.05] CHEVROLET SILVERADO 1500 2020: [1.9, 1.9, 0.112] CHEVROLET EQUINOX 2019: [2.0, 2.0, 0.05] From 90ce7605c159133eaad5ffe6259da513db28e8ff Mon Sep 17 00:00:00 2001 From: Jason Wen <47793918+sunnyhaibin@users.noreply.github.com> Date: Wed, 15 Feb 2023 20:33:04 -0500 Subject: [PATCH 41/63] Hyundai: 2015-16 Genesis resume from standstill fix (#25579) * Hyundai: 2015-16 Genesis resume from standstill fix * Add comment * Fix typo * Merge both methods * Add back the comment * 20Hz not needed according to tester * no new global state variable * PCM's perspective: random counter -> random counter * only send 5 --------- Co-authored-by: Shane Smiskol --- selfdrive/car/hyundai/carcontroller.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index 516666eff1..1e6f78af20 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -169,7 +169,8 @@ class CarController: if (self.frame - self.last_button_frame) * DT_CTRL > 0.1: # send 25 messages at a time to increases the likelihood of resume being accepted can_sends.extend([hyundaican.create_clu11(self.packer, self.frame, CS.clu11, Buttons.RES_ACCEL, self.CP.carFingerprint)] * 25) - self.last_button_frame = self.frame + if (self.frame - self.last_button_frame) * DT_CTRL >= 0.15: + self.last_button_frame = self.frame if self.frame % 2 == 0 and self.CP.openpilotLongitudinalControl: # TODO: unclear if this is needed From 4638d4b1a2e1dd7ad500750e6f8d97b0e66e9e97 Mon Sep 17 00:00:00 2001 From: wowcat1234 <124840678+wowcat1234@users.noreply.github.com> Date: Wed, 15 Feb 2023 21:17:46 -0600 Subject: [PATCH 42/63] Add fingerprint for Hyundai Ioniq 22 limited HEV (#27334) * Update values.py * update for ioniq HEV 22 --------- Co-authored-by: Shane Smiskol --- selfdrive/car/hyundai/values.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 9067299473..086bd1f26b 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -483,6 +483,7 @@ FW_VERSIONS = { CAR.IONIQ_HEV_2022: { (Ecu.fwdRadar, 0x7d0, None): [ b'\xf1\x00AEhe SCC F-CUP 1.00 1.00 99110-G2600 ', + b'\xf1\x00AEhe SCC FHCUP 1.00 1.00 99110-G2600 ', ], (Ecu.eps, 0x7d4, None): [ b'\xf1\x00AE MDPS C 1.00 1.01 56310G2510\x00 4APHC101', @@ -495,6 +496,7 @@ FW_VERSIONS = { ], (Ecu.transmission, 0x7e1, None): [ b'\xf1\x816U3J9051\x00\x00\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00HAE0G16NL2\x00\x00\x00\x00', + b'\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00HAE0G16NL2\x96\xda\xd4\xee', ], }, CAR.SONATA: { From d7ddf25899ba480b11a6b9064875392b7d2f68b5 Mon Sep 17 00:00:00 2001 From: gregschueman <124465406+gregschueman@users.noreply.github.com> Date: Wed, 15 Feb 2023 22:21:36 -0500 Subject: [PATCH 43/63] 2021 Hyundai Ioniq PHEV - additional engine fingerprint added (#27221) * Update values.py Addition of Hyundai 2021 Ioniq PHEV modeled on 2019 entry * Update values.py * Update values.py * Update values.py * Update values.py * replace with shorter trans --------- Co-authored-by: Shane Smiskol --- selfdrive/car/hyundai/values.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 086bd1f26b..4a7f257092 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -437,13 +437,14 @@ FW_VERSIONS = { (Ecu.engine, 0x7e0, None): [ b'\xf1\x816H6F6051\x00\x00\x00\x00\x00\x00\x00\x00', b'\xf1\x816H6G6051\x00\x00\x00\x00\x00\x00\x00\x00', + b'\xf1\x816H6G5051\x00\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.transmission, 0x7e1, None): [ b'\xf1\x816U3J9051\000\000\xf1\0006U3H1_C2\000\0006U3J9051\000\000PAE0G16NL0\x82zT\xd2', b'\xf1\x816U3J8051\x00\x00\xf1\x006U3H1_C2\x00\x006U3J8051\x00\x00PAETG16UL0\x00\x00\x00\x00', - b'\xf1\x816U3J9051\x00\x00\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00PAE0G16NL2\xad\xeb\xabt', b'\xf1\x816U3J9051\x00\x00\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00PAE0G16NL2\x00\x00\x00\x00', b'\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00PAE0G16NL0\x00\x00\x00\x00', + b'\xf1\x006U3H1_C2\x00\x006U3J9051\x00\x00PAE0G16NL2\xad\xeb\xabt', ], }, CAR.IONIQ_EV_2020: { From 2769b110e0b0ea82f96471d964b05499441b6d73 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 15 Feb 2023 19:42:56 -0800 Subject: [PATCH 44/63] Fingerprint for Hyundai Santa Fe 2019 Europe (#26952) * Fingerpint fur Hyundai Santa Fe 2019 Europe * add version for transmission segment 092ef1cc055c6354|2023-01-05--17-49-21 * remove long --------- Co-authored-by: sevdokim --- selfdrive/car/hyundai/values.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 4a7f257092..15c239506b 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -685,12 +685,14 @@ FW_VERSIONS = { }, CAR.SANTA_FE: { (Ecu.fwdRadar, 0x7d0, None): [ + b'\xf1\x00TM__ SCC F-CUP 1.00 1.00 99110-S1210 ', b'\xf1\x00TM__ SCC F-CUP 1.00 1.01 99110-S2000 ', b'\xf1\x00TM__ SCC F-CUP 1.00 1.02 99110-S2000 ', b'\xf1\x00TM__ SCC F-CUP 1.00 1.03 99110-S2000 ', ], (Ecu.abs, 0x7d1, None): [ b'\xf1\x00TM ESC \r 100\x18\x031 58910-S2650', + b'\xf1\x00TM ESC \r 105\x19\x05# 58910-S1500', b'\xf1\x00TM ESC \r 103\x18\x11\x08 58910-S2650', b'\xf1\x00TM ESC \r 104\x19\x07\x08 58910-S2650', b'\xf1\x00TM ESC \x02 100\x18\x030 58910-S2600', @@ -709,11 +711,14 @@ FW_VERSIONS = { b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8409', b'\xf1\x00TM MDPS C 1.00 1.00 56340-S2000 8A12', b'\xf1\x00TM MDPS C 1.00 1.01 56340-S2000 9129', + b'\xf1\x00TM MDPS R 1.00 1.02 57700-S1100 4TMDP102' ], (Ecu.fwdCamera, 0x7c4, None): [ + b'\xf1\x00TM MFC AT EUR LHD 1.00 1.01 99211-S1010 181207', b'\xf1\x00TM MFC AT USA LHD 1.00 1.00 99211-S2000 180409', ], (Ecu.transmission, 0x7e1, None): [ + b'\xf1\x00bcsh8p54 U833\x00\x00\x00\x00\x00\x00TTM4V22US3_<]\xf1', b'\xf1\x006W351_C2\x00\x006W3E1051\x00\x00TTM4T20NS5\x00\x00\x00\x00', b'\xf1\x87LBJSGA7082574HG0\x87www\x98\x88\x88\x88\x99\xaa\xb9\x9afw\x86gx\x99\xa7\x89co\xf8\xffvU_\xffR\xaf\xf1\x816W3C2051\x00\x00\xf1\x006W351_C2\x00\x006W3C2051\x00\x00TTM2T20NS1\x00\xa6\xe0\x91', b'\xf1\x87LBKSGA0458404HG0vfvg\x87www\x89\x99\xa8\x99y\xaa\xa7\x9ax\x88\xa7\x88t_\xf9\xff\x86w\x8f\xff\x15x\xf1\x816W3C2051\x00\x00\xf1\x006W351_C2\x00\x006W3C2051\x00\x00TTM2T20NS1\x00\x00\x00\x00', From e6c02027d3d7c6cd850fb13b948bd010b15b5308 Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Thu, 16 Feb 2023 19:34:18 +0100 Subject: [PATCH 45/63] cabana: fix updating tabbar_ids on "Close Other Tabs" (#27362) --- tools/cabana/detailwidget.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 55ba0b9feb..bf4c1e44f8 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -103,10 +103,14 @@ void DetailWidget::showTabBarContextMenu(const QPoint &pt) { QMenu menu(this); menu.addAction(tr("Close Other Tabs")); if (menu.exec(tabbar->mapToGlobal(pt))) { + tabbar_ids.move(index, 0); tabbar->moveTab(index, 0); tabbar->setCurrentIndex(0); - while (tabbar->count() > 1) + while (tabbar->count() > 1) { + tabbar_ids.removeAt(1); tabbar->removeTab(1); + } + assert(tabbar_ids.size() == tabbar->count()); } } } From 8772306467630df66716e47ec34fa36935152bf6 Mon Sep 17 00:00:00 2001 From: Willem Melching Date: Thu, 16 Feb 2023 19:34:42 +0100 Subject: [PATCH 46/63] cabana: fix events() call in AbstractStream::updateLastMsgsTo (#27360) --- tools/cabana/streams/abstractstream.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/cabana/streams/abstractstream.cc b/tools/cabana/streams/abstractstream.cc index 5f12e0c42f..8fdfbd5c1b 100644 --- a/tools/cabana/streams/abstractstream.cc +++ b/tools/cabana/streams/abstractstream.cc @@ -62,8 +62,9 @@ void AbstractStream::updateLastMsgsTo(double sec) { last_msgs.reserve(can_msgs.size()); double route_start_time = routeStartTime(); uint64_t last_ts = (sec + route_start_time) * 1e9; - auto last = std::upper_bound(events()->rbegin(), events()->rend(), last_ts, [](uint64_t ts, auto &e) { return e->mono_time < ts; }); - for (auto it = last; it != events()->rend(); ++it) { + auto evs = events(); + auto last = std::upper_bound(evs->rbegin(), evs->rend(), last_ts, [](uint64_t ts, auto &e) { return e->mono_time < ts; }); + for (auto it = last; it != evs->rend(); ++it) { if ((*it)->which == cereal::Event::Which::CAN) { for (const auto &c : (*it)->event.getCan()) { auto &m = last_msgs[{.source = c.getSrc(), .address = c.getAddress()}]; From 2510f78126b0a457b5e8b42f1f32e5bf24a2c045 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Fri, 17 Feb 2023 06:47:36 +0800 Subject: [PATCH 47/63] cabana: add online-help (#27349) * add online helps * typo * remove duplicate 'too' * show idle message:For Help, Press F1 * improve drawHelp * fix color desc --- tools/cabana/binaryview.cc | 15 ++++++++ tools/cabana/chartswidget.cc | 5 +++ tools/cabana/detailwidget.cc | 5 +-- tools/cabana/mainwin.cc | 66 ++++++++++++++++++++++++++++++++-- tools/cabana/mainwin.h | 14 ++++++++ tools/cabana/messageswidget.cc | 9 +++++ tools/cabana/signaledit.cc | 5 +++ tools/cabana/videowidget.cc | 7 ++++ 8 files changed, 122 insertions(+), 4 deletions(-) diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 9085bf310a..20edfd06ff 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -42,6 +42,21 @@ BinaryView::BinaryView(QWidget *parent) : QTableView(parent) { QObject::connect(UndoStack::instance(), &QUndoStack::indexChanged, this, &BinaryView::refresh); addShortcuts(); + setWhatsThis(R"( + Binary View
+ + Shortcuts:
+ Delete Signal: + x , + Backspace , + Delete
+ Change endianness: e
+ Change singedness: s
+ Open chart: + c , + p , + g
+ )"); } void BinaryView::addShortcuts() { diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 9a085ec732..9c5ed097c6 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -94,6 +94,11 @@ ChartsWidget::ChartsWidget(QWidget *parent) : QWidget(parent) { docking = !docking; updateToolBar(); }); + + setWhatsThis(tr(R"( + Chart view
+ + )")); } void ChartsWidget::eventsMerged() { diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index bf4c1e44f8..95ef975dd1 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -264,11 +264,12 @@ WelcomeWidget::WelcomeWidget(QWidget *parent) : QWidget(parent) { return hlayout; }; - auto lb = new QLabel(tr("<-Select a message to to view details")); + auto lb = new QLabel(tr("<-Select a message to view details")); lb->setAlignment(Qt::AlignHCenter); main_layout->addWidget(lb); main_layout->addLayout(newShortcutRow("Pause", "Space")); - main_layout->addLayout(newShortcutRow("Help", "Alt + H")); + main_layout->addLayout(newShortcutRow("Help", "F1")); + main_layout->addLayout(newShortcutRow("WhatsThis", "Shift+F1")); main_layout->addStretch(0); setStyleSheet("QLabel{color:darkGray;}"); diff --git a/tools/cabana/mainwin.cc b/tools/cabana/mainwin.cc index bce6d313c8..07d37df4e4 100644 --- a/tools/cabana/mainwin.cc +++ b/tools/cabana/mainwin.cc @@ -9,7 +9,9 @@ #include #include #include +#include #include +#include #include #include #include @@ -20,7 +22,7 @@ static MainWindow *main_win = nullptr; void qLogMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg) { if (type == QtDebugMsg) std::cout << msg.toStdString() << std::endl; - if (main_win) emit main_win->showMessage(msg, 0); + if (main_win) emit main_win->showMessage(msg, 2000); } MainWindow::MainWindow() : QMainWindow() { @@ -43,7 +45,7 @@ MainWindow::MainWindow() : QMainWindow() { qRegisterMetaType("ReplyMsgType"); installMessageHandler([this](ReplyMsgType type, const std::string msg) { // use queued connection to recv the log messages from replay. - emit showMessage(QString::fromStdString(msg), 3000); + emit showMessage(QString::fromStdString(msg), 2000); }); installDownloadProgressHandler([this](uint64_t cur, uint64_t total, bool success) { emit updateProgressBar(cur, total, success); @@ -125,6 +127,7 @@ void MainWindow::createActions() { tools_menu->addAction(tr("Find &Similar Bits"), this, &MainWindow::findSimilarBits); QMenu *help_menu = menuBar()->addMenu(tr("&Help")); + help_menu->addAction(tr("Help"), this, &MainWindow::onlineHelp)->setShortcuts(QKeySequence::HelpContents); help_menu->addAction(tr("About &Qt"), qApp, &QApplication::aboutQt); } @@ -173,6 +176,7 @@ void MainWindow::createStatusBar() { progress_bar->setTextVisible(true); progress_bar->setFixedSize({230, 16}); progress_bar->setVisible(false); + statusBar()->addWidget(new QLabel(tr("For Help,Press F1"))); statusBar()->addPermanentWidget(progress_bar); } @@ -422,3 +426,61 @@ void MainWindow::findSimilarBits() { QObject::connect(dlg, &FindSimilarBitsDlg::openMessage, messages_widget, &MessagesWidget::selectMessage); dlg->show(); } + +void MainWindow::onlineHelp() { + if (auto help = findChild()) { + help->close(); + } else { + help = new HelpOverlay(this); + help->setGeometry(rect()); + help->show(); + help->raise(); + } +} + +// HelpOverlay +HelpOverlay::HelpOverlay(MainWindow *parent) : QWidget(parent) { + setAttribute(Qt::WA_NoSystemBackground, true); + setAttribute(Qt::WA_TranslucentBackground, true); + setAttribute(Qt::WA_DeleteOnClose); + parent->installEventFilter(this); +} + +void HelpOverlay::paintEvent(QPaintEvent *event) { + QPainter painter(this); + painter.fillRect(rect(), QColor(0, 0, 0, 50)); + MainWindow *parent = (MainWindow *)parentWidget(); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); + drawHelpForWidget(painter, parent->findChild()); +} + +void HelpOverlay::drawHelpForWidget(QPainter &painter, QWidget *w) { + if (w && w->isVisible() && !w->whatsThis().isEmpty()) { + QPoint pt = mapFromGlobal(w->mapToGlobal(w->rect().center())); + if (rect().contains(pt)) { + QTextDocument document; + document.setHtml(w->whatsThis()); + QSize doc_size = document.size().toSize(); + QPoint topleft = {pt.x() - doc_size.width() / 2, pt.y() - doc_size.height() / 2}; + painter.translate(topleft); + painter.fillRect(QRect{{0, 0}, doc_size}, palette().toolTipBase()); + document.drawContents(&painter); + painter.translate(-topleft); + } + } +} + +bool HelpOverlay::eventFilter(QObject *obj, QEvent *event) { + if (obj == parentWidget() && event->type() == QEvent::Resize) { + QResizeEvent *resize_event = (QResizeEvent *)(event); + setGeometry(QRect{QPoint(0, 0), resize_event->size()}); + } + return false; +} + +void HelpOverlay::mouseReleaseEvent(QMouseEvent *event) { + close(); +} diff --git a/tools/cabana/mainwin.h b/tools/cabana/mainwin.h index 5e627df58b..e7a39adab7 100644 --- a/tools/cabana/mainwin.h +++ b/tools/cabana/mainwin.h @@ -54,6 +54,7 @@ protected: void setOption(); void findSimilarBits(); void undoStackCleanChanged(bool clean); + void onlineHelp(); VideoWidget *video_widget = nullptr; QDockWidget *video_dock; @@ -69,4 +70,17 @@ protected: enum { MAX_RECENT_FILES = 15 }; QAction *recent_files_acts[MAX_RECENT_FILES] = {}; QMenu *open_recent_menu = nullptr; + friend class OnlineHelp; +}; + +class HelpOverlay : public QWidget { + Q_OBJECT +public: + HelpOverlay(MainWindow *parent); + +protected: + void drawHelpForWidget(QPainter &painter, QWidget *w); + void paintEvent(QPaintEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; + bool eventFilter(QObject *obj, QEvent *event) override; }; diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 4f6bb92375..1cf85ed740 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -65,6 +65,15 @@ MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { }); updateSuppressedButtons(); + + setWhatsThis(tr(R"( + Message View
+ + Byte color:
+ ■ constant changing
+ ■ increasing
+ ■ decreasing
+ )")); } void MessagesWidget::selectMessage(const MessageId &msg_id) { diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index 98dd39204f..e2be5c85d0 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -365,6 +365,11 @@ SignalView::SignalView(ChartsWidget *charts, QWidget *parent) : charts(charts), QObject::connect(model, &QAbstractItemModel::rowsInserted, this, &SignalView::rowsChanged); QObject::connect(model, &QAbstractItemModel::rowsRemoved, this, &SignalView::rowsChanged); QObject::connect(dbc(), &DBCManager::signalAdded, [this](uint32_t address, const Signal *sig) { expandSignal(sig); }); + + setWhatsThis(tr(R"( + Signal view
+ + )")); } void SignalView::setMessage(const MessageId &id) { diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index cd3dc0b516..f77f7c306d 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -53,6 +53,13 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) { QObject::connect(can, &AbstractStream::paused, this, &VideoWidget::updatePlayBtnState); QObject::connect(can, &AbstractStream::resume, this, &VideoWidget::updatePlayBtnState); updatePlayBtnState(); + + setWhatsThis(tr(R"( + Video
+ + Shortcuts:
+ Pause/Resume: space
+ )")); } QWidget *VideoWidget::createCameraWidget() { From 202eb06a05e43ce77e5be19540fb427b5a060cfc Mon Sep 17 00:00:00 2001 From: grekiki <96022003+GregorKikelj@users.noreply.github.com> Date: Thu, 16 Feb 2023 23:51:25 +0100 Subject: [PATCH 48/63] Carla simulator: set driver orientation (#27363) --- tools/sim/bridge.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/sim/bridge.py b/tools/sim/bridge.py index f0694078e2..7bb12badb2 100755 --- a/tools/sim/bridge.py +++ b/tools/sim/bridge.py @@ -211,7 +211,10 @@ def fake_driver_monitoring(exit_event: threading.Event): while not exit_event.is_set(): # dmonitoringmodeld output dat = messaging.new_message('driverStateV2') + dat.driverStateV2.leftDriverData.faceOrientation = [0., 0., 0.] dat.driverStateV2.leftDriverData.faceProb = 1.0 + dat.driverStateV2.rightDriverData.faceOrientation = [0., 0., 0.] + dat.driverStateV2.rightDriverData.faceProb = 1.0 pm.send('driverStateV2', dat) # dmonitoringd output From 5e0b28111902f9d8565a5bae50369185ad1cbe01 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 16 Feb 2023 16:09:11 -0800 Subject: [PATCH 49/63] HKG: log AEB/FCW for Kia Ceed (#27364) Ceed uses FCA --- selfdrive/car/hyundai/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 15c239506b..422431a718 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -1660,7 +1660,7 @@ FEATURES = { "use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022, CAR.KIA_K5_HEV_2020}, # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 - "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, + "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.KIA_CEED, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, } CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_4TH_GEN, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN, CAR.KIA_SORENTO_PHEV_4TH_GEN, CAR.GENESIS_GV60_EV_1ST_GEN, CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_NIRO_HEV_2ND_GEN} From 37adf5d3a681daac2542270a24897ae00d42e4b8 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Fri, 17 Feb 2023 10:53:12 +0800 Subject: [PATCH 50/63] cabana: simplify conversions between QVariant and QVector (#27367) --- tools/cabana/historylog.cc | 2 +- tools/cabana/messageswidget.cc | 16 +++++++--------- tools/cabana/util.cc | 25 ++++++------------------- tools/cabana/util.h | 1 - 4 files changed, 14 insertions(+), 30 deletions(-) diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index f7f02b06d8..87968d495c 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -17,7 +17,7 @@ QVariant HistoryLogModel::data(const QModelIndex &index, int role) const { } return show_signals ? QString::number(m.sig_values[index.column() - 1]) : toHex(m.data); } else if (role == Qt::UserRole && index.column() == 1 && !show_signals) { - return ChangeTracker::toVariantList(m.colors); + return QVariant::fromValue(m.colors); } return {}; } diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 1cf85ed740..81ebc6af20 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -121,17 +121,15 @@ QVariant MessageListModel::data(const QModelIndex &index, int role) const { case 4: return toHex(can_data.dat); } } else if (role == Qt::UserRole && index.column() == 4) { - QList colors; - colors.reserve(can_data.dat.size()); - for (int i = 0; i < can_data.dat.size(); i++){ - if (suppressed_bytes.contains({id, i})) { - colors.append(QColor(255, 255, 255, 0)); - } else { - colors.append(i < can_data.colors.size() ? can_data.colors[i] : QColor(255, 255, 255, 0)); + QVector colors = can_data.colors; + if (!suppressed_bytes.empty()) { + for (int i = 0; i < colors.size(); i++) { + if (suppressed_bytes.contains({id, i})) { + colors[i] = QColor(255, 255, 255, 0); + } } } - return colors; - + return QVariant::fromValue(colors); } return {}; } diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index 454dd29b87..9843a3f00c 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -66,13 +66,6 @@ void ChangeTracker::clear() { colors.clear(); } -QList ChangeTracker::toVariantList(const QVector &colors) { - QList ret; - ret.reserve(colors.size()); - for (auto &c : colors) ret.append(c); - return ret; -} - // MessageBytesDelegate MessageBytesDelegate::MessageBytesDelegate(QObject *parent) : QStyledItemDelegate(parent) { @@ -89,12 +82,8 @@ void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem & return; } - if ((option.state & QStyle::State_Selected) && (option.state & QStyle::State_Active)) { - painter->setPen(option.palette.color(QPalette::HighlightedText)); - } else { - painter->setPen(option.palette.color(QPalette::Text)); - } - + auto color_role = option.state & QStyle::State_Selected ? QPalette::HighlightedText: QPalette::Text; + painter->setPen(option.palette.color(color_role)); painter->setFont(fixed_font); QRect space = painter->boundingRect(opt.rect, opt.displayAlignment, " "); QRect pos = painter->boundingRect(opt.rect, opt.displayAlignment, "00"); @@ -103,15 +92,13 @@ void MessageBytesDelegate::paint(QPainter *painter, const QStyleOptionViewItem & int m = space.width() / 2; const QMargins margins(m, m, m, m); - QList colors = index.data(Qt::UserRole).toList(); - int i = 0; - for (auto &byte : byte_list) { + auto colors = index.data(Qt::UserRole).value>(); + for (int i = 0; i < byte_list.size(); ++i) { if (i < colors.size()) { - painter->fillRect(pos.marginsAdded(margins), colors[i].value()); + painter->fillRect(pos.marginsAdded(margins), colors[i]); } - painter->drawText(pos, opt.displayAlignment, byte); + painter->drawText(pos, opt.displayAlignment, byte_list[i]); pos.moveLeft(pos.right() + space.width()); - i++; } } diff --git a/tools/cabana/util.h b/tools/cabana/util.h index 8ec4cda90c..eb5203fb0b 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -14,7 +14,6 @@ class ChangeTracker { public: void compute(const QByteArray &dat, double ts, uint32_t freq); - static QList toVariantList(const QVector &colors); void clear(); QVector last_change_t; From b2453d55c12e4e6e8e5115ef7c8daf0f60205fdb Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Thu, 16 Feb 2023 21:52:32 -0800 Subject: [PATCH 51/63] Hyundai: detect FCA feature (#27322) * detect fca * use value * it will be from camera on camera acc cars * Update ref_commit --- selfdrive/car/hyundai/carstate.py | 8 ++++---- selfdrive/car/hyundai/interface.py | 4 ++++ selfdrive/car/hyundai/values.py | 4 +--- selfdrive/test/process_replay/ref_commit | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/selfdrive/car/hyundai/carstate.py b/selfdrive/car/hyundai/carstate.py index 0bab188790..22934c05b2 100644 --- a/selfdrive/car/hyundai/carstate.py +++ b/selfdrive/car/hyundai/carstate.py @@ -135,8 +135,8 @@ class CarState(CarStateBase): ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear)) if not self.CP.openpilotLongitudinalControl: - aeb_src = "FCA11" if self.CP.carFingerprint in FEATURES["use_fca"] else "SCC12" - aeb_sig = "FCA_CmdAct" if self.CP.carFingerprint in FEATURES["use_fca"] else "AEB_CmdAct" + aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12" + aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct" aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0 aeb_braking = cp_cruise.vl[aeb_src]["CF_VSM_DecCmdAct"] != 0 or cp_cruise.vl[aeb_src][aeb_sig] != 0 ret.stockFcw = aeb_warning and not aeb_braking @@ -317,7 +317,7 @@ class CarState(CarStateBase): ("SCC12", 50), ] - if CP.carFingerprint in FEATURES["use_fca"]: + if CP.flags & HyundaiFlags.USE_FCA.value: signals += [ ("FCA_CmdAct", "FCA11"), ("CF_VSM_Warn", "FCA11"), @@ -408,7 +408,7 @@ class CarState(CarStateBase): ("SCC12", 50), ] - if CP.carFingerprint in FEATURES["use_fca"]: + if CP.flags & HyundaiFlags.USE_FCA.value: signals += [ ("FCA_CmdAct", "FCA11"), ("CF_VSM_Warn", "FCA11"), diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index ae0f26274c..d2cc5b4ec0 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -48,6 +48,10 @@ class CarInterface(CarInterfaceBase): if 0x485 in fingerprint[2]: ret.flags |= HyundaiFlags.SEND_LFA.value + # These cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 + if 0x38d in fingerprint[0] or 0x38d in fingerprint[2]: + ret.flags |= HyundaiFlags.USE_FCA.value + ret.steerActuatorDelay = 0.1 # Default delay ret.steerLimitTimer = 0.4 tire_stiffness_factor = 1. diff --git a/selfdrive/car/hyundai/values.py b/selfdrive/car/hyundai/values.py index 422431a718..d0a4e4dd1a 100644 --- a/selfdrive/car/hyundai/values.py +++ b/selfdrive/car/hyundai/values.py @@ -61,6 +61,7 @@ class HyundaiFlags(IntFlag): ENABLE_BLINKERS = 32 CANFD_ALT_GEARS_2 = 64 SEND_LFA = 128 + USE_FCA = 256 class CAR: @@ -1658,9 +1659,6 @@ FEATURES = { "use_cluster_gears": {CAR.ELANTRA, CAR.KONA}, "use_tcu_gears": {CAR.KIA_OPTIMA_G4, CAR.KIA_OPTIMA_G4_FL, CAR.SONATA_LF, CAR.VELOSTER, CAR.TUCSON}, "use_elect_gears": {CAR.KIA_NIRO_EV, CAR.KIA_NIRO_PHEV, CAR.KIA_NIRO_HEV_2021, CAR.KIA_OPTIMA_H, CAR.IONIQ_EV_LTD, CAR.KONA_EV, CAR.IONIQ, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.ELANTRA_HEV_2021, CAR.SONATA_HYBRID, CAR.KONA_HEV, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.IONIQ_PHEV_2019, CAR.KONA_EV_2022, CAR.KIA_K5_HEV_2020}, - - # these cars use the FCA11 message for the AEB and FCW signals, all others use SCC12 - "use_fca": {CAR.SONATA, CAR.SONATA_HYBRID, CAR.ELANTRA, CAR.ELANTRA_2021, CAR.ELANTRA_HEV_2021, CAR.KIA_STINGER, CAR.KIA_CEED, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.KONA_EV, CAR.KIA_FORTE, CAR.KIA_NIRO_EV, CAR.KIA_NIRO_HEV_2021, CAR.PALISADE, CAR.GENESIS_G70, CAR.GENESIS_G70_2020, CAR.KONA, CAR.SANTA_FE, CAR.KIA_SELTOS, CAR.KONA_HEV, CAR.SANTA_FE_2022, CAR.KIA_K5_2021, CAR.IONIQ_HEV_2022, CAR.SANTA_FE_HEV_2022, CAR.SANTA_FE_PHEV_2022, CAR.TUCSON, CAR.KONA_EV_2022, CAR.KIA_STINGER_2022, CAR.KIA_K5_HEV_2020, CAR.KIA_OPTIMA_G4_FL}, } CANFD_CAR = {CAR.KIA_EV6, CAR.IONIQ_5, CAR.TUCSON_4TH_GEN, CAR.TUCSON_HYBRID_4TH_GEN, CAR.KIA_SPORTAGE_HYBRID_5TH_GEN, CAR.SANTA_CRUZ_1ST_GEN, CAR.KIA_SPORTAGE_5TH_GEN, CAR.GENESIS_GV70_1ST_GEN, CAR.KIA_SORENTO_PHEV_4TH_GEN, CAR.GENESIS_GV60_EV_1ST_GEN, CAR.KIA_SORENTO_4TH_GEN, CAR.KIA_NIRO_HEV_2ND_GEN} diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index b151a6a5ae..6884eb4660 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -fbb99ee7dc0336062e6785814af82e359dcdd9bf +8883c476d5abc12b4b2949e04c6d7c0cd7c8b9fa From 524f7079a9a51631bef042f28bfc339ecdf6d7d3 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 18 Feb 2023 02:35:50 +0800 Subject: [PATCH 52/63] cabana: add description for timeline color in help (#27375) --- tools/cabana/videowidget.cc | 41 +++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/tools/cabana/videowidget.cc b/tools/cabana/videowidget.cc index f77f7c306d..2b5374d85f 100644 --- a/tools/cabana/videowidget.cc +++ b/tools/cabana/videowidget.cc @@ -13,6 +13,15 @@ #include #include +static const QColor timeline_colors[] = { + [(int)TimelineType::None] = QColor(111, 143, 175), + [(int)TimelineType::Engaged] = QColor(0, 163, 108), + [(int)TimelineType::UserFlag] = Qt::magenta, + [(int)TimelineType::AlertInfo] = Qt::green, + [(int)TimelineType::AlertWarning] = QColor(255, 195, 0), + [(int)TimelineType::AlertCritical] = QColor(199, 0, 57), +}; + inline QString formatTime(int seconds) { return QDateTime::fromTime_t(seconds).toString(seconds > 60 * 60 ? "hh:mm:ss" : "mm:ss"); } @@ -57,9 +66,23 @@ VideoWidget::VideoWidget(QWidget *parent) : QWidget(parent) { setWhatsThis(tr(R"( Video
- Shortcuts:
- Pause/Resume: space
- )")); + Timeline color + + + + + + + +
■ Disengaged ■ Engaged
■ User Flag ■ Info
■ Warning ■ Critical
+ Shortcuts
+ Pause/Resume:  space  + )").arg(timeline_colors[(int)TimelineType::None].name(), + timeline_colors[(int)TimelineType::Engaged].name(), + timeline_colors[(int)TimelineType::UserFlag].name(), + timeline_colors[(int)TimelineType::AlertInfo].name(), + timeline_colors[(int)TimelineType::AlertWarning].name(), + timeline_colors[(int)TimelineType::AlertCritical].name())); } QWidget *VideoWidget::createCameraWidget() { @@ -212,17 +235,9 @@ void Slider::sliderChange(QAbstractSlider::SliderChange change) { } void Slider::paintEvent(QPaintEvent *ev) { - static const QColor colors[] = { - [(int)TimelineType::None] = QColor(111, 143, 175), - [(int)TimelineType::Engaged] = QColor(0, 163, 108), - [(int)TimelineType::UserFlag] = Qt::white, - [(int)TimelineType::AlertInfo] = Qt::green, - [(int)TimelineType::AlertWarning] = QColor(255, 195, 0), - [(int)TimelineType::AlertCritical] = QColor(199, 0, 57)}; - QPainter p(this); QRect r = rect().adjusted(0, 4, 0, -4); - p.fillRect(r, colors[(int)TimelineType::None]); + p.fillRect(r, timeline_colors[(int)TimelineType::None]); double min = minimum() / 1000.0; double max = maximum() / 1000.0; for (auto [begin, end, type] : timeline) { @@ -230,7 +245,7 @@ void Slider::paintEvent(QPaintEvent *ev) { continue; r.setLeft(((std::max(min, (double)begin) - min) / (max - min)) * width()); r.setRight(((std::min(max, (double)end) - min) / (max - min)) * width()); - p.fillRect(r, colors[(int)type]); + p.fillRect(r, timeline_colors[(int)type]); } QStyleOptionSlider opt; From 2c5e55ccdca597857208fc2fbb6bbc58972dbc4b Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 18 Feb 2023 02:53:47 +0800 Subject: [PATCH 53/63] cabana: attach messageid to tabdata (#27368) --- tools/cabana/detailwidget.cc | 20 +++++++++----------- tools/cabana/detailwidget.h | 1 - 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index 95ef975dd1..f290b3b706 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -86,13 +86,11 @@ DetailWidget::DetailWidget(ChartsWidget *charts, QWidget *parent) : charts(chart QObject::connect(tabbar, &QTabBar::customContextMenuRequested, this, &DetailWidget::showTabBarContextMenu); QObject::connect(tabbar, &QTabBar::currentChanged, [this](int index) { if (index != -1) { - setMessage(tabbar_ids[index]); + setMessage(tabbar->tabData(index).value()); } }); QObject::connect(tabbar, &QTabBar::tabCloseRequested, [this](int index) { - tabbar_ids.removeAt(index); tabbar->removeTab(index); - assert(tabbar_ids.size() == tabbar->count()); }); QObject::connect(charts, &ChartsWidget::seriesChanged, signal_view, &SignalView::updateChartState); } @@ -103,14 +101,11 @@ void DetailWidget::showTabBarContextMenu(const QPoint &pt) { QMenu menu(this); menu.addAction(tr("Close Other Tabs")); if (menu.exec(tabbar->mapToGlobal(pt))) { - tabbar_ids.move(index, 0); tabbar->moveTab(index, 0); tabbar->setCurrentIndex(0); while (tabbar->count() > 1) { - tabbar_ids.removeAt(1); tabbar->removeTab(1); } - assert(tabbar_ids.size() == tabbar->count()); } } } @@ -121,21 +116,25 @@ void DetailWidget::removeAll() { while (tabbar->count() > 0) { tabbar->removeTab(0); } - tabbar_ids.clear(); tabbar->blockSignals(false); stacked_layout->setCurrentIndex(0); } void DetailWidget::setMessage(const MessageId &message_id) { msg_id = message_id; - int index = tabbar_ids.indexOf(*msg_id); + tabbar->blockSignals(true); + int index = tabbar->count() - 1; + for (/**/; index >= 0; --index) { + if (tabbar->tabData(index).value() == message_id) break; + } if (index == -1) { - tabbar_ids.append(*msg_id); index = tabbar->addTab(message_id.toString()); + tabbar->setTabData(index, QVariant::fromValue(message_id)); tabbar->setTabToolTip(index, msgName(message_id)); } - assert(tabbar->count() == tabbar_ids.size()); + tabbar->setCurrentIndex(index); + tabbar->blockSignals(false); setUpdatesEnabled(false); @@ -144,7 +143,6 @@ void DetailWidget::setMessage(const MessageId &message_id) { history_log->setMessage(*msg_id); stacked_layout->setCurrentIndex(1); - tabbar->setCurrentIndex(index); refresh(); splitter->setSizes({1, 2}); diff --git a/tools/cabana/detailwidget.h b/tools/cabana/detailwidget.h index 949a8c9b8d..b3e353d539 100644 --- a/tools/cabana/detailwidget.h +++ b/tools/cabana/detailwidget.h @@ -50,7 +50,6 @@ private: ElidedLabel *name_label; QWidget *warning_widget; QTabBar *tabbar; - QList tabbar_ids; QTabWidget *tab_widget; QAction *remove_msg_act; LogsWidget *history_log; From 89f68bf0cbf53a81b0553d3816fdbe522f941fa1 Mon Sep 17 00:00:00 2001 From: martinl Date: Fri, 17 Feb 2023 21:08:41 +0200 Subject: [PATCH 54/63] cleanup: remove nonexisting third_party includes (#27372) --- SConstruct | 4 ---- 1 file changed, 4 deletions(-) diff --git a/SConstruct b/SConstruct index 31aa6ecced..007931b7f5 100644 --- a/SConstruct +++ b/SConstruct @@ -197,10 +197,6 @@ env = Environment( "#third_party/libyuv/include", "#third_party/json11", "#third_party/curl/include", - "#third_party/libgralloc/include", - "#third_party/android_frameworks_native/include", - "#third_party/android_hardware_libhardware/include", - "#third_party/android_system_core/include", "#third_party/linux/include", "#third_party/snpe/include", "#third_party/mapbox-gl-native-qt/include", From b9a01752fc88e12eb3375aca1492d0cedae17946 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 17 Feb 2023 14:13:22 -0800 Subject: [PATCH 55/63] bump version to 0.9.2 --- RELEASES.md | 4 ++++ common/version.h | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index 78d2e3b74b..ff5b686e0c 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,7 @@ +Version 0.9.2 (2023-03-XX) +======================== + + Version 0.9.1 (2023-02-23) ======================== * New driving model diff --git a/common/version.h b/common/version.h index 7b5764785a..5637029cf4 100644 --- a/common/version.h +++ b/common/version.h @@ -1 +1 @@ -#define COMMA_VERSION "0.9.1" +#define COMMA_VERSION "0.9.2" From dad948983a7ff26ffc073c536bd1e99b5d826cec Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Fri, 17 Feb 2023 15:04:21 -0800 Subject: [PATCH 56/63] chyrsler: add comment about radar parsing --- selfdrive/car/chrysler/interface.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 961684f398..303f563c90 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -12,6 +12,7 @@ class CarInterface(CarInterfaceBase): ret.carName = "chrysler" ret.dashcamOnly = candidate in RAM_HD + # radar parsing needs some work, see https://github.com/commaai/openpilot/issues/26842 ret.radarUnavailable = True # DBC[candidate]['radar'] is None ret.steerActuatorDelay = 0.1 ret.steerLimitTimer = 0.4 From 04fe6c4ec72dfcf89456a484d03f85502c237701 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Fri, 17 Feb 2023 15:28:26 -0800 Subject: [PATCH 57/63] Expand lateral MPC to 10s (#27343) * 10s lat * Full length MPC * redfine N * Leave controls the same for now * Updates * use long plan in lat plan * interp plan * add new interp * simplergit add selfdrive/controls/plannerd.py selfdrive/controls/ * expand to 10s * revert this * fix linter * Update sconscripts * fix test * fix test * fix test * Revert "Update sconscripts" This reverts commit 6e23c69dcebd5ed003e37e01921f6af7c31de0db. * Dont import drive helpers * better compile deps * fix compile * comment * update replay * Update plannerd time --- selfdrive/controls/lib/drive_helpers.py | 2 -- .../controls/lib/lateral_mpc_lib/SConscript | 1 + .../controls/lib/lateral_mpc_lib/lat_mpc.py | 10 ++++----- selfdrive/controls/lib/lateral_planner.py | 21 +++++++++++-------- .../lib/longitudinal_mpc_lib/SConscript | 1 + .../lib/longitudinal_mpc_lib/long_mpc.py | 1 + selfdrive/controls/tests/test_lateral_mpc.py | 3 ++- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/test/test_onroad.py | 2 +- 9 files changed, 24 insertions(+), 19 deletions(-) diff --git a/selfdrive/controls/lib/drive_helpers.py b/selfdrive/controls/lib/drive_helpers.py index a332d06765..05c3897335 100644 --- a/selfdrive/controls/lib/drive_helpers.py +++ b/selfdrive/controls/lib/drive_helpers.py @@ -17,8 +17,6 @@ V_CRUISE_INITIAL_EXPERIMENTAL_MODE = 105 IMPERIAL_INCREMENT = 1.6 # should be CV.MPH_TO_KPH, but this causes rounding errors MIN_SPEED = 1.0 -LAT_MPC_N = 16 -LON_MPC_N = 32 CONTROL_N = 17 CAR_ROTATION_RADIUS = 0.0 diff --git a/selfdrive/controls/lib/lateral_mpc_lib/SConscript b/selfdrive/controls/lib/lateral_mpc_lib/SConscript index 868b5a873c..745ed99d10 100644 --- a/selfdrive/controls/lib/lateral_mpc_lib/SConscript +++ b/selfdrive/controls/lib/lateral_mpc_lib/SConscript @@ -47,6 +47,7 @@ acados_dir = '#third_party/acados' acados_templates_dir = '#third_party/acados/acados_template/c_templates_tera' source_list = ['lat_mpc.py', + '#/selfdrive/modeld/constants.py', f'{acados_dir}/include/acados_c/ocp_nlp_interface.h', f'{acados_dir}/x86_64/lib/libacados.so', f'{acados_dir}/larch64/lib/libacados.so', diff --git a/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py b/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py index 536f436fce..ca7b991e69 100755 --- a/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py +++ b/selfdrive/controls/lib/lateral_mpc_lib/lat_mpc.py @@ -3,8 +3,8 @@ import os import numpy as np from casadi import SX, vertcat, sin, cos - from common.realtime import sec_since_boot +# WARNING: imports outside of constants will not trigger a rebuild from selfdrive.modeld.constants import T_IDXS if __name__ == '__main__': # generating code @@ -17,12 +17,12 @@ EXPORT_DIR = os.path.join(LAT_MPC_DIR, "c_generated_code") JSON_FILE = os.path.join(LAT_MPC_DIR, "acados_ocp_lat.json") X_DIM = 4 P_DIM = 2 -N = 16 COST_E_DIM = 3 COST_DIM = COST_E_DIM + 2 SPEED_OFFSET = 10.0 MODEL_NAME = 'lat' ACADOS_SOLVER_TYPE = 'SQP_RTI' +N = 32 def gen_lat_model(): model = AcadosModel() @@ -168,14 +168,14 @@ class LateralMpc(): self.solver.constraints_set(0, "lbx", x0_cp) self.solver.constraints_set(0, "ubx", x0_cp) self.yref[:,0] = y_pts - v_ego = p_cp[0] + v_ego = p_cp[0, 0] # rotation_radius = p_cp[1] self.yref[:,1] = heading_pts * (v_ego + SPEED_OFFSET) self.yref[:,2] = yaw_rate_pts * (v_ego + SPEED_OFFSET) for i in range(N): self.solver.cost_set(i, "yref", self.yref[i]) - self.solver.set(i, "p", p_cp) - self.solver.set(N, "p", p_cp) + self.solver.set(i, "p", p_cp[i]) + self.solver.set(N, "p", p_cp[N]) self.solver.cost_set(N, "yref", self.yref[N][:COST_E_DIM]) t = sec_since_boot() diff --git a/selfdrive/controls/lib/lateral_planner.py b/selfdrive/controls/lib/lateral_planner.py index 932ad49535..7230b5ad14 100644 --- a/selfdrive/controls/lib/lateral_planner.py +++ b/selfdrive/controls/lib/lateral_planner.py @@ -16,12 +16,12 @@ CAMERA_OFFSET = 0.04 PATH_COST = 1.0 LATERAL_MOTION_COST = 0.11 LATERAL_ACCEL_COST = 0.0 -LATERAL_JERK_COST = 0.05 +LATERAL_JERK_COST = 0.04 # Extreme steering rate is unpleasant, even # when it does not cause bad jerk. # TODO this cost should be lowered when low # speed lateral control is stable on all cars -STEERING_RATE_COST = 800.0 +STEERING_RATE_COST = 700.0 class LateralPlanner: @@ -35,6 +35,7 @@ class LateralPlanner: self.solution_invalid_cnt = 0 self.path_xyz = np.zeros((TRAJECTORY_SIZE, 3)) + self.velocity_xyz = np.zeros((TRAJECTORY_SIZE, 3)) self.plan_yaw = np.zeros((TRAJECTORY_SIZE,)) self.plan_yaw_rate = np.zeros((TRAJECTORY_SIZE,)) self.t_idxs = np.arange(TRAJECTORY_SIZE) @@ -49,7 +50,6 @@ class LateralPlanner: def update(self, sm): # clip speed , lateral planning is not possible at 0 speed - self.v_ego = max(MIN_SPEED, sm['carState'].vEgo) measured_curvature = sm['controlsState'].curvature # Parse model predictions @@ -59,6 +59,10 @@ class LateralPlanner: self.t_idxs = np.array(md.position.t) self.plan_yaw = np.array(md.orientation.z) self.plan_yaw_rate = np.array(md.orientationRate.z) + self.velocity_xyz = np.column_stack([md.velocity.x, md.velocity.y, md.velocity.z]) + car_speed = np.linalg.norm(self.velocity_xyz, axis=1) + self.v_plan = np.clip(car_speed, MIN_SPEED, np.inf) + self.v_ego = self.v_plan[0] # Lane change logic desire_state = md.meta.desireState @@ -68,21 +72,20 @@ class LateralPlanner: lane_change_prob = self.l_lane_change_prob + self.r_lane_change_prob self.DH.update(sm['carState'], sm['carControl'].latActive, lane_change_prob) - d_path_xyz = self.path_xyz self.lat_mpc.set_weights(PATH_COST, LATERAL_MOTION_COST, LATERAL_ACCEL_COST, LATERAL_JERK_COST, STEERING_RATE_COST) - y_pts = np.interp(self.v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(d_path_xyz, axis=1), d_path_xyz[:, 1]) - heading_pts = np.interp(self.v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(self.path_xyz, axis=1), self.plan_yaw) - yaw_rate_pts = np.interp(self.v_ego * self.t_idxs[:LAT_MPC_N + 1], np.linalg.norm(self.path_xyz, axis=1), self.plan_yaw_rate) + y_pts = self.path_xyz[:LAT_MPC_N+1, 1] + heading_pts = self.plan_yaw[:LAT_MPC_N+1] + yaw_rate_pts = self.plan_yaw_rate[:LAT_MPC_N+1] self.y_pts = y_pts assert len(y_pts) == LAT_MPC_N + 1 assert len(heading_pts) == LAT_MPC_N + 1 assert len(yaw_rate_pts) == LAT_MPC_N + 1 - lateral_factor = max(0, self.factor1 - (self.factor2 * self.v_ego**2)) - p = np.array([self.v_ego, lateral_factor]) + lateral_factor = np.clip(self.factor1 - (self.factor2 * self.v_plan**2), 0.0, np.inf) + p = np.column_stack([self.v_plan, lateral_factor]) self.lat_mpc.run(self.x0, p, y_pts, diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript index e5b2360607..7f5daf157c 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript @@ -54,6 +54,7 @@ acados_dir = '#third_party/acados' acados_templates_dir = '#third_party/acados/acados_template/c_templates_tera' source_list = ['long_mpc.py', + '#/selfdrive/modeld/constants.py', f'{acados_dir}/include/acados_c/ocp_nlp_interface.h', f'{acados_dir}/x86_64/lib/libacados.so', f'{acados_dir}/larch64/lib/libacados.so', diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py index c017951232..660002691a 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/long_mpc.py @@ -5,6 +5,7 @@ import numpy as np from common.realtime import sec_since_boot from common.numpy_fast import clip from system.swaglog import cloudlog +# WARNING: imports outside of constants will not trigger a rebuild from selfdrive.modeld.constants import index_function from selfdrive.controls.lib.radar_helpers import _LEAD_ACCEL_TAU diff --git a/selfdrive/controls/tests/test_lateral_mpc.py b/selfdrive/controls/tests/test_lateral_mpc.py index df5154b2b4..b569da09b4 100644 --- a/selfdrive/controls/tests/test_lateral_mpc.py +++ b/selfdrive/controls/tests/test_lateral_mpc.py @@ -17,7 +17,8 @@ def run_mpc(lat_mpc=None, v_ref=30., x_init=0., y_init=0., psi_init=0., curvatur curv_rate_pts = np.zeros(LAT_MPC_N + 1) x0 = np.array([x_init, y_init, psi_init, curvature_init]) - p = np.array([v_ref, CAR_ROTATION_RADIUS]) + p = np.column_stack([v_ref * np.ones(LAT_MPC_N + 1), + CAR_ROTATION_RADIUS * np.ones(LAT_MPC_N + 1)]) # converge in no more than 10 iterations for _ in range(10): diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 6884eb4660..4a670b11ff 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -8883c476d5abc12b4b2949e04c6d7c0cd7c8b9fa +086896986a3fcdb1a03d9afd00a9abc928f9ef25 diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index 4021e27de3..84511771f7 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -26,7 +26,7 @@ PROCS = { "./encoderd": 17.0, "./camerad": 14.5, "./locationd": 9.1, - "selfdrive.controls.plannerd": 11.7, + "selfdrive.controls.plannerd": 16.5, "./_ui": 19.2, "selfdrive.locationd.paramsd": 9.0, "./_sensord": 12.0, From b6fd39856c2862132f00ca48269f2e851cda62f3 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Fri, 17 Feb 2023 18:39:27 -0800 Subject: [PATCH 58/63] HKG: simplify Ioniq car params (#27371) * move PHEV to other ioniqs * reverse if * order * order --- selfdrive/car/hyundai/interface.py | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index d2cc5b4ec0..2a909b6e2e 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -103,18 +103,13 @@ class CarInterface(CarInterfaceBase): ret.wheelbase = 2.6 ret.steerRatio = 13.42 # Spec tire_stiffness_factor = 0.385 - elif candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.IONIQ_HEV_2022): + elif candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV_2019, CAR.IONIQ_HEV_2022, CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV): ret.mass = 1490. + STD_CARGO_KG # weight per hyundai site https://www.hyundaiusa.com/ioniq-electric/specifications.aspx ret.wheelbase = 2.7 ret.steerRatio = 13.73 # Spec tire_stiffness_factor = 0.385 - if candidate not in (CAR.IONIQ_EV_2020, CAR.IONIQ_PHEV, CAR.IONIQ_HEV_2022): + if candidate in (CAR.IONIQ, CAR.IONIQ_EV_LTD, CAR.IONIQ_PHEV_2019): ret.minSteerSpeed = 32 * CV.MPH_TO_MS - elif candidate == CAR.IONIQ_PHEV_2019: - ret.mass = 1550. + STD_CARGO_KG # weight per hyundai site https://www.hyundaiusa.com/us/en/vehicles/2019-ioniq-plug-in-hybrid/compare-specs - ret.wheelbase = 2.7 - ret.steerRatio = 13.73 - ret.minSteerSpeed = 32 * CV.MPH_TO_MS elif candidate == CAR.VELOSTER: ret.mass = 3558. * CV.LB_TO_KG ret.wheelbase = 2.80 From 7330466dffe4b1142c64d99d328654e7109e8073 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Sat, 18 Feb 2023 03:12:15 +0000 Subject: [PATCH 59/63] Ford Escape PHEV 2022 Fingerprint (#27382) * Ford Escape PHEV 2022 Fingerprint 6cffc47c251aa36c|2023-02-17--18-17-14 VIN: 1FMCU0EZ0NUB76728 * include MY2022 in car info * Update selfdrive/car/ford/values.py Co-authored-by: Shane Smiskol --------- Co-authored-by: koffee-bean Co-authored-by: Shane Smiskol --- selfdrive/car/ford/values.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 526b74b16c..24415c74be 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -72,7 +72,8 @@ class FordCarInfo(CarInfo): CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { CAR.BRONCO_SPORT_MK1: FordCarInfo("Ford Bronco Sport 2021-22"), CAR.ESCAPE_MK4: [ - FordCarInfo("Ford Escape 2020-21"), + FordCarInfo("Ford Escape 2020-22"), + FordCarInfo("Ford Escape Plug-in Hybrid 2020-22"), FordCarInfo("Ford Kuga 2020-21", "Driver Assistance Pack"), ], CAR.EXPLORER_MK6: [ @@ -128,6 +129,7 @@ FW_VERSIONS = { (Ecu.eps, 0x730, None): [ b'LX6C-14D003-AF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'LX6C-14D003-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'LX6C-14D003-AL\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.abs, 0x760, None): [ b'LX6C-2D053-NS\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', @@ -145,10 +147,12 @@ FW_VERSIONS = { b'LX6A-14C204-BJV\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'LX6A-14C204-ESG\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'MX6A-14C204-BEF\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'NX6A-14C204-BLE\x00\x00\x00\x00\x00\x00\x00\x00\x00', ], (Ecu.shiftByWire, 0x732, None): [ b'LX6P-14G395-AB\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'LX6P-14G395-AD\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', + b'PZ1P-14G395-AC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', ], }, CAR.EXPLORER_MK6: { From ce9fd785d55f5bee8e49d035b13548709fbe989c Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Fri, 17 Feb 2023 19:30:06 -0800 Subject: [PATCH 60/63] Ford: add CarInfo for Plug-in Hybrids --- selfdrive/car/ford/values.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 24415c74be..951cd09ba0 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -75,10 +75,12 @@ CAR_INFO: Dict[str, Union[CarInfo, List[CarInfo]]] = { FordCarInfo("Ford Escape 2020-22"), FordCarInfo("Ford Escape Plug-in Hybrid 2020-22"), FordCarInfo("Ford Kuga 2020-21", "Driver Assistance Pack"), + FordCarInfo("Ford Kuga Plug-in Hybrid 2020-22", "Driver Assistance Pack"), ], CAR.EXPLORER_MK6: [ FordCarInfo("Ford Explorer 2020-22"), FordCarInfo("Lincoln Aviator 2021", "Co-Pilot360 Plus"), + FordCarInfo("Lincoln Aviator Plug-in Hybrid 2021", "Co-Pilot360 Plus"), ], CAR.FOCUS_MK4: FordCarInfo("Ford Focus EU 2019", "Driver Assistance Pack"), CAR.MAVERICK_MK1: FordCarInfo("Ford Maverick 2022", "Co-Pilot360 Assist"), From ac0dbf74bc835faa46beab4bbb948c95597e4e67 Mon Sep 17 00:00:00 2001 From: Dean Lee Date: Sat, 18 Feb 2023 11:31:54 +0800 Subject: [PATCH 61/63] cabana: add support for load&save extra dbc info (#27203) * support extra info * support undo/redo * fix undo/redo * cleanup * fix regexp * refactor dbcmanager * replace text in headerview * fix binary::refresh * cleanup * use QRegularExpression * add desc validation * edit val description in table * cleanup --- tools/cabana/SConscript | 2 + tools/cabana/binaryview.cc | 21 ++- tools/cabana/binaryview.h | 3 +- tools/cabana/chartswidget.cc | 8 +- tools/cabana/chartswidget.h | 2 +- tools/cabana/commands.cc | 16 +- tools/cabana/commands.h | 4 +- tools/cabana/dbcmanager.cc | 220 +++++++++++++++++--------- tools/cabana/dbcmanager.h | 56 ++++--- tools/cabana/detailwidget.cc | 6 +- tools/cabana/historylog.cc | 19 +-- tools/cabana/historylog.h | 3 +- tools/cabana/messageswidget.cc | 6 +- tools/cabana/messageswidget.h | 2 + tools/cabana/signaledit.cc | 122 ++++++++++++-- tools/cabana/signaledit.h | 18 ++- tools/cabana/streams/replaystream.cc | 2 - tools/cabana/streams/replaystream.h | 1 - tools/cabana/tests/test_cabana.cc | 19 ++- tools/cabana/tools/findsimilarbits.cc | 1 + tools/cabana/tools/findsimilarbits.h | 1 + tools/cabana/util.cc | 2 +- tools/cabana/util.h | 6 +- tools/cabana/videowidget.h | 2 + 24 files changed, 376 insertions(+), 166 deletions(-) diff --git a/tools/cabana/SConscript b/tools/cabana/SConscript index a9922ba9be..166b3d5548 100644 --- a/tools/cabana/SConscript +++ b/tools/cabana/SConscript @@ -17,6 +17,8 @@ qt_libs = ['qt_util'] + base_libs cabana_libs = [widgets, cereal, messaging, visionipc, replay_lib, opendbc,'avutil', 'avcodec', 'avformat', 'bz2', 'curl', 'yuv'] + qt_libs cabana_env = qt_env.Clone() +opendbc_path = '-DOPENDBC_FILE_PATH=\'"%s"\'' % (cabana_env.Dir("../../opendbc").abspath) +cabana_env['CXXFLAGS'] += [opendbc_path] prev_moc_path = cabana_env['QT_MOCHPREFIX'] cabana_env['QT_MOCHPREFIX'] = os.path.dirname(prev_moc_path) + '/cabana/moc_' diff --git a/tools/cabana/binaryview.cc b/tools/cabana/binaryview.cc index 20edfd06ff..5ea5ea2d99 100644 --- a/tools/cabana/binaryview.cc +++ b/tools/cabana/binaryview.cc @@ -12,7 +12,6 @@ #include "tools/cabana/commands.h" #include "tools/cabana/signaledit.h" -#include "tools/cabana/streams/abstractstream.h" // BinaryView @@ -170,7 +169,7 @@ void BinaryView::highlightPosition(const QPoint &pos) { auto item = (BinaryViewModel::Item *)index.internalPointer(); const Signal *sig = item->sigs.isEmpty() ? nullptr : item->sigs.back(); highlight(sig); - QToolTip::showText(pos, sig ? sig->name.c_str() : "", this, rect()); + QToolTip::showText(pos, sig ? sig->name : "", this, rect()); } } @@ -246,22 +245,22 @@ std::tuple BinaryView::getSelection(QModelIndex index) { void BinaryViewModel::refresh() { beginResetModel(); items.clear(); - if ((dbc_msg = dbc()->msg(*msg_id))) { + if (auto dbc_msg = dbc()->msg(*msg_id)) { row_count = dbc_msg->size; items.resize(row_count * column_count); - for (auto sig : dbc_msg->getSignals()) { - auto [start, end] = getSignalRange(sig); + for (auto &sig : dbc_msg->sigs) { + auto [start, end] = getSignalRange(&sig); for (int j = start; j <= end; ++j) { - int bit_index = sig->is_little_endian ? bigEndianBitIndex(j) : j; + int bit_index = sig.is_little_endian ? bigEndianBitIndex(j) : j; int idx = column_count * (bit_index / 8) + bit_index % 8; if (idx >= items.size()) { - qWarning() << "signal " << sig->name.c_str() << "out of bounds.start_bit:" << sig->start_bit << "size:" << sig->size; + qWarning() << "signal " << sig.name << "out of bounds.start_bit:" << sig.start_bit << "size:" << sig.size; break; } - if (j == start) sig->is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; - if (j == end) sig->is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; - items[idx].bg_color = getColor(sig); - items[idx].sigs.push_back(sig); + if (j == start) sig.is_little_endian ? items[idx].is_lsb = true : items[idx].is_msb = true; + if (j == end) sig.is_little_endian ? items[idx].is_msb = true : items[idx].is_lsb = true; + items[idx].bg_color = getColor(&sig); + items[idx].sigs.push_back(&sig); } } } else { diff --git a/tools/cabana/binaryview.h b/tools/cabana/binaryview.h index 6743b6cfac..1d6d5d0b07 100644 --- a/tools/cabana/binaryview.h +++ b/tools/cabana/binaryview.h @@ -9,6 +9,8 @@ #include #include "tools/cabana/dbcmanager.h" +#include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; class BinaryItemDelegate : public QStyledItemDelegate { public: @@ -49,7 +51,6 @@ public: std::vector items; std::optional msg_id; - const DBCMsg *dbc_msg = nullptr; int row_count = 0; const int column_count = 9; }; diff --git a/tools/cabana/chartswidget.cc b/tools/cabana/chartswidget.cc index 9c5ed097c6..8515ffcfe7 100644 --- a/tools/cabana/chartswidget.cc +++ b/tools/cabana/chartswidget.cc @@ -459,7 +459,7 @@ void ChartView::updateTitle() { } for (auto &s : sigs) { auto decoration = s.series->isVisible() ? "none" : "line-through"; - s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name.c_str(), msgName(s.msg_id), s.msg_id.toString())); + s.series->setName(QString("%2 %3 %4").arg(decoration, s.sig->name, msgName(s.msg_id), s.msg_id.toString())); } } @@ -672,7 +672,7 @@ void ChartView::mouseMoveEvent(QMouseEvent *ev) { value = QString::number(it->y()); track_pts[i] = chart()->mapToPosition(*it); } - text_list.push_back(QString("■ %2: %3").arg(sigs[i].series->color().name(), sigs[i].sig->name.c_str(), value)); + text_list.push_back(QString("■ %2: %3").arg(sigs[i].series->color().name(), sigs[i].sig->name, value)); } auto max = std::max_element(track_pts.begin(), track_pts.end(), [](auto &a, auto &b) { return a.x() < b.x(); }); auto pt = (max == track_pts.end()) ? ev->pos() : *max; @@ -887,7 +887,7 @@ void SeriesSelector::updateAvailableList(int index) { available_list->clear(); MessageId msg_id = msgs_combo->itemData(index).value(); auto selected_items = seletedItems(); - for (auto &[name, s] : dbc()->msg(msg_id)->sigs) { + for (auto &s : dbc()->msg(msg_id)->sigs) { bool is_selected = std::any_of(selected_items.begin(), selected_items.end(), [=, sig=&s](auto it) { return it->msg_id == msg_id && it->sig == sig; }); if (!is_selected) { addItemToList(available_list, msg_id, &s); @@ -896,7 +896,7 @@ void SeriesSelector::updateAvailableList(int index) { } void SeriesSelector::addItemToList(QListWidget *parent, const MessageId id, const Signal *sig, bool show_msg_name) { - QString text = QString("■ %1").arg(getColor(sig).name(), sig->name.c_str()); + QString text = QString("■ %1").arg(getColor(sig).name(), sig->name); if (show_msg_name) text += QString(" %0 %1").arg(msgName(id), id.toString()); QLabel *label = new QLabel(text); diff --git a/tools/cabana/chartswidget.h b/tools/cabana/chartswidget.h index 7569155d39..7089b4eaee 100644 --- a/tools/cabana/chartswidget.h +++ b/tools/cabana/chartswidget.h @@ -15,7 +15,7 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" - +using namespace dbcmanager; using namespace QtCharts; const int CHART_MIN_WIDTH = 300; diff --git a/tools/cabana/commands.cc b/tools/cabana/commands.cc index b03f46b5d2..e03d6d1b11 100644 --- a/tools/cabana/commands.cc +++ b/tools/cabana/commands.cc @@ -36,7 +36,7 @@ RemoveMsgCommand::RemoveMsgCommand(const MessageId &id, QUndoCommand *parent) : void RemoveMsgCommand::undo() { if (!message.name.isEmpty()) { dbc()->updateMsg(id, message.name, message.size); - for (auto &[name, s] : message.sigs) + for (auto &s : message.sigs) dbc()->addSignal(id, s); } } @@ -50,31 +50,31 @@ void RemoveMsgCommand::redo() { AddSigCommand::AddSigCommand(const MessageId &id, const Signal &sig, QUndoCommand *parent) : id(id), signal(sig), QUndoCommand(parent) { - setText(QObject::tr("Add signal %1 to %2").arg(sig.name.c_str()).arg(id.address)); + setText(QObject::tr("Add signal %1 to %2").arg(sig.name).arg(id.address)); } -void AddSigCommand::undo() { dbc()->removeSignal(id, signal.name.c_str()); } +void AddSigCommand::undo() { dbc()->removeSignal(id, signal.name); } void AddSigCommand::redo() { dbc()->addSignal(id, signal); } // RemoveSigCommand RemoveSigCommand::RemoveSigCommand(const MessageId &id, const Signal *sig, QUndoCommand *parent) : id(id), signal(*sig), QUndoCommand(parent) { - setText(QObject::tr("Remove signal %1 from %2").arg(signal.name.c_str()).arg(id.address)); + setText(QObject::tr("Remove signal %1 from %2").arg(signal.name).arg(id.address)); } void RemoveSigCommand::undo() { dbc()->addSignal(id, signal); } -void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name.c_str()); } +void RemoveSigCommand::redo() { dbc()->removeSignal(id, signal.name); } // EditSignalCommand EditSignalCommand::EditSignalCommand(const MessageId &id, const Signal *sig, const Signal &new_sig, QUndoCommand *parent) : id(id), old_signal(*sig), new_signal(new_sig), QUndoCommand(parent) { - setText(QObject::tr("Edit signal %1").arg(old_signal.name.c_str())); + setText(QObject::tr("Edit signal %1").arg(old_signal.name)); } -void EditSignalCommand::undo() { dbc()->updateSignal(id, new_signal.name.c_str(), old_signal); } -void EditSignalCommand::redo() { dbc()->updateSignal(id, old_signal.name.c_str(), new_signal); } +void EditSignalCommand::undo() { dbc()->updateSignal(id, new_signal.name, old_signal); } +void EditSignalCommand::redo() { dbc()->updateSignal(id, old_signal.name, new_signal); } namespace UndoStack { diff --git a/tools/cabana/commands.h b/tools/cabana/commands.h index 46e9f0a030..57df664974 100644 --- a/tools/cabana/commands.h +++ b/tools/cabana/commands.h @@ -4,6 +4,8 @@ #include #include "tools/cabana/dbcmanager.h" +#include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; class EditMsgCommand : public QUndoCommand { public: @@ -25,7 +27,7 @@ public: private: const MessageId id; - DBCMsg message; + Msg message; }; class AddSigCommand : public QUndoCommand { diff --git a/tools/cabana/dbcmanager.cc b/tools/cabana/dbcmanager.cc index 27f16c71e5..ae3a65a99b 100644 --- a/tools/cabana/dbcmanager.cc +++ b/tools/cabana/dbcmanager.cc @@ -1,63 +1,114 @@ #include "tools/cabana/dbcmanager.h" +#include +#include +#include +#include +#include #include #include -#include -uint qHash(const MessageId &item) { - return qHash(item.source) ^ qHash(item.address); +namespace dbcmanager { + +void sortSignalsByAddress(QList &sigs) { + std::sort(sigs.begin(), sigs.end(), [](auto &a, auto &b) { return a.start_bit < b.start_bit; }); } -DBCManager::DBCManager(QObject *parent) : QObject(parent) {} - -DBCManager::~DBCManager() {} - -void DBCManager::open(const QString &dbc_file_name) { - dbc = const_cast(dbc_lookup(dbc_file_name.toStdString())); - initMsgMap(); -} - -bool DBCManager::open(const QString &name, const QString &content, QString *error) { - try { - std::istringstream stream(content.toStdString()); - dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); - initMsgMap(); - return true; - } catch (std::exception &e) { - if (error) *error = e.what(); +bool DBCManager::open(const QString &dbc_file_name, QString *error) { + QString opendbc_file_path = QString("%1/%2.dbc").arg(OPENDBC_FILE_PATH, dbc_file_name); + QFile file(opendbc_file_path); + if (file.open(QIODevice::ReadOnly)) { + return open(dbc_file_name, file.readAll(), error); } return false; } -void DBCManager::initMsgMap() { - msgs.clear(); - for (auto &msg : dbc->msgs) { - auto &m = msgs[msg.address]; - m.name = msg.name.c_str(); - m.size = msg.size; - for (auto &s : msg.sigs) - m.sigs[QString::fromStdString(s.name)] = s; +void DBCManager::parseExtraInfo(const QString &content) { + static QRegularExpression bo_regexp(R"(^BO_ (\w+) (\w+) *: (\w+) (\w+))"); + static QRegularExpression sg_regexp(R"(^SG_ (\w+) : (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); + static QRegularExpression sgm_regexp(R"(^SG_ (\w+) (\w+) *: (\d+)\|(\d+)@(\d+)([\+|\-]) \(([0-9.+\-eE]+),([0-9.+\-eE]+)\) \[([0-9.+\-eE]+)\|([0-9.+\-eE]+)\] \"(.*)\" (.*))"); + static QRegularExpression sg_comment_regexp(R"(^CM_ SG_ *(\w+) *(\w+) *\"(.*)\";)"); + static QRegularExpression val_regexp(R"(VAL_ (\w+) (\w+) (.*);)"); + auto get_sig = [this](uint32_t address, const QString &name) -> Signal * { + auto m = (Msg *)msg(address); + return m ? (Signal *)m->sig(name) : nullptr; + }; + + QTextStream stream((QString *)&content); + uint32_t address = 0; + while (!stream.atEnd()) { + QString line = stream.readLine().trimmed(); + if (line.startsWith("BO_ ")) { + if (auto match = bo_regexp.match(line); match.hasMatch()) { + address = match.captured(1).toUInt(); + } + } else if (line.startsWith("SG_ ")) { + int offset = 0; + auto match = sg_regexp.match(line); + if (!match.hasMatch()) { + match = sgm_regexp.match(line); + offset = 1; + } + if (match.hasMatch()) { + if (auto s = get_sig(address, match.captured(1))) { + s->min = match.captured(8 + offset); + s->max = match.captured(9 + offset); + s->unit = match.captured(10 + offset); + } + } + } else if (line.startsWith("VAL_ ")) { + if (auto match = val_regexp.match(line); match.hasMatch()) { + if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { + QStringList desc_list = match.captured(3).trimmed().split('"'); + for (int i = 0; i < desc_list.size(); i += 2) { + auto val = desc_list[i].trimmed(); + if (!val.isEmpty() && (i + 1) < desc_list.size()) { + auto desc = desc_list[i+1].trimmed(); + s->val_desc.push_back({val, desc}); + } + } + } + } + } else if (line.startsWith("CM_ SG_ ")) { + if (auto match = sg_comment_regexp.match(line); match.hasMatch()) { + if (auto s = get_sig(match.captured(1).toUInt(), match.captured(2))) { + s->comment = match.captured(3).trimmed(); + } + } + } } - emit DBCFileChanged(); } QString DBCManager::generateDBC() { - QString dbc_string; + QString dbc_string, signal_comment, val_desc; for (auto &[address, m] : msgs) { dbc_string += QString("BO_ %1 %2: %3 XXX\n").arg(address).arg(m.name).arg(m.size); - for (auto &[name, sig] : m.sigs) { - dbc_string += QString(" SG_ %1 : %2|%3@%4%5 (%6,%7) [0|0] \"\" XXX\n") - .arg(name) + for (auto &sig : m.sigs) { + dbc_string += QString(" SG_ %1 : %2|%3@%4%5 (%6,%7) [%8|%9] \"%10\" XXX\n") + .arg(sig.name) .arg(sig.start_bit) .arg(sig.size) .arg(sig.is_little_endian ? '1' : '0') .arg(sig.is_signed ? '-' : '+') .arg(sig.factor, 0, 'g', std::numeric_limits::digits10) - .arg(sig.offset, 0, 'g', std::numeric_limits::digits10); + .arg(sig.offset, 0, 'g', std::numeric_limits::digits10) + .arg(sig.min) + .arg(sig.max) + .arg(sig.unit); + if (!sig.comment.isEmpty()) { + signal_comment += QString("CM_ SG_ %1 %2 \"%3\";\n").arg(address).arg(sig.name).arg(sig.comment); + } + if (!sig.val_desc.isEmpty()) { + QString text; + for (auto &[val, desc] : sig.val_desc) { + text += QString("%1 \"%2\"").arg(val, desc); + } + val_desc += QString("VAL_ %1 %2 %3;\n").arg(address).arg(sig.name).arg(text); + } } dbc_string += "\n"; } - return dbc_string; + return dbc_string + signal_comment + val_desc; } void DBCManager::updateMsg(const MessageId &id, const QString &name, uint32_t size) { @@ -73,31 +124,29 @@ void DBCManager::removeMsg(const MessageId &id) { } void DBCManager::addSignal(const MessageId &id, const Signal &sig) { - if (auto m = const_cast(msg(id.address))) { - auto &s = m->sigs[sig.name.c_str()]; - s = sig; - emit signalAdded(id.address, &s); + if (auto m = const_cast(msg(id.address))) { + m->sigs.push_back(sig); + auto s = &m->sigs.last(); + sortSignalsByAddress(m->sigs); + emit signalAdded(id.address, s); } } void DBCManager::updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig) { - if (auto m = const_cast(msg(id))) { - // change key name - QString new_name = QString::fromStdString(sig.name); - auto node = m->sigs.extract(sig_name); - node.key() = new_name; - auto it = m->sigs.insert(std::move(node)); - auto &s = m->sigs[new_name]; - s = sig; - emit signalUpdated(&s); + if (auto m = const_cast(msg(id))) { + if (auto s = (Signal *)m->sig(sig_name)) { + *s = sig; + sortSignalsByAddress(m->sigs); + emit signalUpdated(s); + } } } void DBCManager::removeSignal(const MessageId &id, const QString &sig_name) { - if (auto m = const_cast(msg(id))) { - auto it = m->sigs.find(sig_name); + if (auto m = const_cast(msg(id))) { + auto it = std::find_if(m->sigs.begin(), m->sigs.end(), [&](auto &s) { return s.name == sig_name; }); if (it != m->sigs.end()) { - emit signalRemoved(&(it->second)); + emit signalRemoved(&(*it)); m->sigs.erase(it); } } @@ -108,16 +157,6 @@ DBCManager *dbc() { return &dbc_manager; } -// DBCMsg - -std::vector DBCMsg::getSignals() const { - std::vector ret; - ret.reserve(sigs.size()); - for (auto &[_, sig] : sigs) ret.push_back(&sig); - std::sort(ret.begin(), ret.end(), [](auto l, auto r) { return l->start_bit < r->start_bit; }); - return ret; -} - // helper functions static QVector BIG_ENDIAN_START_BITS = []() { @@ -128,13 +167,8 @@ static QVector BIG_ENDIAN_START_BITS = []() { return ret; }(); -int bigEndianStartBitsIndex(int start_bit) { - return BIG_ENDIAN_START_BITS[start_bit]; -} - -int bigEndianBitIndex(int index) { - return BIG_ENDIAN_START_BITS.indexOf(index); -} +int bigEndianStartBitsIndex(int start_bit) { return BIG_ENDIAN_START_BITS[start_bit]; } +int bigEndianBitIndex(int index) { return BIG_ENDIAN_START_BITS.indexOf(index); } double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) { int64_t val = 0; @@ -155,8 +189,7 @@ double get_raw_value(uint8_t *data, size_t data_size, const Signal &sig) { if (sig.is_signed) { val -= ((val >> (sig.size - 1)) & 0x1) ? (1ULL << sig.size) : 0; } - double value = val * sig.factor + sig.offset; - return value; + return val * sig.factor + sig.offset; } void updateSigSizeParamsFromRange(Signal &s, int start_bit, int size) { @@ -182,5 +215,50 @@ bool operator==(const Signal &l, const Signal &r) { l.start_bit == r.start_bit && l.msb == r.msb && l.lsb == r.lsb && l.is_signed == r.is_signed && l.is_little_endian == r.is_little_endian && - l.factor == r.factor && l.offset == r.offset; + l.factor == r.factor && l.offset == r.offset && + l.min == r.min && l.max == r.max && l.comment == r.comment && l.unit == r.unit && l.val_desc == r.val_desc; +} + +} // namespace dbcmanager + +#include "opendbc/can/common_dbc.h" +std::vector dbcmanager::DBCManager::allDBCNames() { return get_dbc_names(); } + +bool dbcmanager::DBCManager::open(const QString &name, const QString &content, QString *error) { + try { + std::istringstream stream(content.toStdString()); + auto dbc = const_cast(dbc_parse_from_stream(name.toStdString(), stream)); + msgs.clear(); + for (auto &msg : dbc->msgs) { + auto &m = msgs[msg.address]; + m.name = msg.name.c_str(); + m.size = msg.size; + for (auto &s : msg.sigs) { + m.sigs.push_back({}); + auto &sig = m.sigs.last(); + sig.name = s.name.c_str(); + sig.start_bit = s.start_bit; + sig.msb = s.msb; + sig.lsb = s.lsb; + sig.size = s.size; + sig.is_signed = s.is_signed; + sig.factor = s.factor; + sig.offset = s.offset; + sig.is_little_endian = s.is_little_endian; + } + sortSignalsByAddress(m.sigs); + } + parseExtraInfo(content); + name_ = name; + emit DBCFileChanged(); + delete dbc; + } catch (std::exception &e) { + if (error) *error = e.what(); + return false; + } + return true; +} + +uint qHash(const MessageId &item) { + return qHash(item.source) ^ qHash(item.address); } diff --git a/tools/cabana/dbcmanager.h b/tools/cabana/dbcmanager.h index b766c837b6..b438b3e1c2 100644 --- a/tools/cabana/dbcmanager.h +++ b/tools/cabana/dbcmanager.h @@ -1,9 +1,8 @@ #pragma once #include -#include +#include #include -#include "opendbc/can/common_dbc.h" struct MessageId { uint8_t source; @@ -30,40 +29,55 @@ struct MessageId { } }; +uint qHash(const MessageId &item); Q_DECLARE_METATYPE(MessageId); -uint qHash(const MessageId &item); +namespace dbcmanager { -struct DBCMsg { +typedef QList> ValueDescription; + +struct Signal { + QString name; + int start_bit, msb, lsb, size; + bool is_signed; + double factor, offset; + bool is_little_endian; + QString min, max, unit; + QString comment; + ValueDescription val_desc; +}; + +struct Msg { QString name; uint32_t size; - // signal must be saved as value in map to make undo stack work properly. - std::map sigs; - // return vector, sort by start_bits - std::vector getSignals() const; + QList sigs; + + const Signal *sig(const QString &sig_name) const { + auto it = std::find_if(sigs.begin(), sigs.end(), [&](auto &s) { return s.name == sig_name; }); + return it != sigs.end() ? &(*it) : nullptr; + } }; class DBCManager : public QObject { Q_OBJECT public: - DBCManager(QObject *parent); - ~DBCManager(); - - void open(const QString &dbc_file_name); + DBCManager(QObject *parent) {} + ~DBCManager() {} + bool open(const QString &dbc_file_name, QString *error = nullptr); bool open(const QString &name, const QString &content, QString *error = nullptr); QString generateDBC(); void addSignal(const MessageId &id, const Signal &sig); void updateSignal(const MessageId &id, const QString &sig_name, const Signal &sig); void removeSignal(const MessageId &id, const QString &sig_name); - inline static std::vector allDBCNames() { return get_dbc_names(); } - inline QString name() const { return dbc ? dbc->name.c_str() : ""; } + static std::vector allDBCNames(); + inline QString name() const { return name_; } void updateMsg(const MessageId &id, const QString &name, uint32_t size); void removeMsg(const MessageId &id); - inline const std::map &messages() const { return msgs; } - inline const DBCMsg *msg(const MessageId &id) const { return msg(id.address); } - inline const DBCMsg *msg(uint32_t address) const { + inline const std::map &messages() const { return msgs; } + inline const Msg *msg(const MessageId &id) const { return msg(id.address); } + inline const Msg *msg(uint32_t address) const { auto it = msgs.find(address); return it != msgs.end() ? &it->second : nullptr; } @@ -77,9 +91,9 @@ signals: void DBCFileChanged(); private: - void initMsgMap(); - DBC *dbc = nullptr; - std::map msgs; + void parseExtraInfo(const QString &content); + std::map msgs; + QString name_; }; const QString UNTITLED = "untitled"; @@ -97,3 +111,5 @@ inline QString msgName(const MessageId &id) { auto msg = dbc()->msg(id); return msg ? msg->name : UNTITLED; } + +} // namespace dbcmanager diff --git a/tools/cabana/detailwidget.cc b/tools/cabana/detailwidget.cc index f290b3b706..882ea932c6 100644 --- a/tools/cabana/detailwidget.cc +++ b/tools/cabana/detailwidget.cc @@ -6,8 +6,6 @@ #include #include "tools/cabana/commands.h" -#include "tools/cabana/dbcmanager.h" -#include "tools/cabana/streams/abstractstream.h" // DetailWidget @@ -153,13 +151,13 @@ void DetailWidget::refresh() { if (!msg_id) return; QStringList warnings; - const DBCMsg *msg = dbc()->msg(*msg_id); + auto msg = dbc()->msg(*msg_id); if (msg) { if (msg->size != can->lastMessage(*msg_id).dat.size()) { warnings.push_back(tr("Message size (%1) is incorrect.").arg(msg->size)); } for (auto s : binary_view->getOverlappingSignals()) { - warnings.push_back(tr("%1 has overlapping bits.").arg(s->name.c_str())); + warnings.push_back(tr("%1 has overlapping bits.").arg(s->name)); } } else { warnings.push_back(tr("Drag-Select in binary view to create new signal.")); diff --git a/tools/cabana/historylog.cc b/tools/cabana/historylog.cc index 87968d495c..a1c671b68d 100644 --- a/tools/cabana/historylog.cc +++ b/tools/cabana/historylog.cc @@ -5,6 +5,7 @@ #include #include "tools/cabana/commands.h" +#include "tools/cabana/util.h" // HistoryLogModel @@ -30,7 +31,7 @@ void HistoryLogModel::refresh() { beginResetModel(); sigs.clear(); if (auto dbc_msg = dbc()->msg(*msg_id)) { - sigs = dbc_msg->getSignals(); + sigs = dbc_msg->sigs; } last_fetch_time = 0; has_more_data = true; @@ -47,9 +48,9 @@ QVariant HistoryLogModel::headerData(int section, Qt::Orientation orientation, i if (section == 0) { return "Time"; } - return show_signals ? QString::fromStdString(sigs[section - 1]->name).replace('_', ' ') : "Data"; + return show_signals ? sigs[section - 1].name : "Data"; } else if (role == Qt::BackgroundRole && section > 0 && show_signals) { - return QBrush(getColor(sigs[section - 1])); + return QBrush(getColor(&sigs[section - 1])); } } return {}; @@ -113,7 +114,7 @@ std::deque HistoryLogModel::fetchData(InputIt first, I if (msg_id->address == c.getAddress() && msg_id->source == c.getSrc()) { const auto dat = c.getDat(); for (int i = 0; i < sigs.size(); ++i) { - values[i] = get_raw_value((uint8_t *)dat.begin(), dat.size(), *(sigs[i])); + values[i] = get_raw_value((uint8_t *)dat.begin(), dat.size(), sigs[i]); } if (!filter_cmp || filter_cmp(values[filter_sig_idx], filter_value)) { auto &m = msgs.emplace_back(); @@ -170,8 +171,8 @@ QSize HeaderView::sectionSizeFromContents(int logicalIndex) const { return time_col_size; } else { int default_size = qMax(100, (rect().width() - time_col_size.width()) / (model()->columnCount() - 1)); - const QString text = model()->headerData(logicalIndex, this->orientation(), Qt::DisplayRole).toString(); - const QRect rect = fontMetrics().boundingRect({0, 0, default_size, 2000}, defaultAlignment(), text); + QString text = model()->headerData(logicalIndex, this->orientation(), Qt::DisplayRole).toString(); + const QRect rect = fontMetrics().boundingRect({0, 0, default_size, 2000}, defaultAlignment(), text.replace(QChar('_'), ' ')); QSize size = rect.size() + QSize{10, 6}; return QSize{qMax(size.width(), default_size), size.height()}; } @@ -183,7 +184,7 @@ void HeaderView::paintSection(QPainter *painter, const QRect &rect, int logicalI painter->fillRect(rect, bg_role.value()); } QString text = model()->headerData(logicalIndex, Qt::Horizontal, Qt::DisplayRole).toString(); - painter->drawText(rect.adjusted(5, 3, -5, -3), defaultAlignment(), text); + painter->drawText(rect.adjusted(5, 3, -5, -3), defaultAlignment(), text.replace(QChar('_'), ' ')); } // LogsWidget @@ -253,8 +254,8 @@ void LogsWidget::refresh() { bool has_signal = model->sigs.size(); if (has_signal) { signals_cb->clear(); - for (auto s : model->sigs) { - signals_cb->addItem(s->name.c_str()); + for (auto &s : model->sigs) { + signals_cb->addItem(s.name); } } value_edit->clear(); diff --git a/tools/cabana/historylog.h b/tools/cabana/historylog.h index 00a8f73836..a1b7bc0098 100644 --- a/tools/cabana/historylog.h +++ b/tools/cabana/historylog.h @@ -11,6 +11,7 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; class HeaderView : public QHeaderView { public: @@ -63,7 +64,7 @@ public: uint64_t last_fetch_time = 0; std::function filter_cmp = nullptr; std::deque messages; - std::vector sigs; + QList sigs; bool dynamic_mode = true; bool display_signals_mode = true; }; diff --git a/tools/cabana/messageswidget.cc b/tools/cabana/messageswidget.cc index 81ebc6af20..42ac22865c 100644 --- a/tools/cabana/messageswidget.cc +++ b/tools/cabana/messageswidget.cc @@ -7,8 +7,6 @@ #include #include -#include "tools/cabana/dbcmanager.h" - MessagesWidget::MessagesWidget(QWidget *parent) : QWidget(parent) { QVBoxLayout *main_layout = new QVBoxLayout(this); @@ -140,8 +138,8 @@ void MessageListModel::setFilterString(const QString &string) { if (id.toString().contains(txt, cs) || msgName(id).contains(txt, cs)) return true; // Search by signal name if (const auto msg = dbc()->msg(id)) { - for (auto &signal : msg->getSignals()) { - if (QString::fromStdString(signal->name).contains(txt, cs)) return true; + for (auto &signal : msg->sigs) { + if (signal.name.contains(txt, cs)) return true; } } return false; diff --git a/tools/cabana/messageswidget.h b/tools/cabana/messageswidget.h index 562069c3ae..d88def3acb 100644 --- a/tools/cabana/messageswidget.h +++ b/tools/cabana/messageswidget.h @@ -9,7 +9,9 @@ #include #include +#include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; class MessageListModel : public QAbstractTableModel { Q_OBJECT diff --git a/tools/cabana/signaledit.cc b/tools/cabana/signaledit.cc index e2be5c85d0..d5099da6f4 100644 --- a/tools/cabana/signaledit.cc +++ b/tools/cabana/signaledit.cc @@ -1,5 +1,6 @@ #include "tools/cabana/signaledit.h" +#include #include #include #include @@ -23,9 +24,9 @@ SignalModel::SignalModel(QObject *parent) : root(new Item), QAbstractItemModel(p } void SignalModel::insertItem(SignalModel::Item *parent_item, int pos, const Signal *sig) { - Item *item = new Item{.sig = sig, .parent = parent_item, .title = sig->name.c_str(), .type = Item::Sig}; + Item *item = new Item{.sig = sig, .parent = parent_item, .title = sig->name, .type = Item::Sig}; parent_item->children.insert(pos, item); - QString titles[]{"Name", "Size", "Little Endian", "Signed", "Offset", "Factor", "Extra Info", "Unit", "Comment", "Minimum", "Maximum", "Description"}; + QString titles[]{"Name", "Size", "Little Endian", "Signed", "Offset", "Factor", "Extra Info", "Unit", "Comment", "Minimum Value", "Maximum Value", "Value Descriptions"}; for (int i = 0; i < std::size(titles); ++i) { item->children.push_back(new Item{.sig = sig, .parent = item, .title = titles[i], .type = (Item::Type)(i + Item::Name)}); } @@ -47,9 +48,9 @@ void SignalModel::refresh() { beginResetModel(); root.reset(new SignalModel::Item); if (auto msg = dbc()->msg(msg_id)) { - for (auto &s : msg->getSignals()) { - if (filter_str.isEmpty() || QString::fromStdString(s->name).contains(filter_str, Qt::CaseInsensitive)) { - insertItem(root.get(), root->children.size(), s); + for (auto &s : msg->sigs) { + if (filter_str.isEmpty() || s.name.contains(filter_str, Qt::CaseInsensitive)) { + insertItem(root.get(), root->children.size(), &s); } } } @@ -115,14 +116,25 @@ QVariant SignalModel::data(const QModelIndex &index, int role) const { const Item *item = getItem(index); if (role == Qt::DisplayRole || role == Qt::EditRole) { if (index.column() == 0) { - return item->type == Item::Sig ? QString::fromStdString(item->sig->name) : item->title; + return item->type == Item::Sig ? item->sig->name : item->title; } else { switch (item->type) { case Item::Sig: return item->sig_val; - case Item::Name: return QString::fromStdString(item->sig->name); + case Item::Name: return item->sig->name; case Item::Size: return item->sig->size; case Item::Offset: return QString::number(item->sig->offset, 'f', 6); case Item::Factor: return QString::number(item->sig->factor, 'f', 6); + case Item::Unit: return item->sig->unit; + case Item::Comment: return item->sig->comment; + case Item::Min: return item->sig->min; + case Item::Max: return item->sig->max; + case Item::Desc: { + QString val_desc; + for (auto &[val, desc] : item->sig->val_desc) { + val_desc += QString("%1 \"%2\"").arg(val, desc); + } + return val_desc; + } default: break; } } @@ -142,12 +154,17 @@ bool SignalModel::setData(const QModelIndex &index, const QVariant &value, int r Item *item = getItem(index); Signal s = *item->sig; switch (item->type) { - case Item::Name: s.name = value.toString().toStdString(); break; + case Item::Name: s.name = value.toString(); break; case Item::Size: s.size = value.toInt(); break; case Item::Endian: s.is_little_endian = value.toBool(); break; case Item::Signed: s.is_signed = value.toBool(); break; case Item::Offset: s.offset = value.toDouble(); break; case Item::Factor: s.factor = value.toDouble(); break; + case Item::Unit: s.unit = value.toString(); break; + case Item::Comment: s.comment = value.toString(); break; + case Item::Min: s.min = value.toString(); break; + case Item::Max: s.max = value.toString(); break; + case Item::Desc: s.val_desc = value.value(); break; default: return false; } bool ret = saveSignal(item->sig, s); @@ -172,8 +189,8 @@ void SignalModel::showExtraInfo(const QModelIndex &index) { bool SignalModel::saveSignal(const Signal *origin_s, Signal &s) { auto msg = dbc()->msg(msg_id); - if (s.name != origin_s->name && msg->sigs.count(s.name.c_str()) != 0) { - QString text = tr("There is already a signal with the same name '%1'").arg(s.name.c_str()); + if (s.name != origin_s->name && msg->sig(s.name) != nullptr) { + QString text = tr("There is already a signal with the same name '%1'").arg(s.name); QMessageBox::warning(nullptr, tr("Failed to save signal"), text); return false; } @@ -212,8 +229,8 @@ void SignalModel::addSignal(int start_bit, int size, bool little_endian) { Signal sig = {.is_little_endian = little_endian, .factor = 1}; for (int i = 1; /**/; ++i) { - sig.name = "NEW_SIGNAL_" + std::to_string(i); - if (msg->sigs.count(sig.name.c_str()) == 0) break; + sig.name = QString("NEW_SIGNAL_%1").arg(i); + if (msg->sig(sig.name) == nullptr) break; } updateSigSizeParamsFromRange(sig, start_bit, size); UndoStack::push(new AddSigCommand(msg_id, sig)); @@ -266,8 +283,8 @@ void SignalModel::handleSignalRemoved(const Signal *sig) { SignalItemDelegate::SignalItemDelegate(QObject *parent) { name_validator = new NameValidator(this); double_validator = new QDoubleValidator(this); - small_font.setPointSize(8); double_validator->setLocale(QLocale::C); // Match locale of QString::toDouble() instead of system + small_font.setPointSize(8); } void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const { @@ -304,7 +321,8 @@ void SignalItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &op QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { auto item = (SignalModel::Item *)index.internalPointer(); - if (item->type == SignalModel::Item::Name || item->type == SignalModel::Item::Offset || item->type == SignalModel::Item::Factor) { + if (item->type == SignalModel::Item::Name || item->type == SignalModel::Item::Offset || + item->type == SignalModel::Item::Factor || item->type == SignalModel::Item::Min || item->type == SignalModel::Item::Max) { QLineEdit *e = new QLineEdit(parent); e->setFrame(false); e->setValidator(index.row() == 0 ? name_validator : double_validator); @@ -314,6 +332,13 @@ QWidget *SignalItemDelegate::createEditor(QWidget *parent, const QStyleOptionVie spin->setFrame(false); spin->setRange(1, 64); return spin; + } else if (item->type == SignalModel::Item::Desc) { + ValueDescriptionDlg dlg(item->sig->val_desc, parent); + dlg.setWindowTitle(item->sig->name); + if (dlg.exec()) { + ((QAbstractItemModel *)index.model())->setData(index, QVariant::fromValue(dlg.val_desc)); + } + return nullptr; } return QStyledItemDelegate::createEditor(parent, option, index); } @@ -437,7 +462,7 @@ void SignalView::expandSignal(const Signal *sig) { void SignalView::updateChartState() { int i = 0; for (auto item : model->root->children) { - auto plot_btn = tree->indexWidget(model->index(i, 1))->findChildren()[0]; + auto plot_btn = tree->indexWidget(model->index(i, 1))->findChildren()[0]; bool chart_opened = charts->hasSignal(msg_id, item->sig); plot_btn->setChecked(chart_opened); plot_btn->setToolTip(chart_opened ? tr("Close Plot") : tr("Show Plot\nSHIFT click to add to previous opened plot")); @@ -459,3 +484,70 @@ void SignalView::leaveEvent(QEvent *event) { emit highlight(nullptr); QWidget::leaveEvent(event); } + +// ValueDescriptionDlg + +ValueDescriptionDlg::ValueDescriptionDlg(const ValueDescription &descriptions, QWidget *parent) : QDialog(parent) { + QHBoxLayout *toolbar_layout = new QHBoxLayout(); + QPushButton *add = new QPushButton(utils::icon("plus"), ""); + QPushButton *remove = new QPushButton(utils::icon("dash"), ""); + remove->setEnabled(false); + toolbar_layout->addWidget(add); + toolbar_layout->addWidget(remove); + toolbar_layout->addStretch(0); + + table = new QTableWidget(descriptions.size(), 2, this); + table->setItemDelegate(new Delegate(this)); + table->setHorizontalHeaderLabels({"Value", "Description"}); + table->horizontalHeader()->setStretchLastSection(true); + table->setSelectionBehavior(QAbstractItemView::SelectRows); + table->setSelectionMode(QAbstractItemView::SingleSelection); + table->setEditTriggers(QAbstractItemView::DoubleClicked | QAbstractItemView::EditKeyPressed); + table->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); + + int row = 0; + for (auto &[val, desc] : descriptions) { + table->setItem(row, 0, new QTableWidgetItem(val)); + table->setItem(row, 1, new QTableWidgetItem(desc)); + ++row; + } + + auto btn_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); + QVBoxLayout *main_layout = new QVBoxLayout(this); + main_layout->addLayout(toolbar_layout); + main_layout->addWidget(table); + main_layout->addWidget(btn_box); + setMinimumWidth(500); + + QObject::connect(btn_box, &QDialogButtonBox::accepted, this, &ValueDescriptionDlg::save); + QObject::connect(btn_box, &QDialogButtonBox::rejected, this, &QDialog::reject); + QObject::connect(add, &QPushButton::clicked, [this]() { + table->setRowCount(table->rowCount() + 1); + table->setItem(table->rowCount() - 1, 0, new QTableWidgetItem); + table->setItem(table->rowCount() - 1, 1, new QTableWidgetItem); + }); + QObject::connect(remove, &QPushButton::clicked, [this]() { table->removeRow(table->currentRow()); }); + QObject::connect(table, &QTableWidget::itemSelectionChanged, [=]() { + remove->setEnabled(table->currentRow() != -1); + }); +} + +void ValueDescriptionDlg::save() { + for (int i = 0; i < table->rowCount(); ++i) { + QString val = table->item(i, 0)->text().trimmed(); + QString desc = table->item(i, 1)->text().trimmed(); + if (!val.isEmpty() && !desc.isEmpty()) { + val_desc.push_back({val, desc}); + } + } + QDialog::accept(); +} + +QWidget *ValueDescriptionDlg::Delegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { + QLineEdit *edit = new QLineEdit(parent); + edit->setFrame(false); + if (index.column() == 0) { + edit->setValidator(new QIntValidator(edit)); + } + return edit; +} diff --git a/tools/cabana/signaledit.h b/tools/cabana/signaledit.h index 7e5015f707..efdc653584 100644 --- a/tools/cabana/signaledit.h +++ b/tools/cabana/signaledit.h @@ -4,11 +4,10 @@ #include #include #include +#include #include #include "tools/cabana/chartswidget.h" -#include "tools/cabana/dbcmanager.h" -#include "tools/cabana/streams/abstractstream.h" class SignalModel : public QAbstractItemModel { Q_OBJECT @@ -62,6 +61,21 @@ private: friend class SignalView; }; +class ValueDescriptionDlg : public QDialog { +public: + ValueDescriptionDlg(const ValueDescription &descriptions, QWidget *parent); + ValueDescription val_desc; + +private: + struct Delegate : public QStyledItemDelegate { + Delegate(QWidget *parent) : QStyledItemDelegate(parent) {} + QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const override; + }; + + void save(); + QTableWidget *table; +}; + class SignalItemDelegate : public QStyledItemDelegate { public: SignalItemDelegate(QObject *parent); diff --git a/tools/cabana/streams/replaystream.cc b/tools/cabana/streams/replaystream.cc index b768b94327..ebd969be61 100644 --- a/tools/cabana/streams/replaystream.cc +++ b/tools/cabana/streams/replaystream.cc @@ -1,7 +1,5 @@ #include "tools/cabana/streams/replaystream.h" -#include "tools/cabana/dbcmanager.h" - ReplayStream::ReplayStream(uint32_t replay_flags, QObject *parent) : replay_flags(replay_flags), AbstractStream(parent, false) { QObject::connect(&settings, &Settings::changed, [this]() { if (replay) replay->setSegmentCacheLimit(settings.max_cached_minutes); diff --git a/tools/cabana/streams/replaystream.h b/tools/cabana/streams/replaystream.h index 69fb738ab8..3505f6abf4 100644 --- a/tools/cabana/streams/replaystream.h +++ b/tools/cabana/streams/replaystream.h @@ -1,6 +1,5 @@ #pragma once -#include "opendbc/can/common_dbc.h" #include "tools/cabana/streams/abstractstream.h" #include "tools/cabana/settings.h" diff --git a/tools/cabana/tests/test_cabana.cc b/tools/cabana/tests/test_cabana.cc index 586422ffc8..9a8ab710bc 100644 --- a/tools/cabana/tests/test_cabana.cc +++ b/tools/cabana/tests/test_cabana.cc @@ -2,8 +2,10 @@ #include "opendbc/can/common.h" #undef INFO #include "catch2/catch.hpp" -#include "tools/cabana/dbcmanager.h" #include "tools/replay/logreader.h" +#include "tools/cabana/dbcmanager.h" +#include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; // demo route, first segment const std::string TEST_RLOG_URL = "https://commadata2.blob.core.windows.net/commadata2/4cf7a6ad03080c90/2021-09-29--13-46-36/0/rlog.bz2"; @@ -18,12 +20,13 @@ TEST_CASE("DBCManager::generateDBC") { auto &new_msgs = dbc_from_generated.messages(); REQUIRE(msgs.size() == new_msgs.size()); for (auto &[address, m] : msgs) { - auto new_m = new_msgs.at(address); + auto &new_m = new_msgs.at(address); REQUIRE(m.name == new_m.name); REQUIRE(m.size == new_m.size); REQUIRE(m.sigs.size() == new_m.sigs.size()); - for (auto &[name, sig] : m.sigs) - REQUIRE(sig == new_m.sigs[name]); + for (int i = 0; i < m.sigs.size(); ++i) { + REQUIRE(m.sigs[i] == new_m.sigs[i]); + } } } @@ -37,13 +40,13 @@ TEST_CASE("Parse can messages") { REQUIRE(log.events.size() > 0); for (auto e : log.events) { if (e->which == cereal::Event::Which::CAN) { - std::map, std::vector> values_1; + std::map, std::vector> values_1; for (const auto &c : e->event.getCan()) { const auto msg = dbc.msg(c.getAddress()); if (c.getSrc() == 0 && msg) { - for (auto &[name, sig] : msg->sigs) { + for (auto &sig : msg->sigs) { double val = get_raw_value((uint8_t *)c.getDat().begin(), c.getDat().size(), sig); - values_1[{c.getAddress(), name.toStdString()}].push_back(val); + values_1[{c.getAddress(), sig.name}].push_back(val); } } } @@ -53,7 +56,7 @@ TEST_CASE("Parse can messages") { for (auto &[key, v1] : values_1) { bool found = false; for (auto &v2 : values_2) { - if (v2.address == key.first && v2.name == key.second) { + if (v2.address == key.first && key.second == v2.name.c_str()) { REQUIRE(v2.all_values.size() == v1.size()); REQUIRE(v2.all_values == v1); found = true; diff --git a/tools/cabana/tools/findsimilarbits.cc b/tools/cabana/tools/findsimilarbits.cc index ffb0e54b0e..27cb7bced8 100644 --- a/tools/cabana/tools/findsimilarbits.cc +++ b/tools/cabana/tools/findsimilarbits.cc @@ -9,6 +9,7 @@ #include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; FindSimilarBitsDlg::FindSimilarBitsDlg(QWidget *parent) : QDialog(parent, Qt::WindowFlags() | Qt::Window) { setWindowTitle(tr("Find similar bits")); diff --git a/tools/cabana/tools/findsimilarbits.h b/tools/cabana/tools/findsimilarbits.h index 53d7806a8f..ba9b063baf 100644 --- a/tools/cabana/tools/findsimilarbits.h +++ b/tools/cabana/tools/findsimilarbits.h @@ -7,6 +7,7 @@ #include #include "tools/cabana/dbcmanager.h" +using namespace dbcmanager; class FindSimilarBitsDlg : public QDialog { Q_OBJECT diff --git a/tools/cabana/util.cc b/tools/cabana/util.cc index 9843a3f00c..6415cc8e16 100644 --- a/tools/cabana/util.cc +++ b/tools/cabana/util.cc @@ -106,7 +106,7 @@ QColor getColor(const Signal *sig) { float h = 19 * (float)sig->lsb / 64.0; h = fmod(h, 1.0); - size_t hash = qHash(QString::fromStdString(sig->name)); + size_t hash = qHash(sig->name); float s = 0.25 + 0.25 * (float)(hash & 0xff) / 255.0; float v = 0.75 + 0.25 * (float)((hash >> 8) & 0xff) / 255.0; diff --git a/tools/cabana/util.h b/tools/cabana/util.h index eb5203fb0b..2717451061 100644 --- a/tools/cabana/util.h +++ b/tools/cabana/util.h @@ -9,7 +9,9 @@ #include #include -#include "opendbc/can/common_dbc.h" +#include "tools/cabana/dbcmanager.h" +using namespace dbcmanager; + class ChangeTracker { public: @@ -37,7 +39,7 @@ public: inline QString toHex(const QByteArray &dat) { return dat.toHex(' ').toUpper(); } inline char toHex(uint value) { return "0123456789ABCDEF"[value & 0xF]; } -QColor getColor(const Signal *sig); +QColor getColor(const dbcmanager::Signal *sig); class NameValidator : public QRegExpValidator { Q_OBJECT diff --git a/tools/cabana/videowidget.h b/tools/cabana/videowidget.h index 51197eedd6..1a7e27f1b3 100644 --- a/tools/cabana/videowidget.h +++ b/tools/cabana/videowidget.h @@ -11,7 +11,9 @@ #include "selfdrive/ui/qt/widgets/cameraview.h" #include "selfdrive/ui/qt/widgets/controls.h" +#include "tools/cabana/dbcmanager.h" #include "tools/cabana/streams/abstractstream.h" +using namespace dbcmanager; class Slider : public QSlider { Q_OBJECT From eb8bdc0026b49de2fc5107746baeadbd42f58550 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Fri, 17 Feb 2023 19:58:30 -0800 Subject: [PATCH 62/63] MPC path in UI (#27380) * 10s lat * Full length MPC * redfine N * Leave controls the same for now * Updates * use long plan in lat plan * interp plan * simplergit add selfdrive/controls/plannerd.py selfdrive/controls/ * expand to 10s * revert this * fix linter * vizualize * fix long test * typo * cleanup * compiles * unused * unused * bump cereal * bump cereal * use model if no uiplanm * update replay * update ref commit * bump cereal to master --- cereal | 2 +- .../controls/lib/longitudinal_planner.py | 3 ++- selfdrive/controls/plannerd.py | 20 +++++++++++++++-- selfdrive/modeld/models/driving.cc | 4 ++-- .../test/longitudinal_maneuvers/plant.py | 6 ++--- .../test/process_replay/process_replay.py | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- selfdrive/ui/qt/maps/map_helpers.cc | 2 +- selfdrive/ui/qt/maps/map_helpers.h | 2 +- selfdrive/ui/qt/onroad.cc | 2 +- selfdrive/ui/ui.cc | 22 ++++++++++++------- selfdrive/ui/ui.h | 10 +++++---- 12 files changed, 51 insertions(+), 26 deletions(-) diff --git a/cereal b/cereal index 162a26ca2d..b88523f05a 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 162a26ca2d7e5bc9a42bb5ea11e98194f722027b +Subproject commit b88523f05ac958f87a8f6d57c3f4bb20da55f216 diff --git a/selfdrive/controls/lib/longitudinal_planner.py b/selfdrive/controls/lib/longitudinal_planner.py index 0febfbafd9..2ef9051122 100755 --- a/selfdrive/controls/lib/longitudinal_planner.py +++ b/selfdrive/controls/lib/longitudinal_planner.py @@ -121,7 +121,8 @@ class LongitudinalPlanner: x, v, a, j = self.parse_model(sm['modelV2'], self.v_model_error) self.mpc.update(sm['radarState'], v_cruise, x, v, a, j) - self.v_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.v_solution) + self.v_desired_trajectory_full = np.interp(T_IDXS, T_IDXS_MPC, self.mpc.v_solution) + self.v_desired_trajectory = self.v_desired_trajectory_full[:CONTROL_N] self.a_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC, self.mpc.a_solution) self.j_desired_trajectory = np.interp(T_IDXS[:CONTROL_N], T_IDXS_MPC[:-1], self.mpc.j_solution) diff --git a/selfdrive/controls/plannerd.py b/selfdrive/controls/plannerd.py index 93d0c80dac..543274d841 100755 --- a/selfdrive/controls/plannerd.py +++ b/selfdrive/controls/plannerd.py @@ -1,12 +1,28 @@ #!/usr/bin/env python3 +import numpy as np from cereal import car from common.params import Params from common.realtime import Priority, config_realtime_process from system.swaglog import cloudlog +from selfdrive.modeld.constants import T_IDXS from selfdrive.controls.lib.longitudinal_planner import LongitudinalPlanner from selfdrive.controls.lib.lateral_planner import LateralPlanner import cereal.messaging as messaging +def cumtrapz(x, t): + return np.concatenate([[0], np.cumsum(((x[0:-1] + x[1:])/2) * np.diff(t))]) + +def publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner): + plan_odo = cumtrapz(longitudinal_planner.v_desired_trajectory_full, T_IDXS) + model_odo = cumtrapz(lateral_planner.v_plan, T_IDXS) + + ui_send = messaging.new_message('uiPlan') + ui_send.valid = sm.all_checks(service_list=['carState', 'controlsState', 'modelV2']) + uiPlan = ui_send.uiPlan + uiPlan.position.x = np.interp(plan_odo, model_odo, lateral_planner.lat_mpc.x_sol[:,0]).tolist() + uiPlan.position.y = np.interp(plan_odo, model_odo, lateral_planner.lat_mpc.x_sol[:,1]).tolist() + uiPlan.position.z = np.interp(plan_odo, model_odo, lateral_planner.path_xyz[:,2]).tolist() + pm.send('uiPlan', ui_send) def plannerd_thread(sm=None, pm=None): config_realtime_process(5, Priority.CTRL_LOW) @@ -24,7 +40,7 @@ def plannerd_thread(sm=None, pm=None): poll=['radarState', 'modelV2'], ignore_avg_freq=['radarState']) if pm is None: - pm = messaging.PubMaster(['longitudinalPlan', 'lateralPlan']) + pm = messaging.PubMaster(['longitudinalPlan', 'lateralPlan', 'uiPlan']) while True: sm.update() @@ -34,7 +50,7 @@ def plannerd_thread(sm=None, pm=None): lateral_planner.publish(sm, pm) longitudinal_planner.update(sm) longitudinal_planner.publish(sm, pm) - + publish_ui_plan(sm, pm, lateral_planner, longitudinal_planner) def main(sm=None, pm=None): plannerd_thread(sm, pm) diff --git a/selfdrive/modeld/models/driving.cc b/selfdrive/modeld/models/driving.cc index ac101bfee7..5538d6ff9b 100644 --- a/selfdrive/modeld/models/driving.cc +++ b/selfdrive/modeld/models/driving.cc @@ -200,7 +200,7 @@ void fill_meta(cereal::ModelDataV2::MetaData::Builder meta, const ModelOutputMet } template -void fill_xyzt(cereal::ModelDataV2::XYZTData::Builder xyzt, const std::array &t, +void fill_xyzt(cereal::XYZTData::Builder xyzt, const std::array &t, const std::array &x, const std::array &y, const std::array &z) { xyzt.setT(to_kj_array_ptr(t)); xyzt.setX(to_kj_array_ptr(x)); @@ -209,7 +209,7 @@ void fill_xyzt(cereal::ModelDataV2::XYZTData::Builder xyzt, const std::array -void fill_xyzt(cereal::ModelDataV2::XYZTData::Builder xyzt, const std::array &t, +void fill_xyzt(cereal::XYZTData::Builder xyzt, const std::array &t, const std::array &x, const std::array &y, const std::array &z, const std::array &x_std, const std::array &y_std, const std::array &z_std) { fill_xyzt(xyzt, t, x, y, z); diff --git a/selfdrive/test/longitudinal_maneuvers/plant.py b/selfdrive/test/longitudinal_maneuvers/plant.py index bd0556aa07..8febbf4022 100755 --- a/selfdrive/test/longitudinal_maneuvers/plant.py +++ b/selfdrive/test/longitudinal_maneuvers/plant.py @@ -99,13 +99,13 @@ class Plant: # Simulate model predicting slightly faster speed # this is to ensure lead policy is effective when model # does not predict slowdown in e2e mode - position = log.ModelDataV2.XYZTData.new_message() + position = log.XYZTData.new_message() position.x = [float(x) for x in (self.speed + 0.5) * np.array(T_IDXS)] model.modelV2.position = position - velocity = log.ModelDataV2.XYZTData.new_message() + velocity = log.XYZTData.new_message() velocity.x = [float(x) for x in (self.speed + 0.5) * np.ones_like(T_IDXS)] model.modelV2.velocity = velocity - acceleration = log.ModelDataV2.XYZTData.new_message() + acceleration = log.XYZTData.new_message() acceleration.x = [float(x) for x in np.zeros_like(T_IDXS)] model.modelV2.acceleration = acceleration diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 28fc9c452c..7dc0b139a3 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -292,7 +292,7 @@ CONFIGS = [ ProcessConfig( proc_name="plannerd", pub_sub={ - "modelV2": ["lateralPlan", "longitudinalPlan"], + "modelV2": ["lateralPlan", "longitudinalPlan", "uiPlan"], "carControl": [], "carState": [], "controlsState": [], "radarState": [], }, ignore=["logMonoTime", "valid", "longitudinalPlan.processingDelay", "longitudinalPlan.solverExecutionTime", "lateralPlan.solverExecutionTime"], diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 4a670b11ff..e9016cc27c 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -086896986a3fcdb1a03d9afd00a9abc928f9ef25 +70753c5f491de7432ff22f4ef560820ce9919b2e diff --git a/selfdrive/ui/qt/maps/map_helpers.cc b/selfdrive/ui/qt/maps/map_helpers.cc index 8d5d4e1715..95db4f2bbd 100644 --- a/selfdrive/ui/qt/maps/map_helpers.cc +++ b/selfdrive/ui/qt/maps/map_helpers.cc @@ -31,7 +31,7 @@ QGeoCoordinate to_QGeoCoordinate(const QMapbox::Coordinate &in) { QMapbox::CoordinatesCollections model_to_collection( const cereal::LiveLocationKalman::Measurement::Reader &calibratedOrientationECEF, const cereal::LiveLocationKalman::Measurement::Reader &positionECEF, - const cereal::ModelDataV2::XYZTData::Reader &line){ + const cereal::XYZTData::Reader &line){ Eigen::Vector3d ecef(positionECEF.getValue()[0], positionECEF.getValue()[1], positionECEF.getValue()[2]); Eigen::Vector3d orient(calibratedOrientationECEF.getValue()[0], calibratedOrientationECEF.getValue()[1], calibratedOrientationECEF.getValue()[2]); diff --git a/selfdrive/ui/qt/maps/map_helpers.h b/selfdrive/ui/qt/maps/map_helpers.h index 6bd5b0f067..f9c56107e3 100644 --- a/selfdrive/ui/qt/maps/map_helpers.h +++ b/selfdrive/ui/qt/maps/map_helpers.h @@ -20,7 +20,7 @@ QGeoCoordinate to_QGeoCoordinate(const QMapbox::Coordinate &in); QMapbox::CoordinatesCollections model_to_collection( const cereal::LiveLocationKalman::Measurement::Reader &calibratedOrientationECEF, const cereal::LiveLocationKalman::Measurement::Reader &positionECEF, - const cereal::ModelDataV2::XYZTData::Reader &line); + const cereal::XYZTData::Reader &line); QMapbox::CoordinatesCollections coordinate_to_collection(const QMapbox::Coordinate &c); QMapbox::CoordinatesCollections capnp_coordinate_list_to_collection(const capnp::List::Reader &coordinate_list); QMapbox::CoordinatesCollections coordinate_list_to_collection(const QList &coordinate_list); diff --git a/selfdrive/ui/qt/onroad.cc b/selfdrive/ui/qt/onroad.cc index 33b1ea8e27..98c636b0a4 100644 --- a/selfdrive/ui/qt/onroad.cc +++ b/selfdrive/ui/qt/onroad.cc @@ -674,7 +674,7 @@ void AnnotatedCameraWidget::paintGL() { if (s->worldObjectsVisible()) { if (sm.rcv_frame("modelV2") > s->scene.started_frame) { - update_model(s, sm["modelV2"].getModelV2()); + update_model(s, sm["modelV2"].getModelV2(), sm["uiPlan"].getUiPlan()); if (sm.rcv_frame("radarState") > s->scene.started_frame) { update_leads(s, radar_state, sm["modelV2"].getModelV2().getPosition()); } diff --git a/selfdrive/ui/ui.cc b/selfdrive/ui/ui.cc index 6c850b8ca4..50843de68e 100644 --- a/selfdrive/ui/ui.cc +++ b/selfdrive/ui/ui.cc @@ -35,7 +35,7 @@ static bool calib_frame_to_full_frame(const UIState *s, float in_x, float in_y, return false; } -int get_path_length_idx(const cereal::ModelDataV2::XYZTData::Reader &line, const float path_height) { +int get_path_length_idx(const cereal::XYZTData::Reader &line, const float path_height) { const auto line_x = line.getX(); int max_idx = 0; for (int i = 1; i < TRAJECTORY_SIZE && line_x[i] <= path_height; ++i) { @@ -44,7 +44,7 @@ int get_path_length_idx(const cereal::ModelDataV2::XYZTData::Reader &line, const return max_idx; } -void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, const cereal::ModelDataV2::XYZTData::Reader &line) { +void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line) { for (int i = 0; i < 2; ++i) { auto lead_data = (i == 0) ? radar_state.getLeadOne() : radar_state.getLeadTwo(); if (lead_data.getStatus()) { @@ -54,7 +54,7 @@ void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, con } } -void update_line_data(const UIState *s, const cereal::ModelDataV2::XYZTData::Reader &line, +void update_line_data(const UIState *s, const cereal::XYZTData::Reader &line, float y_off, float z_off, QPolygonF *pvd, int max_idx, bool allow_invert=true) { const auto line_x = line.getX(), line_y = line.getY(), line_z = line.getZ(); QPolygonF left_points, right_points; @@ -79,10 +79,15 @@ void update_line_data(const UIState *s, const cereal::ModelDataV2::XYZTData::Rea *pvd = left_points + right_points; } -void update_model(UIState *s, const cereal::ModelDataV2::Reader &model) { +void update_model(UIState *s, + const cereal::ModelDataV2::Reader &model, + const cereal::UiPlan::Reader &plan) { UIScene &scene = s->scene; - auto model_position = model.getPosition(); - float max_distance = std::clamp(model_position.getX()[TRAJECTORY_SIZE - 1], + auto plan_position = plan.getPosition(); + if (plan_position.getX().size() < TRAJECTORY_SIZE){ + plan_position = model.getPosition(); + } + float max_distance = std::clamp(plan_position.getX()[TRAJECTORY_SIZE - 1], MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE); // update lane lines @@ -108,8 +113,8 @@ void update_model(UIState *s, const cereal::ModelDataV2::Reader &model) { const float lead_d = lead_one.getDRel() * 2.; max_distance = std::clamp((float)(lead_d - fmin(lead_d * 0.35, 10.)), 0.0f, max_distance); } - max_idx = get_path_length_idx(model_position, max_distance); - update_line_data(s, model_position, 0.9, 1.22, &scene.track_vertices, max_idx, false); + max_idx = get_path_length_idx(plan_position, max_distance); + update_line_data(s, plan_position, 0.9, 1.22, &scene.track_vertices, max_idx, false); } void update_dmonitoring(UIState *s, const cereal::DriverStateV2::Reader &driverstate, float dm_fade_state, bool is_rhd) { @@ -248,6 +253,7 @@ UIState::UIState(QObject *parent) : QObject(parent) { "modelV2", "controlsState", "liveCalibration", "radarState", "deviceState", "roadCameraState", "pandaStates", "carParams", "driverMonitoringState", "carState", "liveLocationKalman", "driverStateV2", "wideRoadCameraState", "managerState", "navInstruction", "navRoute", "gnssMeasurements", + "uiPlan", }); Params params; diff --git a/selfdrive/ui/ui.h b/selfdrive/ui/ui.h index e3eb97a762..ad2a1fe1f4 100644 --- a/selfdrive/ui/ui.h +++ b/selfdrive/ui/ui.h @@ -198,9 +198,11 @@ public slots: }; void ui_update_params(UIState *s); -int get_path_length_idx(const cereal::ModelDataV2::XYZTData::Reader &line, const float path_height); -void update_model(UIState *s, const cereal::ModelDataV2::Reader &model); +int get_path_length_idx(const cereal::XYZTData::Reader &line, const float path_height); +void update_model(UIState *s, + const cereal::ModelDataV2::Reader &model, + const cereal::UiPlan::Reader &plan); void update_dmonitoring(UIState *s, const cereal::DriverStateV2::Reader &driverstate, float dm_fade_state, bool is_rhd); -void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, const cereal::ModelDataV2::XYZTData::Reader &line); -void update_line_data(const UIState *s, const cereal::ModelDataV2::XYZTData::Reader &line, +void update_leads(UIState *s, const cereal::RadarState::Reader &radar_state, const cereal::XYZTData::Reader &line); +void update_line_data(const UIState *s, const cereal::XYZTData::Reader &line, float y_off, float z_off, QPolygonF *pvd, int max_idx, bool allow_invert); From 7acb4a94cc77a5d2b19b86fccdf373489bcb6f8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Fri, 17 Feb 2023 20:12:31 -0800 Subject: [PATCH 63/63] Update RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index ff5b686e0c..0ea4241a35 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,6 +1,6 @@ Version 0.9.2 (2023-03-XX) ======================== - +* Draw MPC path instead of model predicted path, this is a more accurate representation of what the car will do. Version 0.9.1 (2023-02-23) ========================