From c724d1c86ce4044bfc03f1e7941871466f51a708 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Tue, 27 Feb 2024 12:22:10 +0000 Subject: [PATCH 01/35] Ford: log interesting module configuration data (#31569) * Ford: log interesting module configuration data Ford ECUs have what is called "As-Built Data" which is configured at the factory/workshop to set what packages/features are enabled on the car. But they also contain vehicle specific information (VIN, make, model, weight, wheel base...), DTC information and driver preferences. I dumped the CAN traffic for the FORScan diagnostic tool to see how it requests this information from the ECUs.
FORScan communication with IPMA (camera)
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0200'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'TESTER_PRESENT', 'hex': '00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'TESTER_PRESENT', 'hex': '00'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f190'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f188'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x88JX7T-14F397-AH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1884a5837542d3134463339372d414800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f120'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1 JX7T-14F397-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1204a5837542d3134463339372d424600000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f121'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f124'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1$JX7T-14F398-AG\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1244a5837542d3134463339382d414700000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f125'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1%JX7T-14F398-BF\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1254a5837542d3134463339382d424600000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f126'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f10a'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f111'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x11JX7T-14F403-CA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1114a5837542d3134463430332d434100000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f18c'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x8c182762191\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f18c31383237363231393100000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f162'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f110'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x10DS-JX7T-19H406-AD\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f11044532d4a5837542d3139483430362d414400000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': '0202'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd100'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd10001'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd700'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70001010101'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd701'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'd70101020000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd01'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'dd010102f8'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'f113'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'data': b'\xf1\x13JX7T-19H406-CH\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', 'hex': 'f1134a5837542d3139483430362d434800000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd08'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd0800000500500100300000000000000000000000300000000000000000200100400300100200001200f00300500000000000000300c00b00400200000000000000000000000000000000200f01201e01501400a00200200400700d02501d01700700e06405005e05503401100a000000002002002001000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'fd09ffec0001fef60002'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DTC_INFORMATION', 'hex': '028f'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DTC_INFORMATION', 'hex': '02ff50019768c253002cc401862cc418862c'}
... skip DTC requests ...
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de00020799dbaa10296516a440000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de01fd5616db5fffff557fe1f842080000000800000008000000080000000819bfe00f7c00000000000000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de02800000008000000080000000800000008337fc00800000008000000080000000800000008337fc0000000000000000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de03fffc26c3800000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04'}
{'addr': 1806, 'type': 'positive_response', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de04546a8c0000000000'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de05'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de06'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de07'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de08'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de09'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0a'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0b'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0c'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0d'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
{'addr': 1798, 'type': 'request', 'service': 'READ_DATA_BY_IDENTIFIER', 'hex': 'de0e'}
{'addr': 1806, 'type': 'negative_response', 'hex': '2231'}
Using UDS service `READ_DATA_BY_IDENTIFIER`, we can read the As-Built blocks from `0xDExx` with no diagnostic session/security access necessary. I used [Online As-Built databases](https://cyanlabs.net/asbuilt-db/) and various coding spreadsheets shared online to find values we might be interested in using for fingerprinting (both vehicle parameters and identifying the platform). ABS: - Payload tier (Base, Mid Payload Upgrade, Heavy Duty Payload Upgrade...) - Wheelbase - Steering ratio - Cruise Control Mode (Normal, Adaptive) - Enable Stop and Go PSCM: - Enable Lane Keeping Aid - Enable Traffic Jam Assist - Enable Lane Centering Assist IPMA (Q4): - Steering ratio - Wheelbase APIM (Sync 3 and Sync 4): - Steering ratio - Vehicle weight - Wheelbase There are more potentially useful signals which I haven't included although they might not be necessary: - Vehicle (Ford platform code, like "C344" or "C519" - although the source of the mapping from index to code is FORScan and not Ford themselves unless we can find a better source). - Fuel type - Vehicle length/height/front track/rear track - Tire circumference (could be useful for converting wheel speed rad/s to m/s) - Steering angle source (Pinion, Wheel) - Country code (letters, e.g. US, CA or UK) - Transmission type - CAN network architecture - More feature flags (the APIM also stores settings for ACC, LCA, BLIS) The full list of settings I have found is [here](https://github.com/incognitojam/op-notebooks/blob/main/ford/settings.py). * FwQueryConfig: add data_requests * add car_data to CarInterface get_params * Revert "add car_data to CarInterface get_params" This reverts commit aa161a6b82082705db97bea2c4317e1888a74845. * test_ford: add APIM ecu address * Revert "FwQueryConfig: add data_requests" This reverts commit dc5484a9b80be5bc61a7fdf55560b8813bc43ef7. * fix block numbers and add extra queries * bump test_fw_query_timing * add missing query whitelists * simplify asbuilt requests * use forscan block ids * formatting --------- Co-authored-by: Shane Smiskol --- selfdrive/car/ford/tests/test_ford.py | 1 + selfdrive/car/ford/values.py | 46 ++++++++++++++++++++-- selfdrive/car/tests/test_fw_fingerprint.py | 6 +-- 3 files changed, 46 insertions(+), 7 deletions(-) diff --git a/selfdrive/car/ford/tests/test_ford.py b/selfdrive/car/ford/tests/test_ford.py index fb5d07f4bf..2ad3f5db1b 100755 --- a/selfdrive/car/ford/tests/test_ford.py +++ b/selfdrive/car/ford/tests/test_ford.py @@ -19,6 +19,7 @@ ECU_ADDRESSES = { Ecu.fwdCamera: 0x706, # Image Processing Module A (IPMA) Ecu.engine: 0x7E0, # Powertrain Control Module (PCM) Ecu.shiftByWire: 0x732, # Gear Shift Module (GSM) + Ecu.debug: 0x7D0, # Accessory Protocol Interface Module (APIM) } diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index caa3eb0d37..df3201c853 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -1,11 +1,12 @@ from dataclasses import dataclass, field from enum import Enum +import panda.python.uds as uds from cereal import car from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, dbc_dict, DbcDict, PlatformConfig, Platforms from openpilot.selfdrive.car.docs_definitions import CarFootnote, CarHarness, CarInfo, CarParts, Column, \ Device -from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries +from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries, p16 Ecu = car.CarParams.Ecu @@ -140,6 +141,33 @@ class CAR(Platforms): CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} +DATA_IDENTIFIER_FORD_ASBUILT = 0xDE + +ASBUILT_BLOCKS: list[tuple[int, list]] = [ + (1, [Ecu.debug, Ecu.fwdCamera, Ecu.eps]), + (2, [Ecu.abs, Ecu.debug, Ecu.eps]), + (3, [Ecu.abs, Ecu.debug, Ecu.eps]), + (4, [Ecu.debug, Ecu.fwdCamera]), + (5, [Ecu.debug]), + (6, [Ecu.debug]), + (7, [Ecu.debug]), + (8, [Ecu.debug]), + (9, [Ecu.debug]), + (16, [Ecu.debug, Ecu.fwdCamera]), + (18, [Ecu.fwdCamera]), + (20, [Ecu.fwdCamera]), + (21, [Ecu.fwdCamera]), +] + + +def ford_asbuilt_block_request(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + +def ford_asbuilt_block_response(block_id: int): + return bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + p16(DATA_IDENTIFIER_FORD_ASBUILT + block_id - 1) + + FW_QUERY_CONFIG = FwQueryConfig( requests=[ # CAN and CAN FD queries are combined. @@ -147,19 +175,29 @@ FW_QUERY_CONFIG = FwQueryConfig( Request( [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], logging=True, ), Request( [StdQueries.TESTER_PRESENT_REQUEST, StdQueries.MANUFACTURER_SOFTWARE_VERSION_REQUEST], [StdQueries.TESTER_PRESENT_RESPONSE, StdQueries.MANUFACTURER_SOFTWARE_VERSION_RESPONSE], + whitelist_ecus=[Ecu.abs, Ecu.debug, Ecu.engine, Ecu.eps, Ecu.fwdCamera, Ecu.fwdRadar, Ecu.shiftByWire], bus=0, auxiliary=True, ), + *[Request( + [StdQueries.TESTER_PRESENT_REQUEST, ford_asbuilt_block_request(block_id)], + [StdQueries.TESTER_PRESENT_RESPONSE, ford_asbuilt_block_response(block_id)], + whitelist_ecus=ecus, + bus=0, + logging=True, + ) for block_id, ecus in ASBUILT_BLOCKS], ], extra_ecus=[ - # We are unlikely to get a response from the PCM from behind the gateway - (Ecu.engine, 0x7e0, None), - (Ecu.shiftByWire, 0x732, None), + (Ecu.engine, 0x7e0, None), # Powertrain Control Module + # Note: We are unlikely to get a response from behind the gateway + (Ecu.shiftByWire, 0x732, None), # Gear Shift Module + (Ecu.debug, 0x7d0, None), # Accessory Protocol Interface Module ], ) diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py index 1a745b4447..88c7225f22 100755 --- a/selfdrive/car/tests/test_fw_fingerprint.py +++ b/selfdrive/car/tests/test_fw_fingerprint.py @@ -263,13 +263,13 @@ class TestFwFingerprintTiming(unittest.TestCase): print(f'get_vin {name} case, query time={self.total_time / self.N} seconds') def test_fw_query_timing(self): - total_ref_time = {1: 6.5, 2: 7.4} + total_ref_time = {1: 7.8, 2: 8.7} brand_ref_times = { 1: { 'gm': 0.5, 'body': 0.1, 'chrysler': 0.3, - 'ford': 0.2, + 'ford': 1.5, 'honda': 0.55, 'hyundai': 1.05, 'mazda': 0.1, @@ -280,7 +280,7 @@ class TestFwFingerprintTiming(unittest.TestCase): 'volkswagen': 0.65, }, 2: { - 'ford': 0.3, + 'ford': 1.6, 'hyundai': 1.85, } } From 3978e7e98caef295ea60277bc7994e77b38823f3 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 06:40:46 -0600 Subject: [PATCH 02/35] [bot] Fingerprints: add missing FW versions from new users (#31572) * Export fingerprints * get these FP in --- selfdrive/car/toyota/fingerprints.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/selfdrive/car/toyota/fingerprints.py b/selfdrive/car/toyota/fingerprints.py index 12a1d46aaf..6b48408a10 100644 --- a/selfdrive/car/toyota/fingerprints.py +++ b/selfdrive/car/toyota/fingerprints.py @@ -573,6 +573,7 @@ FW_VERSIONS = { b'\x018821F6201400\x00\x00\x00\x00', ], (Ecu.fwdCamera, 0x750, 0x6d): [ + b'\x028646F12010C0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F12010D0\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F1201100\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', b'\x028646F1201200\x00\x00\x00\x008646G26011A0\x00\x00\x00\x00', @@ -843,6 +844,7 @@ FW_VERSIONS = { b'8965B47023\x00\x00\x00\x00\x00\x00', b'8965B47050\x00\x00\x00\x00\x00\x00', b'8965B47060\x00\x00\x00\x00\x00\x00', + b'8965B47070\x00\x00\x00\x00\x00\x00', ], (Ecu.abs, 0x7b0, None): [ b'F152647290\x00\x00\x00\x00\x00\x00', @@ -1024,6 +1026,7 @@ FW_VERSIONS = { b'\x02896634A13000\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', b'\x02896634A13001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A13101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', + b'\x02896634A13201\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A14001\x00\x00\x00\x00897CF1203001\x00\x00\x00\x00', b'\x02896634A14001\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', b'\x02896634A14101\x00\x00\x00\x00897CF4801001\x00\x00\x00\x00', From d3f0f76a7e33832bb7312597f85b802b50f2d757 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:16:06 -0500 Subject: [PATCH 03/35] Nissan: move to platform config (#31599) * do nissan * cleanup + fix --- selfdrive/car/__init__.py | 5 ++- selfdrive/car/nissan/interface.py | 14 +------ selfdrive/car/nissan/values.py | 68 +++++++++++++++++++------------ 3 files changed, 46 insertions(+), 41 deletions(-) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 3b749101c9..297dc582f7 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,6 +1,6 @@ # functions common among cars from collections import namedtuple -from dataclasses import dataclass, field +from dataclasses import dataclass, field, replace from enum import ReprEnum import capnp @@ -267,6 +267,9 @@ class PlatformConfig: def __hash__(self) -> int: return hash(self.platform_str) + def override(self, **kwargs): + return replace(self, **kwargs) + class Platforms(str, ReprEnum): config: PlatformConfig diff --git a/selfdrive/car/nissan/interface.py b/selfdrive/car/nissan/interface.py index aedcaa1887..a94b97de20 100644 --- a/selfdrive/car/nissan/interface.py +++ b/selfdrive/car/nissan/interface.py @@ -16,25 +16,13 @@ class CarInterface(CarInterfaceBase): ret.steerLimitTimer = 1.0 ret.steerActuatorDelay = 0.1 - ret.steerRatio = 17 ret.steerControlType = car.CarParams.SteerControlType.angle ret.radarUnavailable = True - if candidate in (CAR.ROGUE, CAR.XTRAIL): - ret.mass = 1610 - ret.wheelbase = 2.705 - ret.centerToFront = ret.wheelbase * 0.44 - elif candidate in (CAR.LEAF, CAR.LEAF_IC): - ret.mass = 1610 - ret.wheelbase = 2.705 - ret.centerToFront = ret.wheelbase * 0.44 - elif candidate == CAR.ALTIMA: + if candidate == CAR.ALTIMA: # Altima has EPS on C-CAN unlike the others that have it on V-CAN ret.safetyConfigs[0].safetyParam |= Panda.FLAG_NISSAN_ALT_EPS_BUS - ret.mass = 1492 - ret.wheelbase = 2.824 - ret.centerToFront = ret.wheelbase * 0.44 return ret diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py index c0308f9e0d..58e4eb051a 100644 --- a/selfdrive/car/nissan/values.py +++ b/selfdrive/car/nissan/values.py @@ -1,9 +1,8 @@ from dataclasses import dataclass, field -from enum import StrEnum from cereal import car from panda.python import uds -from openpilot.selfdrive.car import AngleRateLimit, dbc_dict +from openpilot.selfdrive.car import AngleRateLimit, CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car.docs_definitions import CarInfo, CarHarness, CarParts from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, StdQueries @@ -20,29 +19,52 @@ class CarControllerParams: pass -class CAR(StrEnum): - XTRAIL = "NISSAN X-TRAIL 2017" - LEAF = "NISSAN LEAF 2018" - # Leaf with ADAS ECU found behind instrument cluster instead of glovebox - # Currently the only known difference between them is the inverted seatbelt signal. - LEAF_IC = "NISSAN LEAF 2018 Instrument Cluster" - ROGUE = "NISSAN ROGUE 2019" - ALTIMA = "NISSAN ALTIMA 2020" - - @dataclass class NissanCarInfo(CarInfo): package: str = "ProPILOT Assist" car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.nissan_a])) -CAR_INFO: dict[str, NissanCarInfo | list[NissanCarInfo] | None] = { - CAR.XTRAIL: NissanCarInfo("Nissan X-Trail 2017"), - CAR.LEAF: NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), - CAR.LEAF_IC: None, # same platforms - CAR.ROGUE: NissanCarInfo("Nissan Rogue 2018-20"), - CAR.ALTIMA: NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b])), -} +@dataclass(frozen=True) +class NissanCarSpecs(CarSpecs): + centerToFrontRatio: float = 0.44 + steerRatio: float = 17. + + +@dataclass(frozen=True) +class NissanPlaformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('nissan_x_trail_2017_generated', None)) + + +class CAR(Platforms): + XTRAIL = NissanPlaformConfig( + "NISSAN X-TRAIL 2017", + NissanCarInfo("Nissan X-Trail 2017"), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + LEAF = NissanPlaformConfig( + "NISSAN LEAF 2018", + NissanCarInfo("Nissan Leaf 2018-23", video_link="https://youtu.be/vaMbtAh_0cY"), + dbc_dict=dbc_dict('nissan_leaf_2018_generated', None), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + # Leaf with ADAS ECU found behind instrument cluster instead of glovebox + # Currently the only known difference between them is the inverted seatbelt signal. + LEAF_IC = LEAF.override(platform_str="NISSAN LEAF 2018 Instrument Cluster", car_info=None) + ROGUE = NissanPlaformConfig( + "NISSAN ROGUE 2019", + NissanCarInfo("Nissan Rogue 2018-20"), + specs=NissanCarSpecs(mass=1610, wheelbase=2.705) + ) + ALTIMA = NissanPlaformConfig( + "NISSAN ALTIMA 2020", + NissanCarInfo("Nissan Altima 2019-20", car_parts=CarParts.common([CarHarness.nissan_b])), + specs=NissanCarSpecs(mass=1492, wheelbase=2.824) + ) + + +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() # Default diagnostic session NISSAN_DIAGNOSTIC_REQUEST_KWP = bytes([uds.SERVICE_TYPE.DIAGNOSTIC_SESSION_CONTROL, 0x81]) @@ -88,11 +110,3 @@ FW_QUERY_CONFIG = FwQueryConfig( ), ]], ) - -DBC = { - CAR.XTRAIL: dbc_dict('nissan_x_trail_2017_generated', None), - CAR.LEAF: dbc_dict('nissan_leaf_2018_generated', None), - CAR.LEAF_IC: dbc_dict('nissan_leaf_2018_generated', None), - CAR.ROGUE: dbc_dict('nissan_x_trail_2017_generated', None), - CAR.ALTIMA: dbc_dict('nissan_x_trail_2017_generated', None), -} From 666c41d96923b1826f34a971b568f7d7754b4070 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:16:22 -0500 Subject: [PATCH 04/35] Chrylser: move to platform config (#31600) * do chrysler * chrysler specs * cleanup Co-authored-by: Shane Smiskol --------- Co-authored-by: Shane Smiskol --- selfdrive/car/chrysler/interface.py | 12 --- selfdrive/car/chrysler/values.py | 131 +++++++++++++++++----------- 2 files changed, 79 insertions(+), 64 deletions(-) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 32a4f5dfcf..34df32762d 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -24,7 +24,6 @@ class CarInterface(CarInterfaceBase): elif candidate in RAM_DT: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_RAM_DT - ret.minSteerSpeed = 3.8 # m/s CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) if candidate not in RAM_CARS: # Newer FW versions standard on the following platforms, or flashed by a dealer onto older platforms have a higher minimum steering speed. @@ -35,10 +34,6 @@ class CarInterface(CarInterfaceBase): # Chrysler if candidate in (CAR.PACIFICA_2017_HYBRID, CAR.PACIFICA_2018, CAR.PACIFICA_2018_HYBRID, CAR.PACIFICA_2019_HYBRID, CAR.PACIFICA_2020, CAR.DODGE_DURANGO): - ret.mass = 2242. - ret.wheelbase = 3.089 - ret.steerRatio = 16.2 # Pacifica Hybrid 2017 - 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]] @@ -46,9 +41,6 @@ class CarInterface(CarInterfaceBase): # Jeep elif candidate in (CAR.JEEP_GRAND_CHEROKEE, CAR.JEEP_GRAND_CHEROKEE_2019): - ret.mass = 1778 - ret.wheelbase = 2.71 - ret.steerRatio = 16.7 ret.steerActuatorDelay = 0.2 ret.lateralTuning.init('pid') @@ -60,9 +52,6 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.RAM_1500: ret.steerActuatorDelay = 0.2 ret.wheelbase = 3.88 - ret.steerRatio = 16.3 - ret.mass = 2493. - ret.minSteerSpeed = 14.5 # Older EPS FW allow steer to zero if any(fw.ecu == 'eps' and b"68" < fw.fwVersion[:4] <= b"6831" for fw in car_fw): ret.minSteerSpeed = 0. @@ -72,7 +61,6 @@ class CarInterface(CarInterfaceBase): ret.wheelbase = 3.785 ret.steerRatio = 15.61 ret.mass = 3405. - ret.minSteerSpeed = 16 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, 1.0, False) else: diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index a7eec8fe5a..a94512608a 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -1,9 +1,9 @@ -from enum import IntFlag, StrEnum +from enum import IntFlag from dataclasses import dataclass, field from cereal import car from panda.python import uds -from openpilot.selfdrive.car import dbc_dict +from openpilot.selfdrive.car import CarSpecs, DbcDict, PlatformConfig, Platforms, dbc_dict from openpilot.selfdrive.car.docs_definitions import CarHarness, CarInfo, CarParts from openpilot.selfdrive.car.fw_query_definitions import FwQueryConfig, Request, p16 @@ -13,25 +13,89 @@ Ecu = car.CarParams.Ecu class ChryslerFlags(IntFlag): HIGHER_MIN_STEERING_SPEED = 1 +@dataclass +class ChryslerCarInfo(CarInfo): + package: str = "Adaptive Cruise Control (ACC)" + car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) + + +@dataclass +class ChryslerPlatformConfig(PlatformConfig): + dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None)) + + +@dataclass +class ChryslerCarSpecs(CarSpecs): + minSteerSpeed: float = 3.8 # m/s + -class CAR(StrEnum): +class CAR(Platforms): # Chrysler - PACIFICA_2017_HYBRID = "CHRYSLER PACIFICA HYBRID 2017" - PACIFICA_2018_HYBRID = "CHRYSLER PACIFICA HYBRID 2018" - PACIFICA_2019_HYBRID = "CHRYSLER PACIFICA HYBRID 2019" - PACIFICA_2018 = "CHRYSLER PACIFICA 2018" - PACIFICA_2020 = "CHRYSLER PACIFICA 2020" + PACIFICA_2017_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2017", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), + specs=ChryslerCarSpecs(mass=2242., wheelbase=3.089, steerRatio=16.2), + ) + PACIFICA_2018_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2018", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2019_HYBRID = ChryslerPlatformConfig( + "CHRYSLER PACIFICA HYBRID 2019", + ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2018 = ChryslerPlatformConfig( + "CHRYSLER PACIFICA 2018", + ChryslerCarInfo("Chrysler Pacifica 2017-18"), + specs=PACIFICA_2017_HYBRID.specs, + ) + PACIFICA_2020 = ChryslerPlatformConfig( + "CHRYSLER PACIFICA 2020", + [ + ChryslerCarInfo("Chrysler Pacifica 2019-20"), + ChryslerCarInfo("Chrysler Pacifica 2021-23", package="All"), + ], + specs=PACIFICA_2017_HYBRID.specs, + ) # Dodge - DODGE_DURANGO = "DODGE DURANGO 2021" + DODGE_DURANGO = ChryslerPlatformConfig( + "DODGE DURANGO 2021", + ChryslerCarInfo("Dodge Durango 2020-21"), + specs=PACIFICA_2017_HYBRID.specs, + ) # Jeep - JEEP_GRAND_CHEROKEE = "JEEP GRAND CHEROKEE V6 2018" # includes 2017 Trailhawk - JEEP_GRAND_CHEROKEE_2019 = "JEEP GRAND CHEROKEE 2019" # includes 2020 Trailhawk + JEEP_GRAND_CHEROKEE = ChryslerPlatformConfig( # includes 2017 Trailhawk + "JEEP GRAND CHEROKEE V6 2018", + ChryslerCarInfo("Jeep Grand Cherokee 2016-18", video_link="https://www.youtube.com/watch?v=eLR9o2JkuRk"), + specs=ChryslerCarSpecs(mass=1778., wheelbase=2.71, steerRatio=16.7), + ) + + JEEP_GRAND_CHEROKEE_2019 = ChryslerPlatformConfig( # includes 2020 Trailhawk + "JEEP GRAND CHEROKEE 2019", + ChryslerCarInfo("Jeep Grand Cherokee 2019-21", video_link="https://www.youtube.com/watch?v=jBe4lWnRSu4"), + specs=JEEP_GRAND_CHEROKEE.specs, + ) # Ram - RAM_1500 = "RAM 1500 5TH GEN" - RAM_HD = "RAM HD 5TH GEN" + RAM_1500 = ChryslerPlatformConfig( + "RAM 1500 5TH GEN", + ChryslerCarInfo("Ram 1500 2019-24", car_parts=CarParts.common([CarHarness.ram])), + dbc_dict('chrysler_ram_dt_generated', None), + specs=ChryslerCarSpecs(mass=2493., wheelbase=3.88, steerRatio=16.3, minSteerSpeed=14.5), + ) + RAM_HD = ChryslerPlatformConfig( + "RAM HD 5TH GEN", + [ + ChryslerCarInfo("Ram 2500 2020-24", car_parts=CarParts.common([CarHarness.ram])), + ChryslerCarInfo("Ram 3500 2019-22", car_parts=CarParts.common([CarHarness.ram])), + ], + dbc_dict('chrysler_ram_hd_generated', None), + specs=ChryslerCarSpecs(mass=3405., wheelbase=3.785, steerRatio=15.61, minSteerSpeed=16.), + ) class CarControllerParams: @@ -59,32 +123,6 @@ RAM_HD = {CAR.RAM_HD, } RAM_CARS = RAM_DT | RAM_HD -@dataclass -class ChryslerCarInfo(CarInfo): - package: str = "Adaptive Cruise Control (ACC)" - car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) - - -CAR_INFO: dict[str, ChryslerCarInfo | list[ChryslerCarInfo] | None] = { - CAR.PACIFICA_2017_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2017"), - CAR.PACIFICA_2018_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2018"), - CAR.PACIFICA_2019_HYBRID: ChryslerCarInfo("Chrysler Pacifica Hybrid 2019-23"), - CAR.PACIFICA_2018: ChryslerCarInfo("Chrysler Pacifica 2017-18"), - CAR.PACIFICA_2020: [ - ChryslerCarInfo("Chrysler Pacifica 2019-20"), - ChryslerCarInfo("Chrysler Pacifica 2021-23", package="All"), - ], - CAR.JEEP_GRAND_CHEROKEE: ChryslerCarInfo("Jeep Grand Cherokee 2016-18", video_link="https://www.youtube.com/watch?v=eLR9o2JkuRk"), - CAR.JEEP_GRAND_CHEROKEE_2019: ChryslerCarInfo("Jeep Grand Cherokee 2019-21", video_link="https://www.youtube.com/watch?v=jBe4lWnRSu4"), - CAR.DODGE_DURANGO: ChryslerCarInfo("Dodge Durango 2020-21"), - CAR.RAM_1500: ChryslerCarInfo("Ram 1500 2019-24", car_parts=CarParts.common([CarHarness.ram])), - CAR.RAM_HD: [ - ChryslerCarInfo("Ram 2500 2020-24", car_parts=CarParts.common([CarHarness.ram])), - ChryslerCarInfo("Ram 3500 2019-22", car_parts=CarParts.common([CarHarness.ram])), - ], -} - - CHRYSLER_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ p16(0xf132) CHRYSLER_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ @@ -124,16 +162,5 @@ FW_QUERY_CONFIG = FwQueryConfig( ], ) - -DBC = { - CAR.PACIFICA_2017_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2018: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2020: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2018_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.PACIFICA_2019_HYBRID: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.DODGE_DURANGO: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.JEEP_GRAND_CHEROKEE: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.JEEP_GRAND_CHEROKEE_2019: dbc_dict('chrysler_pacifica_2017_hybrid_generated', 'chrysler_pacifica_2017_hybrid_private_fusion'), - CAR.RAM_1500: dbc_dict('chrysler_ram_dt_generated', None), - CAR.RAM_HD: dbc_dict('chrysler_ram_hd_generated', None), -} +CAR_INFO = CAR.create_carinfo_map() +DBC = CAR.create_dbc_map() From d457ed9d50801905b762c870c4799e734dea05b1 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 13:23:13 -0500 Subject: [PATCH 05/35] chrysler: freeze dataclass + remove more from interface (#31613) * fix * fix --- selfdrive/car/chrysler/interface.py | 3 --- selfdrive/car/chrysler/values.py | 4 ++-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index 34df32762d..eb40bc6f6e 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -58,9 +58,6 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.RAM_HD: ret.steerActuatorDelay = 0.2 - ret.wheelbase = 3.785 - ret.steerRatio = 15.61 - ret.mass = 3405. CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, 1.0, False) else: diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index a94512608a..1cc51753d4 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -19,12 +19,12 @@ class ChryslerCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) -@dataclass +@dataclass(frozen=True) class ChryslerPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None)) -@dataclass +@dataclass(frozen=True) class ChryslerCarSpecs(CarSpecs): minSteerSpeed: float = 3.8 # m/s From 0e41bf34746854869ad0d319fbb6bb765288ce50 Mon Sep 17 00:00:00 2001 From: Cameron Clough Date: Tue, 27 Feb 2024 18:59:27 +0000 Subject: [PATCH 06/35] Ford: fix As-Built request identifier (#31609) Should be 0xDE00 not 0xDE --- selfdrive/car/ford/values.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index df3201c853..1008d68b98 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -141,7 +141,7 @@ class CAR(Platforms): CANFD_CAR = {CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1, CAR.MUSTANG_MACH_E_MK1} -DATA_IDENTIFIER_FORD_ASBUILT = 0xDE +DATA_IDENTIFIER_FORD_ASBUILT = 0xDE00 ASBUILT_BLOCKS: list[tuple[int, list]] = [ (1, [Ecu.debug, Ecu.fwdCamera, Ecu.eps]), From 402ac424d90f7b66dfe100b4073a43bf13570081 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 27 Feb 2024 11:09:48 -0800 Subject: [PATCH 07/35] auto PR comments (#30675) * auto PR comments * little more * test * update action * cleanup --- .github/workflows/auto_pr_review.yaml | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index abb6c38d6b..de07ed118f 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,6 +34,23 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" + comment: + runs-on: ubuntu-latest + steps: + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + with: + message: | + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + check-pr-template: runs-on: ubuntu-latest permissions: @@ -41,7 +58,7 @@ jobs: issues: write pull-requests: write actions: read - if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: From dc3728134055bd422abac4f005e1ecbae46e6167 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 14:55:19 -0500 Subject: [PATCH 08/35] typo (#31618) dataset --- docs/CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/CONTRIBUTING.md b/docs/CONTRIBUTING.md index 30f4e0dfd3..755ca82220 100644 --- a/docs/CONTRIBUTING.md +++ b/docs/CONTRIBUTING.md @@ -62,4 +62,4 @@ A good pull request has all of the following: * Consider opting into driver camera uploads to improve the driver monitoring model. * Connect your device to Wi-Fi regularly, so that we can pull data for training better driving models. * Run the `nightly` branch and report issues. This branch is like `master` but it's built just like a release. -* Annotate images in the [comma10k dateset](https://github.com/commaai/comma10k). +* Annotate images in the [comma10k dataset](https://github.com/commaai/comma10k). From 47013fd0a4a322da39cbbdf6bd8129d49abb295d Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Tue, 27 Feb 2024 12:06:53 -0800 Subject: [PATCH 09/35] Revert "auto PR comments (#30675)" This reverts commit 402ac424d90f7b66dfe100b4073a43bf13570081. --- .github/workflows/auto_pr_review.yaml | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index de07ed118f..abb6c38d6b 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,23 +34,6 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" - comment: - runs-on: ubuntu-latest - steps: - - name: comment - uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 - with: - message: | - Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: - * Convert your PR to a draft unless it's ready to review - * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) - * Before marking as "ready for review", ensure: - * the goal is clearly stated in the description - * all the tests are passing - * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) - * include a route or your device' dongle ID if relevant - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - check-pr-template: runs-on: ubuntu-latest permissions: @@ -58,7 +41,7 @@ jobs: issues: write pull-requests: write actions: read - if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: From f293f7bad4d6675b70a97d303f1321fb6cfc9182 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 16:17:56 -0500 Subject: [PATCH 10/35] scons: move cereal library exports to cereal submodule (#31617) * cleanup-cereal * bump --- SConstruct | 9 --------- cereal | 2 +- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/SConstruct b/SConstruct index b04e3903ed..4d4f9ad4fe 100644 --- a/SConstruct +++ b/SConstruct @@ -96,8 +96,6 @@ lenv = { rpath = lenv["LD_LIBRARY_PATH"].copy() if arch == "larch64": - lenv["LD_LIBRARY_PATH"] += ['/data/data/com.termux/files/usr/lib'] - cpppath = [ "#third_party/opencl/include", ] @@ -360,13 +358,6 @@ Export('common', 'gpucommon') # Build cereal and messaging SConscript(['cereal/SConscript']) -cereal = [File('#cereal/libcereal.a')] -messaging = [File('#cereal/libmessaging.a')] -visionipc = [File('#cereal/libvisionipc.a')] -messaging_python = [File('#cereal/messaging/messaging_pyx.so')] - -Export('cereal', 'messaging', 'messaging_python', 'visionipc') - # Build other submodules SConscript([ 'body/board/SConscript', diff --git a/cereal b/cereal index a4255106b7..2012d9fd16 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit a4255106b7255e00ae04162f7aa14aa3cae339c3 +Subproject commit 2012d9fd16f62c737951ce2d1eb19d39f0c7615f From c05b37979d49c0a586b56db9294aa061c2c079e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Tue, 27 Feb 2024 13:23:04 -0800 Subject: [PATCH 11/35] Wheeled body (#31614) * Wheeled body * 100hz only for balance * No carparams in locationd no more * Update ref --- common/params.cc | 1 - selfdrive/car/body/carcontroller.py | 20 ++----------------- selfdrive/locationd/locationd.cc | 8 +++----- .../test/process_replay/process_replay.py | 2 +- selfdrive/test/process_replay/ref_commit | 2 +- 5 files changed, 7 insertions(+), 26 deletions(-) diff --git a/common/params.cc b/common/params.cc index eb75705ca3..aef2cbdecd 100644 --- a/common/params.cc +++ b/common/params.cc @@ -207,7 +207,6 @@ std::unordered_map keys = { {"UpdaterLastFetchTime", PERSISTENT}, {"Version", PERSISTENT}, {"VisionRadarToggle", PERSISTENT}, - {"WheeledBody", PERSISTENT}, }; } // namespace diff --git a/selfdrive/car/body/carcontroller.py b/selfdrive/car/body/carcontroller.py index 1dad8e796a..d15f11d3a4 100644 --- a/selfdrive/car/body/carcontroller.py +++ b/selfdrive/car/body/carcontroller.py @@ -1,6 +1,5 @@ import numpy as np -from openpilot.common.params import Params from openpilot.common.realtime import DT_CTRL from opendbc.can.packer import CANPacker from openpilot.selfdrive.car.body import bodycan @@ -20,18 +19,13 @@ class CarController: self.frame = 0 self.packer = CANPacker(dbc_name) - # Speed, balance and turn PIDs - self.speed_pid = PIDController(0.115, k_i=0.23, rate=1/DT_CTRL) - self.balance_pid = PIDController(1300, k_i=0, k_d=280, rate=1/DT_CTRL) + # PIDs self.turn_pid = PIDController(110, k_i=11.5, rate=1/DT_CTRL) self.wheeled_speed_pid = PIDController(110, k_i=11.5, rate=1/DT_CTRL) self.torque_r_filtered = 0. self.torque_l_filtered = 0. - params = Params() - self.wheeled_body = params.get("WheeledBody") - @staticmethod def deadband_filter(torque, deadband): if torque > 0: @@ -55,17 +49,7 @@ class CarController: speed_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl + CS.out.wheelSpeeds.fr) / 2. speed_error = speed_desired - speed_measured - if self.wheeled_body is None: - freeze_integrator = ((speed_error < 0 and self.speed_pid.error_integral <= -MAX_POS_INTEGRATOR) or - (speed_error > 0 and self.speed_pid.error_integral >= MAX_POS_INTEGRATOR)) - angle_setpoint = self.speed_pid.update(speed_error, freeze_integrator=freeze_integrator) - - # Clip angle error, this is enough to get up from stands - angle_error = np.clip((-CC.orientationNED[1]) - angle_setpoint, -MAX_ANGLE_ERROR, MAX_ANGLE_ERROR) - angle_error_rate = np.clip(-CC.angularVelocity[1], -1., 1.) - torque = self.balance_pid.update(angle_error, error_rate=angle_error_rate) - else: - torque = self.wheeled_speed_pid.update(speed_error, freeze_integrator=False) + torque = self.wheeled_speed_pid.update(speed_error, freeze_integrator=False) speed_diff_measured = SPEED_FROM_RPM * (CS.out.wheelSpeeds.fl - CS.out.wheelSpeeds.fr) turn_error = speed_diff_measured - speed_diff_desired diff --git a/selfdrive/locationd/locationd.cc b/selfdrive/locationd/locationd.cc index e32ed78a3e..1050d68b9b 100644 --- a/selfdrive/locationd/locationd.cc +++ b/selfdrive/locationd/locationd.cc @@ -691,10 +691,9 @@ int Localizer::locationd_thread() { this->configure_gnss_source(source); const std::initializer_list service_list = {gps_location_socket, "cameraOdometry", "liveCalibration", - "carState", "carParams", "accelerometer", "gyroscope"}; + "carState", "accelerometer", "gyroscope"}; - // TODO: remove carParams once we're always sending at 100Hz - SubMaster sm(service_list, {}, nullptr, {gps_location_socket, "carParams"}); + SubMaster sm(service_list, {}, nullptr, {gps_location_socket}); PubMaster pm({"liveLocationKalman"}); uint64_t cnt = 0; @@ -718,8 +717,7 @@ int Localizer::locationd_thread() { filterInitialized = sm.allAliveAndValid(); } - // 100Hz publish for notcars, 20Hz for cars - const char* trigger_msg = sm["carParams"].getCarParams().getNotCar() ? "accelerometer" : "cameraOdometry"; + const char* trigger_msg = "cameraOdometry"; if (sm.updated(trigger_msg)) { bool inputsOK = sm.allValid() && this->are_inputs_ok(); bool gpsOK = this->is_gps_ok(); diff --git a/selfdrive/test/process_replay/process_replay.py b/selfdrive/test/process_replay/process_replay.py index 4fb3e3c4de..5119be0a8c 100755 --- a/selfdrive/test/process_replay/process_replay.py +++ b/selfdrive/test/process_replay/process_replay.py @@ -512,7 +512,7 @@ CONFIGS = [ proc_name="locationd", pubs=[ "cameraOdometry", "accelerometer", "gyroscope", "gpsLocationExternal", - "liveCalibration", "carState", "carParams", "gpsLocation" + "liveCalibration", "carState", "gpsLocation" ], subs=["liveLocationKalman"], ignore=["logMonoTime"], diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index fc38f87310..9c627fb7c9 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -d0cdea7eb15f3cac8a921f7ace3eaa6baebb4fd5 +47609e372bf616932c4dca74d2616c3d97fa2443 From 19db56b1f6a86a6a250e6b69f1533ae02d1fb367 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 17:06:18 -0500 Subject: [PATCH 12/35] tici tests: remove pytest.main (#31622) pytest.main is bad! --- selfdrive/test/test_onroad.py | 2 +- system/hardware/tici/tests/test_hardware.py | 2 +- system/hardware/tici/tests/test_power_draw.py | 3 +-- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/selfdrive/test/test_onroad.py b/selfdrive/test/test_onroad.py index de8a4420b3..8f8c93ecff 100755 --- a/selfdrive/test/test_onroad.py +++ b/selfdrive/test/test_onroad.py @@ -424,4 +424,4 @@ class TestOnroad(unittest.TestCase): if __name__ == "__main__": - pytest.main() + unittest.main() diff --git a/system/hardware/tici/tests/test_hardware.py b/system/hardware/tici/tests/test_hardware.py index 0c436595ee..6c41c383a0 100755 --- a/system/hardware/tici/tests/test_hardware.py +++ b/system/hardware/tici/tests/test_hardware.py @@ -25,4 +25,4 @@ class TestHardware(unittest.TestCase): if __name__ == "__main__": - pytest.main() + unittest.main() diff --git a/system/hardware/tici/tests/test_power_draw.py b/system/hardware/tici/tests/test_power_draw.py index 352fcdf18a..180ec155e4 100755 --- a/system/hardware/tici/tests/test_power_draw.py +++ b/system/hardware/tici/tests/test_power_draw.py @@ -1,6 +1,5 @@ #!/usr/bin/env python3 from collections import defaultdict, deque -import sys import pytest import unittest import time @@ -132,4 +131,4 @@ class TestPowerDraw(unittest.TestCase): if __name__ == "__main__": - pytest.main(sys.argv) + unittest.main() From 262b328ad706194425479b1a56af9321d1a0c97a Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Tue, 27 Feb 2024 17:17:01 -0500 Subject: [PATCH 13/35] ban pytest.main (#31623) ban it! --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index ac5bb0922c..99a8602460 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -190,6 +190,7 @@ lint.flake8-implicit-str-concat.allow-multiline=false "system".msg = "Use openpilot.system" "third_party".msg = "Use openpilot.third_party" "tools".msg = "Use openpilot.tools" +"pytest.main".msg = "pytest.main requires special handling that is easy to mess up!" [tool.coverage.run] concurrency = ["multiprocessing", "thread"] From 56e343b3f1e0117d379ad4582170d51609599530 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 19:41:52 -0600 Subject: [PATCH 14/35] Honda Accord: label non-essential ECUs (#31624) * note non-essential ecus * do accordh --- selfdrive/car/honda/values.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index a2ef757d15..f573296609 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -207,6 +207,8 @@ FW_QUERY_CONFIG = FwQueryConfig( Ecu.combinationMeter: [CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.gateway: [CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.electricBrakeBooster: [CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE + Ecu.hud: [CAR.ACCORD, CAR.ACCORDH], # existence correlates with trim level }, extra_ecus=[ # The only other ECU on PT bus accessible by camera on radarless Civic From ce6637cd8ffdd9eef39a57fe67c3528c55b11c68 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 22:09:02 -0600 Subject: [PATCH 15/35] Honda Accord: allow fingerprinting without comma power (#31477) * Do Accord * add comment * good test * this catches the accord/accordh issue! * as expected, only if both radar&camera have in common FW does the test fail * cmt * clean up * better * Use HondaFlags * detect alt brake * for test * hypothesis isn't installed * test failure * works * Revert " works" This reverts commit bfc0d808abe548630e6507431f13b01e8a1316cb. * Revert "test failure" This reverts commit 10ab6eb63ccd411740751b742f31fd610397fe8e. * Revert "hypothesis isn't installed" This reverts commit d474cc3f0ed7e84fe8bd24f452b3315fd2b8d47c. * Revert "for test" This reverts commit 98e039f4fc0189ccb57c1dae6b344209ef15eb1c. * this is important too * clean up * merge accord fingerprints, test * remove duplicates * accordh doesn't have these * rm * no unknown * start over, merge platforms * add cmt * note non-essential ecus * add non essential obd ecus * combine FW * format fingerprints (remove dups) * migrate test models segs * cmt * Update ref_commit * clean up --- selfdrive/car/honda/carstate.py | 4 +- selfdrive/car/honda/fingerprints.py | 85 ++++++++---------------- selfdrive/car/honda/interface.py | 4 +- selfdrive/car/honda/values.py | 22 +++--- selfdrive/car/tests/routes.py | 4 +- selfdrive/car/tests/test_models_segs.txt | 4 +- selfdrive/car/torque_data/params.toml | 3 +- selfdrive/test/process_replay/ref_commit | 2 +- 8 files changed, 49 insertions(+), 79 deletions(-) diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 9025f72397..4f5337813b 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -64,7 +64,7 @@ def get_can_messages(CP, gearbox_msg): messages.append(("CRUISE_PARAMS", 50)) # TODO: clean this up - if CP.carFingerprint in (CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, + if CP.carFingerprint in (CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G): pass elif CP.carFingerprint in (CAR.ODYSSEY_CHN, CAR.FREED, CAR.HRV): @@ -129,7 +129,7 @@ class CarState(CarStateBase): # panda checks if the signal is non-zero ret.standstill = cp.vl["ENGINE_DATA"]["XMISSION_SPEED"] < 1e-5 # TODO: find a common signal across all cars - if self.CP.carFingerprint in (CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, + if self.CP.carFingerprint in (CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G): ret.doorOpen = bool(cp.vl["SCM_FEEDBACK"]["DRIVERS_DOOR_OPEN"]) elif self.CP.carFingerprint in (CAR.ODYSSEY_CHN, CAR.FREED, CAR.HRV): diff --git a/selfdrive/car/honda/fingerprints.py b/selfdrive/car/honda/fingerprints.py index 359ae83b15..0ae39751f9 100644 --- a/selfdrive/car/honda/fingerprints.py +++ b/selfdrive/car/honda/fingerprints.py @@ -48,6 +48,7 @@ FW_VERSIONS = { ], (Ecu.shiftByWire, 0x18da0bf1, None): [ b'54008-TVC-A910\x00\x00', + b'54008-TWA-A910\x00\x00', ], (Ecu.transmission, 0x18da1ef1, None): [ b'28101-6A7-A220\x00\x00', @@ -89,6 +90,12 @@ FW_VERSIONS = { b'57114-TVA-C530\x00\x00', b'57114-TVA-E520\x00\x00', b'57114-TVE-H250\x00\x00', + b'57114-TWA-A040\x00\x00', + b'57114-TWA-A050\x00\x00', + b'57114-TWA-A530\x00\x00', + b'57114-TWA-B520\x00\x00', + b'57114-TWA-C510\x00\x00', + b'57114-TWB-H030\x00\x00', ], (Ecu.eps, 0x18da30f1, None): [ b'39990-TBX-H120\x00\x00', @@ -100,6 +107,7 @@ FW_VERSIONS = { b'39990-TVA-X030\x00\x00', b'39990-TVA-X040\x00\x00', b'39990-TVE-H130\x00\x00', + b'39990-TWB-H120\x00\x00', ], (Ecu.srs, 0x18da53f1, None): [ b'77959-TBX-H230\x00\x00', @@ -108,6 +116,9 @@ FW_VERSIONS = { b'77959-TVA-H230\x00\x00', b'77959-TVA-L420\x00\x00', b'77959-TVA-X330\x00\x00', + b'77959-TWA-A440\x00\x00', + b'77959-TWA-L420\x00\x00', + b'77959-TWB-H220\x00\x00', ], (Ecu.combinationMeter, 0x18da60f1, None): [ b'78109-TBX-H310\x00\x00', @@ -141,7 +152,19 @@ FW_VERSIONS = { b'78109-TVC-M510\x00\x00', b'78109-TVC-YF10\x00\x00', b'78109-TVE-H610\x00\x00', + b'78109-TWA-A010\x00\x00', + b'78109-TWA-A020\x00\x00', + b'78109-TWA-A030\x00\x00', + b'78109-TWA-A110\x00\x00', + b'78109-TWA-A120\x00\x00', + b'78109-TWA-A130\x00\x00', b'78109-TWA-A210\x00\x00', + b'78109-TWA-A220\x00\x00', + b'78109-TWA-A230\x00\x00', + b'78109-TWA-A610\x00\x00', + b'78109-TWA-H210\x00\x00', + b'78109-TWA-L010\x00\x00', + b'78109-TWA-L210\x00\x00', ], (Ecu.hud, 0x18da61f1, None): [ b'78209-TVA-A010\x00\x00', @@ -158,6 +181,9 @@ FW_VERSIONS = { b'36802-TVE-H070\x00\x00', b'36802-TWA-A070\x00\x00', b'36802-TWA-A080\x00\x00', + b'36802-TWA-A210\x00\x00', + b'36802-TWA-A330\x00\x00', + b'36802-TWB-H060\x00\x00', ], (Ecu.fwdCamera, 0x18dab5f1, None): [ b'36161-TBX-H130\x00\x00', @@ -166,72 +192,17 @@ FW_VERSIONS = { b'36161-TVC-A330\x00\x00', b'36161-TVE-H050\x00\x00', b'36161-TWA-A070\x00\x00', + b'36161-TWA-A330\x00\x00', + b'36161-TWB-H040\x00\x00', ], (Ecu.gateway, 0x18daeff1, None): [ b'38897-TVA-A010\x00\x00', b'38897-TVA-A020\x00\x00', b'38897-TVA-A230\x00\x00', b'38897-TVA-A240\x00\x00', - ], - }, - CAR.ACCORDH: { - (Ecu.gateway, 0x18daeff1, None): [ b'38897-TWA-A120\x00\x00', b'38897-TWD-J020\x00\x00', ], - (Ecu.vsa, 0x18da28f1, None): [ - b'57114-TWA-A040\x00\x00', - b'57114-TWA-A050\x00\x00', - b'57114-TWA-A530\x00\x00', - b'57114-TWA-B520\x00\x00', - b'57114-TWA-C510\x00\x00', - b'57114-TWB-H030\x00\x00', - ], - (Ecu.srs, 0x18da53f1, None): [ - b'77959-TWA-A440\x00\x00', - b'77959-TWA-L420\x00\x00', - b'77959-TWB-H220\x00\x00', - ], - (Ecu.combinationMeter, 0x18da60f1, None): [ - b'78109-TWA-A010\x00\x00', - b'78109-TWA-A020\x00\x00', - b'78109-TWA-A030\x00\x00', - b'78109-TWA-A110\x00\x00', - b'78109-TWA-A120\x00\x00', - b'78109-TWA-A130\x00\x00', - b'78109-TWA-A210\x00\x00', - b'78109-TWA-A220\x00\x00', - b'78109-TWA-A230\x00\x00', - b'78109-TWA-A610\x00\x00', - b'78109-TWA-H210\x00\x00', - b'78109-TWA-L010\x00\x00', - b'78109-TWA-L210\x00\x00', - ], - (Ecu.shiftByWire, 0x18da0bf1, None): [ - b'54008-TWA-A910\x00\x00', - ], - (Ecu.hud, 0x18da61f1, None): [ - b'78209-TVA-A010\x00\x00', - b'78209-TVA-A110\x00\x00', - ], - (Ecu.fwdCamera, 0x18dab5f1, None): [ - b'36161-TWA-A070\x00\x00', - b'36161-TWA-A330\x00\x00', - b'36161-TWB-H040\x00\x00', - ], - (Ecu.fwdRadar, 0x18dab0f1, None): [ - b'36802-TWA-A070\x00\x00', - b'36802-TWA-A080\x00\x00', - b'36802-TWA-A210\x00\x00', - b'36802-TWA-A330\x00\x00', - b'36802-TWB-H060\x00\x00', - ], - (Ecu.eps, 0x18da30f1, None): [ - b'39990-TVA-A150\x00\x00', - b'39990-TVA-A160\x00\x00', - b'39990-TVA-A340\x00\x00', - b'39990-TWB-H120\x00\x00', - ], }, CAR.CIVIC: { (Ecu.programmedFuelInjection, 0x18da10f1, None): [ diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 153fa1e635..041ab67a97 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -59,7 +59,7 @@ class CarInterface(CarInterfaceBase): if any(0x33DA in f for f in fingerprint.values()): ret.flags |= HondaFlags.BOSCH_EXT_HUD.value - # Accord 1.5T CVT has different gearbox message + # Accord ICE 1.5T CVT has different gearbox message if candidate == CAR.ACCORD and 0x191 in fingerprint[1]: ret.transmissionType = TransmissionType.cvt @@ -115,7 +115,7 @@ class CarInterface(CarInterfaceBase): ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] - elif candidate in (CAR.ACCORD, CAR.ACCORDH): + elif candidate == CAR.ACCORD: ret.mass = 3279. * CV.LB_TO_KG ret.wheelbase = 2.83 ret.centerToFront = ret.wheelbase * 0.39 diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index f573296609..434316943b 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -74,7 +74,6 @@ VISUAL_HUD = { class CAR(StrEnum): ACCORD = "HONDA ACCORD 2018" - ACCORDH = "HONDA ACCORD HYBRID 2018" CIVIC = "HONDA CIVIC 2016" CIVIC_BOSCH = "HONDA CIVIC (BOSCH) 2019" CIVIC_BOSCH_DIESEL = "HONDA CIVIC SEDAN 1.6 DIESEL 2019" @@ -119,8 +118,8 @@ CAR_INFO: dict[str, HondaCarInfo | list[HondaCarInfo] | None] = { CAR.ACCORD: [ HondaCarInfo("Honda Accord 2018-22", "All", video_link="https://www.youtube.com/watch?v=mrUwlj3Mi58", min_steer_speed=3. * CV.MPH_TO_MS), HondaCarInfo("Honda Inspire 2018", "All", min_steer_speed=3. * CV.MPH_TO_MS), + HondaCarInfo("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS), ], - CAR.ACCORDH: HondaCarInfo("Honda Accord Hybrid 2018-22", "All", min_steer_speed=3. * CV.MPH_TO_MS), CAR.CIVIC: HondaCarInfo("Honda Civic 2016-18", min_steer_speed=12. * CV.MPH_TO_MS, video_link="https://youtu.be/-IkImTe1NYE"), CAR.CIVIC_BOSCH: [ HondaCarInfo("Honda Civic 2019-21", "All", video_link="https://www.youtube.com/watch?v=4Iz1Mz5LGF8", @@ -201,14 +200,16 @@ FW_QUERY_CONFIG = FwQueryConfig( # We lose these ECUs without the comma power on these cars. # Note that we still attempt to match with them when they are present non_essential_ecus={ - Ecu.programmedFuelInjection: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.transmission: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.vsa: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.combinationMeter: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.gateway: [CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.electricBrakeBooster: [CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.transmission: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.srs: [CAR.ACCORD], + Ecu.eps: [CAR.ACCORD], + Ecu.vsa: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.gateway: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.electricBrakeBooster: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE - Ecu.hud: [CAR.ACCORD, CAR.ACCORDH], # existence correlates with trim level + Ecu.hud: [CAR.ACCORD], # existence correlates with trim level }, extra_ecus=[ # The only other ECU on PT bus accessible by camera on radarless Civic @@ -219,7 +220,6 @@ FW_QUERY_CONFIG = FwQueryConfig( DBC = { CAR.ACCORD: dbc_dict('honda_accord_2018_can_generated', None), - CAR.ACCORDH: dbc_dict('honda_accord_2018_can_generated', None), CAR.ACURA_ILX: dbc_dict('acura_ilx_2016_can_generated', 'acura_ilx_2016_nidec'), CAR.ACURA_RDX: dbc_dict('acura_rdx_2018_can_generated', 'acura_ilx_2016_nidec'), CAR.ACURA_RDX_3G: dbc_dict('acura_rdx_2020_can_generated', None), @@ -252,6 +252,6 @@ STEER_THRESHOLD = { HONDA_NIDEC_ALT_PCM_ACCEL = {CAR.ODYSSEY} HONDA_NIDEC_ALT_SCM_MESSAGES = {CAR.ACURA_ILX, CAR.ACURA_RDX, CAR.CRV, CAR.CRV_EU, CAR.FIT, CAR.FREED, CAR.HRV, CAR.ODYSSEY_CHN, CAR.PILOT, CAR.RIDGELINE} -HONDA_BOSCH = {CAR.ACCORD, CAR.ACCORDH, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, +HONDA_BOSCH = {CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CIVIC_BOSCH_DIESEL, CAR.CRV_5G, CAR.CRV_HYBRID, CAR.INSIGHT, CAR.ACURA_RDX_3G, CAR.HONDA_E, CAR.CIVIC_2022, CAR.HRV_3G} HONDA_BOSCH_RADARLESS = {CAR.CIVIC_2022, CAR.HRV_3G} diff --git a/selfdrive/car/tests/routes.py b/selfdrive/car/tests/routes.py index 9c14c0d252..811416ccef 100755 --- a/selfdrive/car/tests/routes.py +++ b/selfdrive/car/tests/routes.py @@ -82,8 +82,8 @@ routes = [ CarTestRoute("08a3deb07573f157|2020-03-06--16-11-19", HONDA.ACCORD), # 1.5T CarTestRoute("1da5847ac2488106|2021-05-24--19-31-50", HONDA.ACCORD), # 2.0T CarTestRoute("085ac1d942c35910|2021-03-25--20-11-15", HONDA.ACCORD), # 2021 with new style HUD msgs - CarTestRoute("07585b0da3c88459|2021-05-26--18-52-04", HONDA.ACCORDH), - CarTestRoute("f29e2b57a55e7ad5|2021-03-24--20-52-38", HONDA.ACCORDH), # 2021 with new style HUD msgs + CarTestRoute("07585b0da3c88459|2021-05-26--18-52-04", HONDA.ACCORD), # hybrid + CarTestRoute("f29e2b57a55e7ad5|2021-03-24--20-52-38", HONDA.ACCORD), # hybrid, 2021 with new style HUD msgs CarTestRoute("1ad763dd22ef1a0e|2020-02-29--18-37-03", HONDA.CRV_5G), CarTestRoute("0a96f86fcfe35964|2020-02-05--07-25-51", HONDA.ODYSSEY), CarTestRoute("d83f36766f8012a5|2020-02-05--18-42-21", HONDA.CIVIC_BOSCH_DIESEL), diff --git a/selfdrive/car/tests/test_models_segs.txt b/selfdrive/car/tests/test_models_segs.txt index ca089bbdde..c983fb08e7 100644 --- a/selfdrive/car/tests/test_models_segs.txt +++ b/selfdrive/car/tests/test_models_segs.txt @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:cadad21e1230729c70cffb4c46dd0a5dda4eec1a262b1bcd9f1b6b98265c20b5 -size 125104 +oid sha256:0810a361ec5b5f5f9a2ee73b89ffb2df62ef40e8feff7e97ecb62f80fa53f6f5 +size 124950 diff --git a/selfdrive/car/torque_data/params.toml b/selfdrive/car/torque_data/params.toml index 568646c84c..142332b220 100644 --- a/selfdrive/car/torque_data/params.toml +++ b/selfdrive/car/torque_data/params.toml @@ -11,8 +11,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "CHRYSLER PACIFICA HYBRID 2018" = [2.08887, 1.2943025830995154, 0.114818] "CHRYSLER PACIFICA HYBRID 2019" = [1.90120, 1.1958788168371808, 0.131520] "GENESIS G70 2018" = [3.8520195946707947, 2.354697063349854, 0.06830285485626221] -"HONDA ACCORD 2018" = [1.7135052593468778, 0.3461280068322071, 0.21579936052863807] -"HONDA ACCORD HYBRID 2018" = [1.6651615004829625, 0.30322180951193245, 0.2083000440586149] +"HONDA ACCORD 2018" = [1.6893333799149202, 0.3246749081720698, 0.2120497022936265] "HONDA CIVIC (BOSCH) 2019" = [1.691708637466905, 0.40132900729454185, 0.25460295304024094] "HONDA CIVIC 2016" = [1.6528895627785531, 0.4018518740819229, 0.25458812851328544] "HONDA CR-V 2016" = [0.7667141440182675, 0.5927571534745969, 0.40909087636157127] diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 9c627fb7c9..0fa4652e4c 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -47609e372bf616932c4dca74d2616c3d97fa2443 +dab93e072903e80f91029a03600430c43c722cb7 From a5fa419fbd32afe176dc4380e84c785bf84ba8aa Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 27 Feb 2024 21:48:40 -0800 Subject: [PATCH 16/35] Volkswagen: log camera ECU FW --- selfdrive/car/volkswagen/values.py | 1 + 1 file changed, 1 insertion(+) diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 4dff9205d6..3344d58ea9 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -393,6 +393,7 @@ FW_QUERY_CONFIG = FwQueryConfig( obd_multiplexing=obd_multiplexing, ), ]], + extra_ecus=[(Ecu.fwdCamera, 0x74f, None)], ) CAR_INFO = CAR.create_carinfo_map() From 2c247ea2c6f6c22aa6ce55a6220e75ab17b58e06 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 28 Feb 2024 00:12:00 -0600 Subject: [PATCH 17/35] Honda Civic (Nidec): allow fingerprinting without comma power (#31501) * civic: FP with no OBD port * non essential ecus --- selfdrive/car/honda/values.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/selfdrive/car/honda/values.py b/selfdrive/car/honda/values.py index 434316943b..ce4a531d01 100644 --- a/selfdrive/car/honda/values.py +++ b/selfdrive/car/honda/values.py @@ -187,7 +187,6 @@ FW_QUERY_CONFIG = FwQueryConfig( [StdQueries.UDS_VERSION_REQUEST], [StdQueries.UDS_VERSION_RESPONSE], bus=0, - logging=True, ), # Bosch PT bus Request( @@ -200,13 +199,13 @@ FW_QUERY_CONFIG = FwQueryConfig( # We lose these ECUs without the comma power on these cars. # Note that we still attempt to match with them when they are present non_essential_ecus={ - Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.transmission: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.programmedFuelInjection: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.transmission: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.srs: [CAR.ACCORD], Ecu.eps: [CAR.ACCORD], - Ecu.vsa: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], - Ecu.gateway: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.vsa: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.combinationMeter: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], + Ecu.gateway: [CAR.ACCORD, CAR.CIVIC, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.electricBrakeBooster: [CAR.ACCORD, CAR.CIVIC_BOSCH, CAR.CRV_5G], Ecu.shiftByWire: [CAR.ACCORD], # existence correlates with transmission type for ICE Ecu.hud: [CAR.ACCORD], # existence correlates with trim level From 7cf2b28b7883fdc3e68ad9e0974879103fa3a6ba Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 14:41:42 -0500 Subject: [PATCH 18/35] scons: fix race condition with opendbc (#31621) * fix race condition * add to release * fix for now * bump --- SConstruct | 8 +------- opendbc | 2 +- release/files_common | 2 ++ selfdrive/SConscript | 7 +++++++ selfdrive/controls/lib/lateral_mpc_lib/SConscript | 3 ++- selfdrive/controls/lib/longitudinal_mpc_lib/SConscript | 4 ++-- 6 files changed, 15 insertions(+), 11 deletions(-) create mode 100644 selfdrive/SConscript diff --git a/SConstruct b/SConstruct index 4d4f9ad4fe..dac3529892 100644 --- a/SConstruct +++ b/SConstruct @@ -384,13 +384,7 @@ if arch != "Darwin": # Build openpilot SConscript(['third_party/SConscript']) -SConscript(['selfdrive/boardd/SConscript']) -SConscript(['selfdrive/controls/lib/lateral_mpc_lib/SConscript']) -SConscript(['selfdrive/controls/lib/longitudinal_mpc_lib/SConscript']) -SConscript(['selfdrive/locationd/SConscript']) -SConscript(['selfdrive/navd/SConscript']) -SConscript(['selfdrive/modeld/SConscript']) -SConscript(['selfdrive/ui/SConscript']) +SConscript(['selfdrive/SConscript']) if arch in ['x86_64', 'aarch64', 'Darwin'] and Dir('#tools/cabana/').exists() and GetOption('extras'): SConscript(['tools/replay/SConscript']) diff --git a/opendbc b/opendbc index 0ac21652f2..5f096db742 160000 --- a/opendbc +++ b/opendbc @@ -1 +1 @@ -Subproject commit 0ac21652f2e643e29aa471ad6b238bf74b22e356 +Subproject commit 5f096db742b0c5dcd19976afdb07d5dd098f4b07 diff --git a/release/files_common b/release/files_common index d62ef8d1bb..1fb05b43a7 100644 --- a/release/files_common +++ b/release/files_common @@ -60,6 +60,8 @@ system/logmessaged.py system/micd.py system/version.py +selfdrive/SConscript + selfdrive/athena/__init__.py selfdrive/athena/athenad.py selfdrive/athena/manage_athenad.py diff --git a/selfdrive/SConscript b/selfdrive/SConscript new file mode 100644 index 0000000000..6b72177d8e --- /dev/null +++ b/selfdrive/SConscript @@ -0,0 +1,7 @@ +SConscript(['boardd/SConscript']) +SConscript(['controls/lib/lateral_mpc_lib/SConscript']) +SConscript(['controls/lib/longitudinal_mpc_lib/SConscript']) +SConscript(['locationd/SConscript']) +SConscript(['navd/SConscript']) +SConscript(['modeld/SConscript']) +SConscript(['ui/SConscript']) \ No newline at end of file diff --git a/selfdrive/controls/lib/lateral_mpc_lib/SConscript b/selfdrive/controls/lib/lateral_mpc_lib/SConscript index 49666abe69..b6603e69fc 100644 --- a/selfdrive/controls/lib/lateral_mpc_lib/SConscript +++ b/selfdrive/controls/lib/lateral_mpc_lib/SConscript @@ -1,4 +1,4 @@ -Import('env', 'envCython', 'arch') +Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python') gen = "c_generated_code" @@ -60,6 +60,7 @@ lenv.Clean(generated_files, Dir(gen)) generated_lat = lenv.Command(generated_files, source_list, f"cd {Dir('.').abspath} && python3 lat_mpc.py") +lenv.Depends(generated_lat, [messaging_python, common_python, opendbc_python]) lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") diff --git a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript index 79afa1d918..c00d5cb5a7 100644 --- a/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript +++ b/selfdrive/controls/lib/longitudinal_mpc_lib/SConscript @@ -1,4 +1,4 @@ -Import('env', 'envCython', 'arch', 'messaging_python', 'common_python') +Import('env', 'envCython', 'arch', 'messaging_python', 'common_python', 'opendbc_python') gen = "c_generated_code" @@ -66,7 +66,7 @@ lenv.Clean(generated_files, Dir(gen)) generated_long = lenv.Command(generated_files, source_list, f"cd {Dir('.').abspath} && python3 long_mpc.py") -lenv.Depends(generated_long, [messaging_python, common_python]) +lenv.Depends(generated_long, [messaging_python, common_python, opendbc_python]) lenv["CFLAGS"].append("-DACADOS_WITH_QPOASES") lenv["CXXFLAGS"].append("-DACADOS_WITH_QPOASES") From e9a10ca712c79c51037f5c96b8f8e749c98ce060 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 15:05:43 -0500 Subject: [PATCH 19/35] auto pr review (#31626) * auto PR comments * little more * test * update action * cleanup * ensure it only runs once * comment that part out --------- Co-authored-by: Adeeb Shihadeh --- .github/workflows/auto_pr_review.yaml | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index abb6c38d6b..0720c1e676 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -34,6 +34,25 @@ jobs: already-exists-action: close_this already-exists-comment: "Your PR should be made against the `master` branch" + comment: + runs-on: ubuntu-latest + steps: + - name: comment + uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + with: + message: | + + Thanks for contributing to openpilot! In order for us to review your PR as quickly as possible, check the following: + * Convert your PR to a draft unless it's ready to review + * Read the [contributing docs](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md) + * Before marking as "ready for review", ensure: + * the goal is clearly stated in the description + * all the tests are passing + * the change is [something we merge](https://github.com/commaai/openpilot/blob/master/docs/CONTRIBUTING.md#what-gets-merged) + * include a route or your device' dongle ID if relevant + comment_tag: run_id + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + check-pr-template: runs-on: ubuntu-latest permissions: @@ -41,7 +60,7 @@ jobs: issues: write pull-requests: write actions: read - if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' + if: false && github.event.pull_request.head.repo.full_name != 'commaai/openpilot' steps: - uses: actions/github-script@v7 with: @@ -91,7 +110,7 @@ jobs: // Utility function to check if a list of checkboxes is a subset of another list of checkboxes isCheckboxSubset = (templateCheckBoxTexts, prTextCheckBoxTexts) => { - // Check if each template checkbox text is a substring of at least one PR checkbox text + // Check if each template checkbox text is a substring of at least one PR checkbox text // (user should be allowed to add additional text) return templateCheckBoxTexts.every((item) => prTextCheckBoxTexts.some((element) => element.includes(item))) } From 6cf7599bcd1a0218bb359f72c3d17e15c53bae93 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 28 Feb 2024 15:54:21 -0800 Subject: [PATCH 20/35] setup: add openpilot button (#31628) * setup: add openpilot button * rename --- selfdrive/ui/qt/setup/setup.cc | 122 +++++++++++++++++++---- selfdrive/ui/qt/setup/setup.h | 1 + selfdrive/ui/translations/main_ar.ts | 12 +++ selfdrive/ui/translations/main_de.ts | 12 +++ selfdrive/ui/translations/main_fr.ts | 12 +++ selfdrive/ui/translations/main_ja.ts | 12 +++ selfdrive/ui/translations/main_ko.ts | 12 +++ selfdrive/ui/translations/main_pt-BR.ts | 12 +++ selfdrive/ui/translations/main_th.ts | 12 +++ selfdrive/ui/translations/main_tr.ts | 12 +++ selfdrive/ui/translations/main_zh-CHS.ts | 12 +++ selfdrive/ui/translations/main_zh-CHT.ts | 12 +++ 12 files changed, 226 insertions(+), 17 deletions(-) diff --git a/selfdrive/ui/qt/setup/setup.cc b/selfdrive/ui/qt/setup/setup.cc index 4f2e4f48cb..08f4a0f9c0 100644 --- a/selfdrive/ui/qt/setup/setup.cc +++ b/selfdrive/ui/qt/setup/setup.cc @@ -20,7 +20,7 @@ #include "selfdrive/ui/qt/widgets/input.h" const std::string USER_AGENT = "AGNOSSetup-"; -const QString TEST_URL = "https://openpilot.comma.ai"; +const QString OPENPILOT_URL = "https://openpilot.comma.ai"; bool is_elf(char *fname) { FILE *fp = fopen(fname, "rb"); @@ -201,20 +201,7 @@ QWidget * Setup::network_setup() { QPushButton *cont = new QPushButton(); cont->setObjectName("navBtn"); cont->setProperty("primary", true); - QObject::connect(cont, &QPushButton::clicked, [=]() { - auto w = currentWidget(); - QTimer::singleShot(0, [=]() { - setCurrentWidget(downloading_widget); - }); - QString url = InputDialog::getText(tr("Enter URL"), this, tr("for Custom Software")); - if (!url.isEmpty()) { - QTimer::singleShot(1000, this, [=]() { - download(url); - }); - } else { - setCurrentWidget(w); - } - }); + QObject::connect(cont, &QPushButton::clicked, this, &Setup::nextPage); blayout->addWidget(cont); // setup timer for testing internet connection @@ -229,11 +216,11 @@ QWidget * Setup::network_setup() { } repaint(); }); - request->sendRequest(TEST_URL); + request->sendRequest(OPENPILOT_URL); QTimer *timer = new QTimer(this); QObject::connect(timer, &QTimer::timeout, [=]() { if (!request->active() && cont->isVisible()) { - request->sendRequest(TEST_URL); + request->sendRequest(OPENPILOT_URL); } }); timer->start(1000); @@ -241,6 +228,106 @@ QWidget * Setup::network_setup() { return widget; } +QWidget * radio_button(QString title, QButtonGroup *group) { + QPushButton *btn = new QPushButton(title); + btn->setCheckable(true); + group->addButton(btn); + btn->setStyleSheet(R"( + QPushButton { + height: 230; + padding-left: 100px; + padding-right: 100px; + text-align: left; + font-size: 80px; + font-weight: 400; + border-radius: 10px; + background-color: #4F4F4F; + } + QPushButton:checked { + background-color: #465BEA; + } + )"); + + // checkmark icon + QPixmap pix(":/img_circled_check.svg"); + btn->setIcon(pix); + btn->setIconSize(QSize(0, 0)); + btn->setLayoutDirection(Qt::RightToLeft); + QObject::connect(btn, &QPushButton::toggled, [=](bool checked) { + btn->setIconSize(checked ? QSize(104, 104) : QSize(0, 0)); + }); + return btn; +} + +QWidget * Setup::software_selection() { + QWidget *widget = new QWidget(); + QVBoxLayout *main_layout = new QVBoxLayout(widget); + main_layout->setContentsMargins(55, 50, 55, 50); + main_layout->setSpacing(0); + + // title + QLabel *title = new QLabel(tr("Choose Software to Install")); + title->setStyleSheet("font-size: 90px; font-weight: 500;"); + main_layout->addWidget(title, 0, Qt::AlignLeft | Qt::AlignTop); + + main_layout->addSpacing(50); + + // openpilot + custom radio buttons + QButtonGroup *group = new QButtonGroup(widget); + group->setExclusive(true); + + QWidget *openpilot = radio_button(tr("openpilot"), group); + main_layout->addWidget(openpilot); + + main_layout->addSpacing(30); + + QWidget *custom = radio_button(tr("Custom Software"), group); + main_layout->addWidget(custom); + + main_layout->addStretch(); + + // back + continue buttons + QHBoxLayout *blayout = new QHBoxLayout; + main_layout->addLayout(blayout); + blayout->setSpacing(50); + + QPushButton *back = new QPushButton(tr("Back")); + back->setObjectName("navBtn"); + QObject::connect(back, &QPushButton::clicked, this, &Setup::prevPage); + blayout->addWidget(back); + + QPushButton *cont = new QPushButton(tr("Continue")); + cont->setObjectName("navBtn"); + cont->setEnabled(false); + cont->setProperty("primary", true); + blayout->addWidget(cont); + + QObject::connect(cont, &QPushButton::clicked, [=]() { + auto w = currentWidget(); + QTimer::singleShot(0, [=]() { + setCurrentWidget(downloading_widget); + }); + QString url = OPENPILOT_URL; + if (group->checkedButton() != openpilot) { + url = InputDialog::getText(tr("Enter URL"), this, tr("for Custom Software")); + } + if (!url.isEmpty()) { + QTimer::singleShot(1000, this, [=]() { + download(url); + }); + } else { + setCurrentWidget(w); + } + }); + + connect(group, QOverload::of(&QButtonGroup::buttonClicked), [=](QAbstractButton *btn) { + btn->setChecked(true); + cont->setEnabled(true); + }); + + return widget; +} + QWidget * Setup::downloading() { QWidget *widget = new QWidget(); QVBoxLayout *main_layout = new QVBoxLayout(widget); @@ -326,6 +413,7 @@ Setup::Setup(QWidget *parent) : QStackedWidget(parent) { addWidget(getting_started()); addWidget(network_setup()); + addWidget(software_selection()); downloading_widget = downloading(); addWidget(downloading_widget); diff --git a/selfdrive/ui/qt/setup/setup.h b/selfdrive/ui/qt/setup/setup.h index 8c33acc380..ee5cc85483 100644 --- a/selfdrive/ui/qt/setup/setup.h +++ b/selfdrive/ui/qt/setup/setup.h @@ -17,6 +17,7 @@ private: QWidget *low_voltage(); QWidget *getting_started(); QWidget *network_setup(); + QWidget *software_selection(); QWidget *downloading(); QWidget *download_failed(QLabel *url, QLabel *body); diff --git a/selfdrive/ui/translations/main_ar.ts b/selfdrive/ui/translations/main_ar.ts index eb6a580c01..7a431b8bf8 100644 --- a/selfdrive/ui/translations/main_ar.ts +++ b/selfdrive/ui/translations/main_ar.ts @@ -762,6 +762,18 @@ This may take up to a minute. Select a language اختر لغة + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_de.ts b/selfdrive/ui/translations/main_de.ts index 6d814b9625..ae2bdf33cb 100644 --- a/selfdrive/ui/translations/main_de.ts +++ b/selfdrive/ui/translations/main_de.ts @@ -744,6 +744,18 @@ This may take up to a minute. Select a language Sprache wählen + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_fr.ts b/selfdrive/ui/translations/main_fr.ts index cd96c466e9..ba496c1b89 100644 --- a/selfdrive/ui/translations/main_fr.ts +++ b/selfdrive/ui/translations/main_fr.ts @@ -746,6 +746,18 @@ Cela peut prendre jusqu'à une minute. Select a language Choisir une langue + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_ja.ts b/selfdrive/ui/translations/main_ja.ts index d07c7d525a..54ff0fa4ae 100644 --- a/selfdrive/ui/translations/main_ja.ts +++ b/selfdrive/ui/translations/main_ja.ts @@ -740,6 +740,18 @@ This may take up to a minute. Select a language 言語を選択 + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_ko.ts b/selfdrive/ui/translations/main_ko.ts index a903978329..3f98db2f9c 100644 --- a/selfdrive/ui/translations/main_ko.ts +++ b/selfdrive/ui/translations/main_ko.ts @@ -742,6 +742,18 @@ This may take up to a minute. Select a language 언어를 선택하세요 + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index fce5a8a8ff..e31001a1e0 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -746,6 +746,18 @@ Isso pode levar até um minuto. Select a language Selecione o Idioma + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_th.ts b/selfdrive/ui/translations/main_th.ts index f4d097b2a2..c1f0039a3c 100644 --- a/selfdrive/ui/translations/main_th.ts +++ b/selfdrive/ui/translations/main_th.ts @@ -742,6 +742,18 @@ This may take up to a minute. Select a language เลือกภาษา + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_tr.ts b/selfdrive/ui/translations/main_tr.ts index ec6f71f5b0..d19c9ff036 100644 --- a/selfdrive/ui/translations/main_tr.ts +++ b/selfdrive/ui/translations/main_tr.ts @@ -740,6 +740,18 @@ This may take up to a minute. Select a language Dil seçin + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_zh-CHS.ts b/selfdrive/ui/translations/main_zh-CHS.ts index 91f55c6e94..a27dc18bd2 100644 --- a/selfdrive/ui/translations/main_zh-CHS.ts +++ b/selfdrive/ui/translations/main_zh-CHS.ts @@ -742,6 +742,18 @@ This may take up to a minute. Select a language 选择语言 + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget diff --git a/selfdrive/ui/translations/main_zh-CHT.ts b/selfdrive/ui/translations/main_zh-CHT.ts index e8c8854d0e..1e7f1a614b 100644 --- a/selfdrive/ui/translations/main_zh-CHT.ts +++ b/selfdrive/ui/translations/main_zh-CHT.ts @@ -742,6 +742,18 @@ This may take up to a minute. Select a language 選擇語言 + + Choose Software to Install + + + + openpilot + openpilot + + + Custom Software + + SetupWidget From 7208e37f8c02c2d5260ed06faf4c531f753811a3 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 19:44:10 -0500 Subject: [PATCH 21/35] disable notebooks (#31631) --- .github/workflows/tools_tests.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/tools_tests.yaml b/.github/workflows/tools_tests.yaml index d15ab8cd60..a051cb1241 100644 --- a/.github/workflows/tools_tests.yaml +++ b/.github/workflows/tools_tests.yaml @@ -86,7 +86,7 @@ jobs: notebooks: name: notebooks runs-on: ubuntu-20.04 - if: github.repository == 'commaai/openpilot' + if: false && github.repository == 'commaai/openpilot' timeout-minutes: 45 steps: - uses: actions/checkout@v4 From f4a7e8eae6e4102a35c0ba787d61861bd40ed8f4 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 19:47:08 -0500 Subject: [PATCH 22/35] disable commaCarSegments tests (#31632) disable this test too --- tools/lib/tests/test_comma_car_segments.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/lib/tests/test_comma_car_segments.py b/tools/lib/tests/test_comma_car_segments.py index 50d4200b4f..b293251583 100644 --- a/tools/lib/tests/test_comma_car_segments.py +++ b/tools/lib/tests/test_comma_car_segments.py @@ -1,3 +1,4 @@ +import pytest import unittest import requests @@ -6,6 +7,7 @@ from openpilot.tools.lib.logreader import LogReader from openpilot.tools.lib.route import SegmentRange +@pytest.mark.skip(reason="huggingface is flaky, run this test manually to check for issues") class TestCommaCarSegments(unittest.TestCase): def test_database(self): database = get_comma_car_segments_database() From 4cec88c02902ff15eafbb497e779c5ca2dc13d8b Mon Sep 17 00:00:00 2001 From: Shea_D Date: Wed, 28 Feb 2024 19:07:06 -0600 Subject: [PATCH 23/35] Ford - Add OBDC Cable Length to CarPartList (#31608) * Update comma cable requirement for Ford CANFD * Adding Long_Cable to part list * Moving cable info into doc_definitions under CarHarness * Updating parts for ford_q4 * Updating Q3 info * Updated MachE with USBC coupler * fix typo * updating docs/cars.md * Add 3X angled no cable * Adding in nocable device package * Add missing ) Co-authored-by: Cameron Clough * Generating new Docs.MD * Added threex_nocable for MachE * Swap MachE to regular mount no cable * confirmed with Comma Operations all boxes include 1.5ft cable regardless of 9.5ft selection * Updating CarInfo * Update USB_Coupler for Q4 Harness * Remove cable from import * removed ] * Disagree with the inconsistency but OK Co-authored-by: Shane Smiskol * Update selfdrive/car/ford/values.py --------- Co-authored-by: sheaduncan Co-authored-by: Cameron Clough Co-authored-by: Shane Smiskol --- selfdrive/car/docs_definitions.py | 3 ++- selfdrive/car/ford/values.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/docs_definitions.py b/selfdrive/car/docs_definitions.py index 841cc3af2f..1adf78b1c8 100644 --- a/selfdrive/car/docs_definitions.py +++ b/selfdrive/car/docs_definitions.py @@ -118,7 +118,8 @@ class CarHarness(EnumBase): nissan_b = BaseCarHarness("Nissan B connector", parts=[Accessory.harness_box, Cable.rj45_cable_7ft, Cable.long_obdc_cable, Cable.usbc_coupler]) mazda = BaseCarHarness("Mazda connector") ford_q3 = BaseCarHarness("Ford Q3 connector") - ford_q4 = BaseCarHarness("Ford Q4 connector") + ford_q4 = BaseCarHarness("Ford Q4 connector", parts=[Accessory.harness_box, Accessory.comma_power_v2, Cable.rj45_cable_7ft, Cable.long_obdc_cable, + Cable.usbc_coupler]) class Device(EnumBase): diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index 1008d68b98..f969d395d2 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -58,7 +58,7 @@ class FordCarInfo(CarInfo): def init_make(self, CP: car.CarParams): harness = CarHarness.ford_q4 if CP.carFingerprint in CANFD_CAR else CarHarness.ford_q3 - if CP.carFingerprint in (CAR.BRONCO_SPORT_MK1, CAR.MAVERICK_MK1, CAR.F_150_MK14): + if CP.carFingerprint in (CAR.BRONCO_SPORT_MK1, CAR.MAVERICK_MK1, CAR.F_150_MK14, CAR.F_150_LIGHTNING_MK1): self.car_parts = CarParts([Device.threex_angled_mount, harness]) else: self.car_parts = CarParts([Device.threex, harness]) From d4c497d82674126103118a4d5bb7a39db2823609 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 20:13:44 -0500 Subject: [PATCH 24/35] add CarControllerBase base class to all CarControllers (#31630) just base class for now --- selfdrive/car/body/carcontroller.py | 3 ++- selfdrive/car/chrysler/carcontroller.py | 3 ++- selfdrive/car/ford/carcontroller.py | 3 ++- selfdrive/car/gm/carcontroller.py | 3 ++- selfdrive/car/honda/carcontroller.py | 3 ++- selfdrive/car/hyundai/carcontroller.py | 3 ++- selfdrive/car/interfaces.py | 9 +++++++++ selfdrive/car/mazda/carcontroller.py | 3 ++- selfdrive/car/nissan/carcontroller.py | 3 ++- selfdrive/car/subaru/carcontroller.py | 3 ++- selfdrive/car/tesla/carcontroller.py | 3 ++- selfdrive/car/toyota/carcontroller.py | 3 ++- selfdrive/car/volkswagen/carcontroller.py | 3 ++- 13 files changed, 33 insertions(+), 12 deletions(-) diff --git a/selfdrive/car/body/carcontroller.py b/selfdrive/car/body/carcontroller.py index d15f11d3a4..db34320caa 100644 --- a/selfdrive/car/body/carcontroller.py +++ b/selfdrive/car/body/carcontroller.py @@ -4,6 +4,7 @@ from openpilot.common.realtime import DT_CTRL from opendbc.can.packer import CANPacker from openpilot.selfdrive.car.body import bodycan from openpilot.selfdrive.car.body.values import SPEED_FROM_RPM +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.controls.lib.pid import PIDController @@ -14,7 +15,7 @@ MAX_POS_INTEGRATOR = 0.2 # meters MAX_TURN_INTEGRATOR = 0.1 # meters -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.frame = 0 self.packer = CANPacker(dbc_name) diff --git a/selfdrive/car/chrysler/carcontroller.py b/selfdrive/car/chrysler/carcontroller.py index 050eb41b1a..39248f3f75 100644 --- a/selfdrive/car/chrysler/carcontroller.py +++ b/selfdrive/car/chrysler/carcontroller.py @@ -3,9 +3,10 @@ from openpilot.common.realtime import DT_CTRL from openpilot.selfdrive.car import apply_meas_steer_torque_limits from openpilot.selfdrive.car.chrysler import chryslercan from openpilot.selfdrive.car.chrysler.values import RAM_CARS, CarControllerParams, ChryslerFlags +from openpilot.selfdrive.car.interfaces import CarControllerBase -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.apply_steer_last = 0 diff --git a/selfdrive/car/ford/carcontroller.py b/selfdrive/car/ford/carcontroller.py index 45516d6035..61c46674db 100644 --- a/selfdrive/car/ford/carcontroller.py +++ b/selfdrive/car/ford/carcontroller.py @@ -4,6 +4,7 @@ from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_std_steer_angle_limits from openpilot.selfdrive.car.ford import fordcan from openpilot.selfdrive.car.ford.values import CANFD_CAR, CarControllerParams +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX LongCtrlState = car.CarControl.Actuators.LongControlState @@ -22,7 +23,7 @@ def apply_ford_curvature_limits(apply_curvature, apply_curvature_last, current_c return clip(apply_curvature, -CarControllerParams.CURVATURE_MAX, CarControllerParams.CURVATURE_MAX) -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.VM = VM diff --git a/selfdrive/car/gm/carcontroller.py b/selfdrive/car/gm/carcontroller.py index 6c7e8007f2..e010c56536 100644 --- a/selfdrive/car/gm/carcontroller.py +++ b/selfdrive/car/gm/carcontroller.py @@ -6,6 +6,7 @@ from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_driver_steer_torque_limits from openpilot.selfdrive.car.gm import gmcan from openpilot.selfdrive.car.gm.values import DBC, CanBus, CarControllerParams, CruiseButtons +from openpilot.selfdrive.car.interfaces import CarControllerBase VisualAlert = car.CarControl.HUDControl.VisualAlert NetworkLocation = car.CarParams.NetworkLocation @@ -17,7 +18,7 @@ CAMERA_CANCEL_DELAY_FRAMES = 10 MIN_STEER_MSG_INTERVAL_MS = 15 -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.start_time = 0. diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 056b47c4b3..8170e1e9ef 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -7,6 +7,7 @@ from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import create_gas_interceptor_command from openpilot.selfdrive.car.honda import hondacan from openpilot.selfdrive.car.honda.values import CruiseButtons, VISUAL_HUD, HONDA_BOSCH, HONDA_BOSCH_RADARLESS, HONDA_NIDEC_ALT_PCM_ACCEL, CarControllerParams +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.controls.lib.drive_helpers import rate_limit VisualAlert = car.CarControl.HUDControl.VisualAlert @@ -104,7 +105,7 @@ def rate_limit_steer(new_steer, last_steer): return clip(new_steer, last_steer - MAX_DELTA, last_steer + MAX_DELTA) -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.packer = CANPacker(dbc_name) diff --git a/selfdrive/car/hyundai/carcontroller.py b/selfdrive/car/hyundai/carcontroller.py index 0b5f724ab9..b0851abf55 100644 --- a/selfdrive/car/hyundai/carcontroller.py +++ b/selfdrive/car/hyundai/carcontroller.py @@ -7,6 +7,7 @@ from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fau from openpilot.selfdrive.car.hyundai import hyundaicanfd, hyundaican from openpilot.selfdrive.car.hyundai.hyundaicanfd import CanBus from openpilot.selfdrive.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CANFD_CAR, CAR +from openpilot.selfdrive.car.interfaces import CarControllerBase VisualAlert = car.CarControl.HUDControl.VisualAlert LongCtrlState = car.CarControl.Actuators.LongControlState @@ -42,7 +43,7 @@ def process_hud_alert(enabled, fingerprint, hud_control): return sys_warning, sys_state, left_lane_warning, right_lane_warning -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.CAN = CanBus(CP) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 0a5ec94aa0..63005e6351 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -518,3 +518,12 @@ class NanoFFModel: pred = x[0] pred = pred * (self.weights['output_norm_mat'][1] - self.weights['output_norm_mat'][0]) + self.weights['output_norm_mat'][0] return pred + + +SendCan = tuple[int, int, bytes, int] + + +class CarControllerBase(ABC): + @abstractmethod + def update(self, CC, CS, now_nanos) -> tuple[car.CarControl.Actuators, list[SendCan]]: + pass diff --git a/selfdrive/car/mazda/carcontroller.py b/selfdrive/car/mazda/carcontroller.py index 320ad19bb4..3f3b7a9494 100644 --- a/selfdrive/car/mazda/carcontroller.py +++ b/selfdrive/car/mazda/carcontroller.py @@ -1,13 +1,14 @@ from cereal import car from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_driver_steer_torque_limits +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.mazda import mazdacan from openpilot.selfdrive.car.mazda.values import CarControllerParams, Buttons VisualAlert = car.CarControl.HUDControl.VisualAlert -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.apply_steer_last = 0 diff --git a/selfdrive/car/nissan/carcontroller.py b/selfdrive/car/nissan/carcontroller.py index 2da518bbf1..6aa4bb9438 100644 --- a/selfdrive/car/nissan/carcontroller.py +++ b/selfdrive/car/nissan/carcontroller.py @@ -1,13 +1,14 @@ from cereal import car from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_std_steer_angle_limits +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.nissan import nissancan from openpilot.selfdrive.car.nissan.values import CAR, CarControllerParams VisualAlert = car.CarControl.HUDControl.VisualAlert -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.car_fingerprint = CP.carFingerprint diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py index cc8ce4f722..4a65c2c02c 100644 --- a/selfdrive/car/subaru/carcontroller.py +++ b/selfdrive/car/subaru/carcontroller.py @@ -1,6 +1,7 @@ from openpilot.common.numpy_fast import clip, interp from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.subaru import subarucan from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, STEER_RATE_LIMITED, \ CanBus, CarControllerParams, SubaruFlags @@ -11,7 +12,7 @@ MAX_STEER_RATE = 25 # deg/s MAX_STEER_RATE_FRAMES = 7 # tx control frames needed before torque can be cut -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.apply_steer_last = 0 diff --git a/selfdrive/car/tesla/carcontroller.py b/selfdrive/car/tesla/carcontroller.py index 95a248a614..f217c4692d 100644 --- a/selfdrive/car/tesla/carcontroller.py +++ b/selfdrive/car/tesla/carcontroller.py @@ -1,11 +1,12 @@ from openpilot.common.numpy_fast import clip from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_std_steer_angle_limits +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.tesla.teslacan import TeslaCAN from openpilot.selfdrive.car.tesla.values import DBC, CANBUS, CarControllerParams -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.frame = 0 diff --git a/selfdrive/car/toyota/carcontroller.py b/selfdrive/car/toyota/carcontroller.py index 343b1d3031..d960114f1b 100644 --- a/selfdrive/car/toyota/carcontroller.py +++ b/selfdrive/car/toyota/carcontroller.py @@ -2,6 +2,7 @@ from cereal import car from openpilot.common.numpy_fast import clip, interp from openpilot.selfdrive.car import apply_meas_steer_torque_limits, apply_std_steer_angle_limits, common_fault_avoidance, \ create_gas_interceptor_command, make_can_msg +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.toyota import toyotacan from openpilot.selfdrive.car.toyota.values import CAR, STATIC_DSU_MSGS, NO_STOP_TIMER_CAR, TSS2_CAR, \ MIN_ACC_SPEED, PEDAL_TRANSITION, CarControllerParams, ToyotaFlags, \ @@ -25,7 +26,7 @@ MAX_LTA_ANGLE = 94.9461 # deg MAX_LTA_DRIVER_TORQUE_ALLOWANCE = 150 # slightly above steering pressed allows some resistance when changing lanes -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.params = CarControllerParams(self.CP) diff --git a/selfdrive/car/volkswagen/carcontroller.py b/selfdrive/car/volkswagen/carcontroller.py index 0cee2c7fce..f99e87d5d3 100644 --- a/selfdrive/car/volkswagen/carcontroller.py +++ b/selfdrive/car/volkswagen/carcontroller.py @@ -4,6 +4,7 @@ from openpilot.common.numpy_fast import clip from openpilot.common.conversions import Conversions as CV from openpilot.common.realtime import DT_CTRL from openpilot.selfdrive.car import apply_driver_steer_torque_limits +from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.volkswagen import mqbcan, pqcan from openpilot.selfdrive.car.volkswagen.values import CANBUS, PQ_CARS, CarControllerParams, VolkswagenFlags @@ -11,7 +12,7 @@ VisualAlert = car.CarControl.HUDControl.VisualAlert LongCtrlState = car.CarControl.Actuators.LongControlState -class CarController: +class CarController(CarControllerBase): def __init__(self, dbc_name, CP, VM): self.CP = CP self.CCP = CarControllerParams(CP) From ec9856b784e6cda8f02e012076666aebe7476650 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 28 Feb 2024 20:01:58 -0600 Subject: [PATCH 25/35] GM: add more FW logging (#31633) * add more DIDs * one more * update refs * rm * btr * Update selfdrive/car/gm/values.py --- selfdrive/car/gm/values.py | 13 +++++++++++++ selfdrive/car/tests/test_fw_fingerprint.py | 4 ++-- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index 35fdf3fb92..ca35b53f72 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -189,22 +189,35 @@ class CanBus: # In a Data Module, an identifier is a string used to recognize an object, # either by itself or together with the identifiers of parent objects. # Each returns a 4 byte hex representation of the decimal part number. `b"\x02\x8c\xf0'"` -> 42790951 +GM_BOOT_SOFTWARE_PART_NUMER_REQUEST = b'\x1a\xc0' # likely does not contain anything useful GM_SOFTWARE_MODULE_1_REQUEST = b'\x1a\xc1' GM_SOFTWARE_MODULE_2_REQUEST = b'\x1a\xc2' GM_SOFTWARE_MODULE_3_REQUEST = b'\x1a\xc3' + +# Part number of XML data file that is used to configure ECU +GM_XML_DATA_FILE_PART_NUMBER = b'\x1a\x9c' +GM_XML_CONFIG_COMPAT_ID = b'\x1a\x9b' # used to know if XML file is compatible with the ECU software/hardware + # This DID is for identifying the part number that reflects the mix of hardware, # software, and calibrations in the ECU when it first arrives at the vehicle assembly plant. # If there's an Alpha Code, it's associated with this part number and stored in the DID $DB. GM_END_MODEL_PART_NUMBER_REQUEST = b'\x1a\xcb' +GM_END_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST = b'\x1a\xdb' GM_BASE_MODEL_PART_NUMBER_REQUEST = b'\x1a\xcc' +GM_BASE_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST = b'\x1a\xdc' GM_FW_RESPONSE = b'\x5a' GM_FW_REQUESTS = [ + GM_BOOT_SOFTWARE_PART_NUMER_REQUEST, GM_SOFTWARE_MODULE_1_REQUEST, GM_SOFTWARE_MODULE_2_REQUEST, GM_SOFTWARE_MODULE_3_REQUEST, + GM_XML_DATA_FILE_PART_NUMBER, + GM_XML_CONFIG_COMPAT_ID, GM_END_MODEL_PART_NUMBER_REQUEST, + GM_END_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST, GM_BASE_MODEL_PART_NUMBER_REQUEST, + GM_BASE_MODEL_PART_NUMBER_ALPHA_CODE_REQUEST, ] GM_RX_OFFSET = 0x400 diff --git a/selfdrive/car/tests/test_fw_fingerprint.py b/selfdrive/car/tests/test_fw_fingerprint.py index 88c7225f22..a8bae29391 100755 --- a/selfdrive/car/tests/test_fw_fingerprint.py +++ b/selfdrive/car/tests/test_fw_fingerprint.py @@ -263,10 +263,10 @@ class TestFwFingerprintTiming(unittest.TestCase): print(f'get_vin {name} case, query time={self.total_time / self.N} seconds') def test_fw_query_timing(self): - total_ref_time = {1: 7.8, 2: 8.7} + total_ref_time = {1: 8.3, 2: 9.2} brand_ref_times = { 1: { - 'gm': 0.5, + 'gm': 1.0, 'body': 0.1, 'chrysler': 0.3, 'ford': 1.5, From 3ae151635d829ce432c13d72b0b075ced892f704 Mon Sep 17 00:00:00 2001 From: Alexandre Nobuharu Sato <66435071+AlexandreSato@users.noreply.github.com> Date: Thu, 29 Feb 2024 00:33:37 -0300 Subject: [PATCH 26/35] Multilang: update pt-BR translations (#31634) update pt-BR translations --- selfdrive/ui/translations/main_pt-BR.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/selfdrive/ui/translations/main_pt-BR.ts b/selfdrive/ui/translations/main_pt-BR.ts index e31001a1e0..c4789ed42e 100644 --- a/selfdrive/ui/translations/main_pt-BR.ts +++ b/selfdrive/ui/translations/main_pt-BR.ts @@ -638,7 +638,7 @@ Isso pode levar até um minuto. System reset triggered. Press confirm to erase all content and settings. Press cancel to resume boot. - Reinicialização do sistema acionada. Pressione confirmar para apagar todo o conteúdo e configurações. Pressione cancel para retomar a inicialização. + Reinicialização do sistema acionada. Pressione confirmar para apagar todo o conteúdo e configurações. Pressione cancel para retomar a inicialização. @@ -748,15 +748,15 @@ Isso pode levar até um minuto. Choose Software to Install - + Escolha o Software a ser Instalado openpilot - openpilot + openpilot Custom Software - + Software Customizado From 85eb221e4c9344a5c135789691e8e0500aa51482 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Harald=20Sch=C3=A4fer?= Date: Wed, 28 Feb 2024 19:55:57 -0800 Subject: [PATCH 27/35] GpsLocation: Rename accuracy to horizontal accuracy (#31629) * Rename accuracy to horizontal accuracy * typo in cereal --- cereal | 2 +- selfdrive/locationd/locationd.cc | 4 ++-- system/ubloxd/tests/print_gps_stats.py | 2 +- system/ubloxd/ublox_msg.cc | 2 +- tools/plotjuggler/layouts/gps_vs_llk.xml | 2 +- tools/plotjuggler/layouts/ublox-debug.xml | 2 +- tools/sim/lib/simulated_sensors.py | 2 +- 7 files changed, 8 insertions(+), 8 deletions(-) diff --git a/cereal b/cereal index 2012d9fd16..2ad942be5b 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 2012d9fd16f62c737951ce2d1eb19d39f0c7615f +Subproject commit 2ad942be5b42532d7919c2127cb531e7178cbd2b diff --git a/selfdrive/locationd/locationd.cc b/selfdrive/locationd/locationd.cc index 1050d68b9b..26999cd684 100644 --- a/selfdrive/locationd/locationd.cc +++ b/selfdrive/locationd/locationd.cc @@ -310,7 +310,7 @@ void Localizer::input_fake_gps_observations(double current_time) { void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::Reader& log, const double sensor_time_offset) { // ignore the message if the fix is invalid bool gps_invalid_flag = (log.getFlags() % 2 == 0); - bool gps_unreasonable = (Vector2d(log.getAccuracy(), log.getVerticalAccuracy()).norm() >= SANE_GPS_UNCERTAINTY); + bool gps_unreasonable = (Vector2d(log.getHorizontalAccuracy(), log.getVerticalAccuracy()).norm() >= SANE_GPS_UNCERTAINTY); bool gps_accuracy_insane = ((log.getVerticalAccuracy() <= 0) || (log.getSpeedAccuracy() <= 0) || (log.getBearingAccuracyDeg() <= 0)); bool gps_lat_lng_alt_insane = ((std::abs(log.getLatitude()) > 90) || (std::abs(log.getLongitude()) > 180) || (std::abs(log.getAltitude()) > ALTITUDE_SANITY_CHECK)); bool gps_vel_insane = (floatlist2vector(log.getVNED()).norm() > TRANS_SANITY_CHECK); @@ -331,7 +331,7 @@ void Localizer::handle_gps(double current_time, const cereal::GpsLocationData::R VectorXd ecef_pos = this->converter->ned2ecef({ 0.0, 0.0, 0.0 }).to_vector(); VectorXd ecef_vel = this->converter->ned2ecef({ log.getVNED()[0], log.getVNED()[1], log.getVNED()[2] }).to_vector() - ecef_pos; - float ecef_pos_std = std::sqrt(this->gps_variance_factor * std::pow(log.getAccuracy(), 2) + this->gps_vertical_variance_factor * std::pow(log.getVerticalAccuracy(), 2)); + float ecef_pos_std = std::sqrt(this->gps_variance_factor * std::pow(log.getHorizontalAccuracy(), 2) + this->gps_vertical_variance_factor * std::pow(log.getVerticalAccuracy(), 2)); MatrixXdr ecef_pos_R = Vector3d::Constant(std::pow(this->gps_std_factor * ecef_pos_std, 2)).asDiagonal(); MatrixXdr ecef_vel_R = Vector3d::Constant(std::pow(this->gps_std_factor * log.getSpeedAccuracy(), 2)).asDiagonal(); diff --git a/system/ubloxd/tests/print_gps_stats.py b/system/ubloxd/tests/print_gps_stats.py index cfddb7f8b8..edf94c060a 100755 --- a/system/ubloxd/tests/print_gps_stats.py +++ b/system/ubloxd/tests/print_gps_stats.py @@ -13,7 +13,7 @@ if __name__ == "__main__": cnos = [] for m in ug.measurementReport.measurements: cnos.append(m.cno) - print("Sats: %d Accuracy: %.2f m cnos" % (ug.measurementReport.numMeas, gle.accuracy), sorted(cnos)) + print("Sats: %d Accuracy: %.2f m cnos" % (ug.measurementReport.numMeas, gle.horizontalAccuracy), sorted(cnos)) except Exception: pass sm.update() diff --git a/system/ubloxd/ublox_msg.cc b/system/ubloxd/ublox_msg.cc index 7b4505dc81..eb1a1e4b19 100644 --- a/system/ubloxd/ublox_msg.cc +++ b/system/ubloxd/ublox_msg.cc @@ -132,7 +132,7 @@ kj::Array UbloxMsgParser::gen_nav_pvt(ubx_t::nav_pvt_t *msg) { gpsLoc.setAltitude(msg->height() * 1e-03); gpsLoc.setSpeed(msg->g_speed() * 1e-03); gpsLoc.setBearingDeg(msg->head_mot() * 1e-5); - gpsLoc.setAccuracy(msg->h_acc() * 1e-03); + gpsLoc.setHorizontalAccuracy(msg->h_acc() * 1e-03); std::tm timeinfo = std::tm(); timeinfo.tm_year = msg->year() - 1900; timeinfo.tm_mon = msg->month() - 1; diff --git a/tools/plotjuggler/layouts/gps_vs_llk.xml b/tools/plotjuggler/layouts/gps_vs_llk.xml index 44980712ed..69b8f20058 100644 --- a/tools/plotjuggler/layouts/gps_vs_llk.xml +++ b/tools/plotjuggler/layouts/gps_vs_llk.xml @@ -32,7 +32,7 @@ - + diff --git a/tools/plotjuggler/layouts/ublox-debug.xml b/tools/plotjuggler/layouts/ublox-debug.xml index d595a9ecc7..ea4dd35535 100644 --- a/tools/plotjuggler/layouts/ublox-debug.xml +++ b/tools/plotjuggler/layouts/ublox-debug.xml @@ -8,7 +8,7 @@ - + diff --git a/tools/sim/lib/simulated_sensors.py b/tools/sim/lib/simulated_sensors.py index df6a0aeeff..e78f984736 100644 --- a/tools/sim/lib/simulated_sensors.py +++ b/tools/sim/lib/simulated_sensors.py @@ -55,7 +55,7 @@ class SimulatedSensors: dat.gpsLocationExternal = { "unixTimestampMillis": int(time.time() * 1000), "flags": 1, # valid fix - "accuracy": 1.0, + "horizontalAccuracy": 1.0, "verticalAccuracy": 1.0, "speedAccuracy": 0.1, "bearingAccuracyDeg": 0.1, From 3a6c3315ab181bf7390ae1faa6e87c93b1a97338 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 23:12:14 -0500 Subject: [PATCH 28/35] Subaru: move to flags within PlatformConfig (#31584) * flags * update ref * use the flags directly * use post_init (don't freeze) * we can maintain frozen with custom class * not preglobal * move to common * cleanup --- common/utils.py | 11 +++++ selfdrive/car/__init__.py | 22 ++++++++-- selfdrive/car/chrysler/values.py | 2 +- selfdrive/car/ford/values.py | 2 +- selfdrive/car/gm/values.py | 2 +- selfdrive/car/interfaces.py | 3 +- selfdrive/car/nissan/values.py | 2 +- selfdrive/car/subaru/carcontroller.py | 13 +++--- selfdrive/car/subaru/carstate.py | 54 ++++++++++++------------ selfdrive/car/subaru/interface.py | 23 +++++----- selfdrive/car/subaru/values.py | 42 ++++++++++++------ selfdrive/car/volkswagen/values.py | 4 +- selfdrive/test/process_replay/ref_commit | 2 +- 13 files changed, 112 insertions(+), 70 deletions(-) create mode 100644 common/utils.py diff --git a/common/utils.py b/common/utils.py new file mode 100644 index 0000000000..b9de020ee6 --- /dev/null +++ b/common/utils.py @@ -0,0 +1,11 @@ +class Freezable: + _frozen: bool = False + + def freeze(self): + if not self._frozen: + self._frozen = True + + def __setattr__(self, *args, **kwargs): + if self._frozen: + raise Exception("cannot modify frozen object") + super().__setattr__(*args, **kwargs) diff --git a/selfdrive/car/__init__.py b/selfdrive/car/__init__.py index 297dc582f7..7f47abbf98 100644 --- a/selfdrive/car/__init__.py +++ b/selfdrive/car/__init__.py @@ -1,12 +1,14 @@ # functions common among cars from collections import namedtuple -from dataclasses import dataclass, field, replace -from enum import ReprEnum +from dataclasses import dataclass, field +from enum import IntFlag, ReprEnum +from dataclasses import replace import capnp from cereal import car from openpilot.common.numpy_fast import clip, interp +from openpilot.common.utils import Freezable from openpilot.selfdrive.car.docs_definitions import CarInfo @@ -256,11 +258,12 @@ class CarSpecs: minEnableSpeed: float = field(default=-1.) -@dataclass(frozen=True, order=True) -class PlatformConfig: +@dataclass(order=True) +class PlatformConfig(Freezable): platform_str: str car_info: CarInfos dbc_dict: DbcDict + flags: int = 0 specs: CarSpecs | None = None @@ -270,6 +273,13 @@ class PlatformConfig: def override(self, **kwargs): return replace(self, **kwargs) + def init(self): + pass + + def __post_init__(self): + self.init() + self.freeze() + class Platforms(str, ReprEnum): config: PlatformConfig @@ -287,3 +297,7 @@ class Platforms(str, ReprEnum): @classmethod def create_carinfo_map(cls) -> dict[str, CarInfos]: return {p: p.config.car_info for p in cls} + + @classmethod + def with_flags(cls, flags: IntFlag) -> set['Platforms']: + return {p for p in cls if p.config.flags & flags} diff --git a/selfdrive/car/chrysler/values.py b/selfdrive/car/chrysler/values.py index 1cc51753d4..8fa7664b66 100644 --- a/selfdrive/car/chrysler/values.py +++ b/selfdrive/car/chrysler/values.py @@ -19,7 +19,7 @@ class ChryslerCarInfo(CarInfo): car_parts: CarParts = field(default_factory=CarParts.common([CarHarness.fca])) -@dataclass(frozen=True) +@dataclass class ChryslerPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('chrysler_pacifica_2017_hybrid_generated', None)) diff --git a/selfdrive/car/ford/values.py b/selfdrive/car/ford/values.py index f969d395d2..e60b7f0612 100644 --- a/selfdrive/car/ford/values.py +++ b/selfdrive/car/ford/values.py @@ -64,7 +64,7 @@ class FordCarInfo(CarInfo): self.car_parts = CarParts([Device.threex, harness]) -@dataclass(frozen=True) +@dataclass class FordPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('ford_lincoln_base_pt', RADAR.DELPHI_MRR)) diff --git a/selfdrive/car/gm/values.py b/selfdrive/car/gm/values.py index ca35b53f72..59b4b6ea30 100644 --- a/selfdrive/car/gm/values.py +++ b/selfdrive/car/gm/values.py @@ -79,7 +79,7 @@ class GMCarInfo(CarInfo): self.footnotes.append(Footnote.OBD_II) -@dataclass(frozen=True) +@dataclass class GMPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('gm_global_a_powertrain_generated', 'gm_global_a_object', chassis_dbc='gm_global_a_chassis')) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 63005e6351..77912e478b 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -120,6 +120,7 @@ class CarInterfaceBase(ABC): ret.centerToFront = ret.wheelbase * candidate.config.specs.centerToFrontRatio ret.minEnableSpeed = candidate.config.specs.minEnableSpeed ret.minSteerSpeed = candidate.config.specs.minSteerSpeed + ret.flags |= int(candidate.config.flags) ret = cls._get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs) @@ -135,7 +136,7 @@ class CarInterfaceBase(ABC): @staticmethod @abstractmethod - def _get_params(ret: car.CarParams, candidate: Platform, fingerprint: dict[int, dict[int, int]], + def _get_params(ret: car.CarParams, candidate, fingerprint: dict[int, dict[int, int]], car_fw: list[car.CarParams.CarFw], experimental_long: bool, docs: bool): raise NotImplementedError diff --git a/selfdrive/car/nissan/values.py b/selfdrive/car/nissan/values.py index 58e4eb051a..7af1700e0b 100644 --- a/selfdrive/car/nissan/values.py +++ b/selfdrive/car/nissan/values.py @@ -31,7 +31,7 @@ class NissanCarSpecs(CarSpecs): steerRatio: float = 17. -@dataclass(frozen=True) +@dataclass class NissanPlaformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('nissan_x_trail_2017_generated', None)) diff --git a/selfdrive/car/subaru/carcontroller.py b/selfdrive/car/subaru/carcontroller.py index 4a65c2c02c..22a1475b5b 100644 --- a/selfdrive/car/subaru/carcontroller.py +++ b/selfdrive/car/subaru/carcontroller.py @@ -3,8 +3,7 @@ from opendbc.can.packer import CANPacker from openpilot.selfdrive.car import apply_driver_steer_torque_limits, common_fault_avoidance from openpilot.selfdrive.car.interfaces import CarControllerBase from openpilot.selfdrive.car.subaru import subarucan -from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, STEER_RATE_LIMITED, \ - CanBus, CarControllerParams, SubaruFlags +from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_ES_ADDR, CanBus, CarControllerParams, SubaruFlags # FIXME: These limits aren't exact. The real limit is more than likely over a larger time period and # involves the total steering angle change rather than rate, but these limits work well for now @@ -43,12 +42,12 @@ class CarController(CarControllerBase): if not CC.latActive: apply_steer = 0 - if self.CP.carFingerprint in PREGLOBAL_CARS: + if self.CP.flags & SubaruFlags.PREGLOBAL: can_sends.append(subarucan.create_preglobal_steering_control(self.packer, self.frame // self.p.STEER_STEP, apply_steer, CC.latActive)) else: apply_steer_req = CC.latActive - if self.CP.carFingerprint in STEER_RATE_LIMITED: + if self.CP.flags & SubaruFlags.STEER_RATE_LIMITED: # Steering rate fault prevention self.steer_rate_counter, apply_steer_req = \ common_fault_avoidance(abs(CS.out.steeringRateDeg) > MAX_STEER_RATE, apply_steer_req, @@ -75,7 +74,7 @@ class CarController(CarControllerBase): cruise_brake = CarControllerParams.BRAKE_MIN # *** alerts and pcm cancel *** - if self.CP.carFingerprint in PREGLOBAL_CARS: + if self.CP.flags & SubaruFlags.PREGLOBAL: if self.frame % 5 == 0: # 1 = main, 2 = set shallow, 3 = set deep, 4 = resume shallow, 5 = resume deep # disengage ACC when OP is disengaged @@ -118,8 +117,8 @@ class CarController(CarControllerBase): self.CP.openpilotLongitudinalControl, cruise_brake > 0, cruise_throttle)) else: if pcm_cancel_cmd: - if self.CP.carFingerprint not in HYBRID_CARS: - bus = CanBus.alt if self.CP.carFingerprint in GLOBAL_GEN2 else CanBus.main + if not (self.CP.flags & SubaruFlags.HYBRID): + bus = CanBus.alt if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else CanBus.main can_sends.append(subarucan.create_es_distance(self.packer, CS.es_distance_msg["COUNTER"] + 1, CS.es_distance_msg, bus, pcm_cancel_cmd)) if self.CP.flags & SubaruFlags.DISABLE_EYESIGHT: diff --git a/selfdrive/car/subaru/carstate.py b/selfdrive/car/subaru/carstate.py index c8a6dfe1e6..ebf0ca9062 100644 --- a/selfdrive/car/subaru/carstate.py +++ b/selfdrive/car/subaru/carstate.py @@ -4,7 +4,7 @@ from opendbc.can.can_define import CANDefine from openpilot.common.conversions import Conversions as CV from openpilot.selfdrive.car.interfaces import CarStateBase from opendbc.can.parser import CANParser -from openpilot.selfdrive.car.subaru.values import DBC, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, CanBus, SubaruFlags +from openpilot.selfdrive.car.subaru.values import DBC, CanBus, SubaruFlags from openpilot.selfdrive.car import CanSignalRateCalculator @@ -19,17 +19,17 @@ class CarState(CarStateBase): def update(self, cp, cp_cam, cp_body): ret = car.CarState.new_message() - throttle_msg = cp.vl["Throttle"] if self.car_fingerprint not in HYBRID_CARS else cp_body.vl["Throttle_Hybrid"] + throttle_msg = cp.vl["Throttle"] if not (self.CP.flags & SubaruFlags.HYBRID) else cp_body.vl["Throttle_Hybrid"] ret.gas = throttle_msg["Throttle_Pedal"] / 255. ret.gasPressed = ret.gas > 1e-5 - if self.car_fingerprint in PREGLOBAL_CARS: + if self.CP.flags & SubaruFlags.PREGLOBAL: ret.brakePressed = cp.vl["Brake_Pedal"]["Brake_Pedal"] > 0 else: - cp_brakes = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp + cp_brakes = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp ret.brakePressed = cp_brakes.vl["Brake_Status"]["Brake"] == 1 - cp_wheels = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp + cp_wheels = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp ret.wheelSpeeds = self.get_wheel_speeds( cp_wheels.vl["Wheel_Speeds"]["FL"], cp_wheels.vl["Wheel_Speeds"]["FR"], @@ -48,24 +48,24 @@ class CarState(CarStateBase): ret.leftBlindspot = (cp.vl["BSD_RCTA"]["L_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["L_APPROACHING"] == 1) ret.rightBlindspot = (cp.vl["BSD_RCTA"]["R_ADJACENT"] == 1) or (cp.vl["BSD_RCTA"]["R_APPROACHING"] == 1) - cp_transmission = cp_body if self.car_fingerprint in HYBRID_CARS else cp + cp_transmission = cp_body if self.CP.flags & SubaruFlags.HYBRID else cp can_gear = int(cp_transmission.vl["Transmission"]["Gear"]) ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(can_gear, None)) ret.steeringAngleDeg = cp.vl["Steering_Torque"]["Steering_Angle"] - if self.car_fingerprint not in PREGLOBAL_CARS: + if not (self.CP.flags & SubaruFlags.PREGLOBAL): # ideally we get this from the car, but unclear if it exists. diagnostic software doesn't even have it ret.steeringRateDeg = self.angle_rate_calulator.update(ret.steeringAngleDeg, cp.vl["Steering_Torque"]["COUNTER"]) ret.steeringTorque = cp.vl["Steering_Torque"]["Steer_Torque_Sensor"] ret.steeringTorqueEps = cp.vl["Steering_Torque"]["Steer_Torque_Output"] - steer_threshold = 75 if self.CP.carFingerprint in PREGLOBAL_CARS else 80 + steer_threshold = 75 if self.CP.flags & SubaruFlags.PREGLOBAL else 80 ret.steeringPressed = abs(ret.steeringTorque) > steer_threshold - cp_cruise = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp - if self.car_fingerprint in HYBRID_CARS: + cp_cruise = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp + if self.CP.flags & SubaruFlags.HYBRID: ret.cruiseState.enabled = cp_cam.vl["ES_DashStatus"]['Cruise_Activated'] != 0 ret.cruiseState.available = cp_cam.vl["ES_DashStatus"]['Cruise_On'] != 0 else: @@ -73,8 +73,8 @@ class CarState(CarStateBase): ret.cruiseState.available = cp_cruise.vl["CruiseControl"]["Cruise_On"] != 0 ret.cruiseState.speed = cp_cam.vl["ES_DashStatus"]["Cruise_Set_Speed"] * CV.KPH_TO_MS - if (self.car_fingerprint in PREGLOBAL_CARS and cp.vl["Dash_State2"]["UNITS"] == 1) or \ - (self.car_fingerprint not in PREGLOBAL_CARS and cp.vl["Dashlights"]["UNITS"] == 1): + if (self.CP.flags & SubaruFlags.PREGLOBAL and cp.vl["Dash_State2"]["UNITS"] == 1) or \ + (not (self.CP.flags & SubaruFlags.PREGLOBAL) and cp.vl["Dashlights"]["UNITS"] == 1): ret.cruiseState.speed *= CV.MPH_TO_KPH ret.seatbeltUnlatched = cp.vl["Dashlights"]["SEATBELT_FL"] == 1 @@ -84,8 +84,8 @@ class CarState(CarStateBase): cp.vl["BodyInfo"]["DOOR_OPEN_FL"]]) ret.steerFaultPermanent = cp.vl["Steering_Torque"]["Steer_Error_1"] == 1 - cp_es_distance = cp_body if self.car_fingerprint in (GLOBAL_GEN2 | HYBRID_CARS) else cp_cam - if self.car_fingerprint in PREGLOBAL_CARS: + cp_es_distance = cp_body if self.CP.flags & (SubaruFlags.GLOBAL_GEN2 | SubaruFlags.HYBRID) else cp_cam + if self.CP.flags & SubaruFlags.PREGLOBAL: self.cruise_button = cp_cam.vl["ES_Distance"]["Cruise_Button"] self.ready = not cp_cam.vl["ES_DashStatus"]["Not_Ready_Startup"] else: @@ -96,12 +96,12 @@ class CarState(CarStateBase): (cp_cam.vl["ES_LKAS_State"]["LKAS_Alert"] == 2) self.es_lkas_state_msg = copy.copy(cp_cam.vl["ES_LKAS_State"]) - cp_es_brake = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp_cam + cp_es_brake = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam self.es_brake_msg = copy.copy(cp_es_brake.vl["ES_Brake"]) - cp_es_status = cp_body if self.car_fingerprint in GLOBAL_GEN2 else cp_cam + cp_es_status = cp_body if self.CP.flags & SubaruFlags.GLOBAL_GEN2 else cp_cam # TODO: Hybrid cars don't have ES_Distance, need a replacement - if self.car_fingerprint not in HYBRID_CARS: + if not (self.CP.flags & SubaruFlags.HYBRID): # 8 is known AEB, there are a few other values related to AEB we ignore ret.stockAeb = (cp_es_distance.vl["ES_Brake"]["AEB_Status"] == 8) and \ (cp_es_distance.vl["ES_Brake"]["Brake_Pressure"] != 0) @@ -109,7 +109,7 @@ class CarState(CarStateBase): self.es_status_msg = copy.copy(cp_es_status.vl["ES_Status"]) self.cruise_control_msg = copy.copy(cp_cruise.vl["CruiseControl"]) - if self.car_fingerprint not in HYBRID_CARS: + if not (self.CP.flags & SubaruFlags.HYBRID): self.es_distance_msg = copy.copy(cp_es_distance.vl["ES_Distance"]) self.es_dashstatus_msg = copy.copy(cp_cam.vl["ES_DashStatus"]) @@ -125,7 +125,7 @@ class CarState(CarStateBase): ("Brake_Status", 50), ] - if CP.carFingerprint not in HYBRID_CARS: + if not (CP.flags & SubaruFlags.HYBRID): messages.append(("CruiseControl", 20)) return messages @@ -136,7 +136,7 @@ class CarState(CarStateBase): ("ES_Brake", 20), ] - if CP.carFingerprint not in HYBRID_CARS: + if not (CP.flags & SubaruFlags.HYBRID): messages += [ ("ES_Distance", 20), ("ES_Status", 20) @@ -164,7 +164,7 @@ class CarState(CarStateBase): ("Brake_Pedal", 50), ] - if CP.carFingerprint not in HYBRID_CARS: + if not (CP.flags & SubaruFlags.HYBRID): messages += [ ("Throttle", 100), ("Transmission", 100) @@ -173,8 +173,8 @@ class CarState(CarStateBase): if CP.enableBsm: messages.append(("BSD_RCTA", 17)) - if CP.carFingerprint not in PREGLOBAL_CARS: - if CP.carFingerprint not in GLOBAL_GEN2: + if not (CP.flags & SubaruFlags.PREGLOBAL): + if not (CP.flags & SubaruFlags.GLOBAL_GEN2): messages += CarState.get_common_global_body_messages(CP) else: messages += CarState.get_common_preglobal_body_messages() @@ -183,7 +183,7 @@ class CarState(CarStateBase): @staticmethod def get_cam_can_parser(CP): - if CP.carFingerprint in PREGLOBAL_CARS: + if CP.flags & SubaruFlags.PREGLOBAL: messages = [ ("ES_DashStatus", 20), ("ES_Distance", 20), @@ -194,7 +194,7 @@ class CarState(CarStateBase): ("ES_LKAS_State", 10), ] - if CP.carFingerprint not in GLOBAL_GEN2: + if not (CP.flags & SubaruFlags.GLOBAL_GEN2): messages += CarState.get_common_global_es_messages(CP) if CP.flags & SubaruFlags.SEND_INFOTAINMENT: @@ -206,11 +206,11 @@ class CarState(CarStateBase): def get_body_can_parser(CP): messages = [] - if CP.carFingerprint in GLOBAL_GEN2: + if CP.flags & SubaruFlags.GLOBAL_GEN2: messages += CarState.get_common_global_body_messages(CP) messages += CarState.get_common_global_es_messages(CP) - if CP.carFingerprint in HYBRID_CARS: + if CP.flags & SubaruFlags.HYBRID: messages += [ ("Throttle_Hybrid", 40), ("Transmission", 100) diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index 2dfb4f9565..ecf718bb3a 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -1,42 +1,43 @@ from cereal import car from panda import Panda from openpilot.selfdrive.car import get_safety_config -from openpilot.selfdrive.car.values import Platform from openpilot.selfdrive.car.disable_ecu import disable_ecu from openpilot.selfdrive.car.interfaces import CarInterfaceBase -from openpilot.selfdrive.car.subaru.values import CAR, GLOBAL_ES_ADDR, LKAS_ANGLE, GLOBAL_GEN2, PREGLOBAL_CARS, HYBRID_CARS, SubaruFlags +from openpilot.selfdrive.car.subaru.values import CAR, GLOBAL_ES_ADDR, SubaruFlags class CarInterface(CarInterfaceBase): @staticmethod - def _get_params(ret, candidate: Platform, fingerprint, car_fw, experimental_long, docs): + def _get_params(ret, candidate: CAR, fingerprint, car_fw, experimental_long, docs): + platform_flags = candidate.config.flags + ret.carName = "subaru" ret.radarUnavailable = True # for HYBRID CARS to be upstreamed, we need: # - replacement for ES_Distance so we can cancel the cruise control # - to find the Cruise_Activated bit from the car # - proper panda safety setup (use the correct cruise_activated bit, throttle from Throttle_Hybrid, etc) - ret.dashcamOnly = candidate in (PREGLOBAL_CARS | LKAS_ANGLE | HYBRID_CARS) + ret.dashcamOnly = bool(platform_flags & (SubaruFlags.PREGLOBAL | SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID)) ret.autoResumeSng = False # Detect infotainment message sent from the camera - if candidate not in PREGLOBAL_CARS and 0x323 in fingerprint[2]: + if not (platform_flags & SubaruFlags.PREGLOBAL) and 0x323 in fingerprint[2]: ret.flags |= SubaruFlags.SEND_INFOTAINMENT.value - if candidate in PREGLOBAL_CARS: + if platform_flags & SubaruFlags.PREGLOBAL: ret.enableBsm = 0x25c in fingerprint[0] ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaruPreglobal)] else: ret.enableBsm = 0x228 in fingerprint[0] ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.subaru)] - if candidate in GLOBAL_GEN2: + if platform_flags & SubaruFlags.GLOBAL_GEN2: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_SUBARU_GEN2 ret.steerLimitTimer = 0.4 ret.steerActuatorDelay = 0.1 - if candidate in LKAS_ANGLE: + if platform_flags & SubaruFlags.LKAS_ANGLE: ret.steerControlType = car.CarParams.SteerControlType.angle else: CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) @@ -84,10 +85,12 @@ class CarInterface(CarInterfaceBase): else: raise ValueError(f"unknown car: {candidate}") - ret.experimentalLongitudinalAvailable = candidate not in (GLOBAL_GEN2 | PREGLOBAL_CARS | LKAS_ANGLE | HYBRID_CARS) + LONG_UNAVAILABLE = SubaruFlags.GLOBAL_GEN2 | SubaruFlags.PREGLOBAL| SubaruFlags.LKAS_ANGLE | SubaruFlags.HYBRID + + ret.experimentalLongitudinalAvailable = not (platform_flags & LONG_UNAVAILABLE) ret.openpilotLongitudinalControl = experimental_long and ret.experimentalLongitudinalAvailable - if candidate in GLOBAL_GEN2 and ret.openpilotLongitudinalControl: + if platform_flags & SubaruFlags.GLOBAL_GEN2 and ret.openpilotLongitudinalControl: ret.flags |= SubaruFlags.DISABLE_EYESIGHT.value if ret.openpilotLongitudinalControl: diff --git a/selfdrive/car/subaru/values.py b/selfdrive/car/subaru/values.py index a296550b12..a7c9a22e2c 100644 --- a/selfdrive/car/subaru/values.py +++ b/selfdrive/car/subaru/values.py @@ -19,7 +19,7 @@ class CarControllerParams: self.STEER_DRIVER_MULTIPLIER = 50 # weight driver torque heavily self.STEER_DRIVER_FACTOR = 1 # from dbc - if CP.carFingerprint in GLOBAL_GEN2: + if CP.flags & SubaruFlags.GLOBAL_GEN2: self.STEER_MAX = 1000 self.STEER_DELTA_UP = 40 self.STEER_DELTA_DOWN = 40 @@ -55,6 +55,14 @@ class CarControllerParams: class SubaruFlags(IntFlag): SEND_INFOTAINMENT = 1 DISABLE_EYESIGHT = 2 + GLOBAL_GEN2 = 4 + + # Cars that temporarily fault when steering angle rate is greater than some threshold. + # Appears to be all torque-based cars produced around 2019 - present + STEER_RATE_LIMITED = 8 + PREGLOBAL = 16 + HYBRID = 32 + LKAS_ANGLE = 64 GLOBAL_ES_ADDR = 0x787 @@ -89,10 +97,14 @@ class SubaruCarInfo(CarInfo): self.footnotes.append(Footnote.EXP_LONG) -@dataclass(frozen=True) +@dataclass class SubaruPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('subaru_global_2017_generated', None)) + def init(self): + if self.flags & SubaruFlags.HYBRID: + self.dbc_dict = dbc_dict('subaru_global_2020_hybrid_generated', None) + class CAR(Platforms): # Global platform @@ -105,11 +117,13 @@ class CAR(Platforms): "SUBARU OUTBACK 6TH GEN", SubaruCarInfo("Subaru Outback 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])), specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.STEER_RATE_LIMITED, ) LEGACY = SubaruPlatformConfig( "SUBARU LEGACY 7TH GEN", SubaruCarInfo("Subaru Legacy 2020-22", "All", car_parts=CarParts.common([CarHarness.subaru_b])), specs=OUTBACK.specs, + flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.STEER_RATE_LIMITED, ) IMPREZA = SubaruPlatformConfig( "SUBARU IMPREZA LIMITED 2019", @@ -128,24 +142,26 @@ class CAR(Platforms): SubaruCarInfo("Subaru XV 2020-21"), ], specs=CarSpecs(mass=1480, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.STEER_RATE_LIMITED, ) # TODO: is there an XV and Impreza too? CROSSTREK_HYBRID = SubaruPlatformConfig( "SUBARU CROSSTREK HYBRID 2020", SubaruCarInfo("Subaru Crosstrek Hybrid 2020", car_parts=CarParts.common([CarHarness.subaru_b])), - dbc_dict('subaru_global_2020_hybrid_generated', None), specs=CarSpecs(mass=1668, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.HYBRID, ) FORESTER = SubaruPlatformConfig( "SUBARU FORESTER 2019", SubaruCarInfo("Subaru Forester 2019-21", "All"), specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=17), + flags=SubaruFlags.STEER_RATE_LIMITED, ) FORESTER_HYBRID = SubaruPlatformConfig( "SUBARU FORESTER HYBRID 2020", SubaruCarInfo("Subaru Forester Hybrid 2020"), - dbc_dict('subaru_global_2020_hybrid_generated', None), specs=FORESTER.specs, + flags=SubaruFlags.HYBRID, ) # Pre-global FORESTER_PREGLOBAL = SubaruPlatformConfig( @@ -153,52 +169,50 @@ class CAR(Platforms): SubaruCarInfo("Subaru Forester 2017-18"), dbc_dict('subaru_forester_2017_generated', None), specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=20), + flags=SubaruFlags.PREGLOBAL, ) LEGACY_PREGLOBAL = SubaruPlatformConfig( "SUBARU LEGACY 2015 - 2018", SubaruCarInfo("Subaru Legacy 2015-18"), dbc_dict('subaru_outback_2015_generated', None), specs=CarSpecs(mass=1568, wheelbase=2.67, steerRatio=12.5), + flags=SubaruFlags.PREGLOBAL, ) OUTBACK_PREGLOBAL = SubaruPlatformConfig( "SUBARU OUTBACK 2015 - 2017", SubaruCarInfo("Subaru Outback 2015-17"), dbc_dict('subaru_outback_2015_generated', None), specs=FORESTER_PREGLOBAL.specs, + flags=SubaruFlags.PREGLOBAL, ) OUTBACK_PREGLOBAL_2018 = SubaruPlatformConfig( "SUBARU OUTBACK 2018 - 2019", SubaruCarInfo("Subaru Outback 2018-19"), dbc_dict('subaru_outback_2019_generated', None), specs=FORESTER_PREGLOBAL.specs, + flags=SubaruFlags.PREGLOBAL, ) # Angle LKAS FORESTER_2022 = SubaruPlatformConfig( "SUBARU FORESTER 2022", SubaruCarInfo("Subaru Forester 2022-24", "All", car_parts=CarParts.common([CarHarness.subaru_c])), specs=FORESTER.specs, + flags=SubaruFlags.LKAS_ANGLE, ) OUTBACK_2023 = SubaruPlatformConfig( "SUBARU OUTBACK 7TH GEN", SubaruCarInfo("Subaru Outback 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])), specs=OUTBACK.specs, + flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.LKAS_ANGLE, ) ASCENT_2023 = SubaruPlatformConfig( "SUBARU ASCENT 2023", SubaruCarInfo("Subaru Ascent 2023", "All", car_parts=CarParts.common([CarHarness.subaru_d])), specs=ASCENT.specs, + flags=SubaruFlags.GLOBAL_GEN2 | SubaruFlags.LKAS_ANGLE, ) -LKAS_ANGLE = {CAR.FORESTER_2022, CAR.OUTBACK_2023, CAR.ASCENT_2023} -GLOBAL_GEN2 = {CAR.OUTBACK, CAR.LEGACY, CAR.OUTBACK_2023, CAR.ASCENT_2023} -PREGLOBAL_CARS = {CAR.FORESTER_PREGLOBAL, CAR.LEGACY_PREGLOBAL, CAR.OUTBACK_PREGLOBAL, CAR.OUTBACK_PREGLOBAL_2018} -HYBRID_CARS = {CAR.CROSSTREK_HYBRID, CAR.FORESTER_HYBRID} - -# Cars that temporarily fault when steering angle rate is greater than some threshold. -# Appears to be all torque-based cars produced around 2019 - present -STEER_RATE_LIMITED = GLOBAL_GEN2 | {CAR.IMPREZA_2020, CAR.FORESTER} - SUBARU_VERSION_REQUEST = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER]) + \ p16(uds.DATA_IDENTIFIER_TYPE.APPLICATION_DATA_IDENTIFICATION) SUBARU_VERSION_RESPONSE = bytes([uds.SERVICE_TYPE.READ_DATA_BY_IDENTIFIER + 0x40]) + \ @@ -235,7 +249,7 @@ FW_QUERY_CONFIG = FwQueryConfig( ], # We don't get the EPS from non-OBD queries on GEN2 cars. Note that we still attempt to match when it exists non_essential_ecus={ - Ecu.eps: list(GLOBAL_GEN2), + Ecu.eps: list(CAR.with_flags(SubaruFlags.GLOBAL_GEN2)), } ) diff --git a/selfdrive/car/volkswagen/values.py b/selfdrive/car/volkswagen/values.py index 3344d58ea9..3e4a742224 100644 --- a/selfdrive/car/volkswagen/values.py +++ b/selfdrive/car/volkswagen/values.py @@ -112,11 +112,11 @@ class CANBUS: class VolkswagenFlags(IntFlag): STOCK_HCA_PRESENT = 1 -@dataclass(frozen=True) +@dataclass class VolkswagenMQBPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_mqb_2010', None)) -@dataclass(frozen=True) +@dataclass class VolkswagenPQPlatformConfig(PlatformConfig): dbc_dict: DbcDict = field(default_factory=lambda: dbc_dict('vw_golf_mk4', None)) diff --git a/selfdrive/test/process_replay/ref_commit b/selfdrive/test/process_replay/ref_commit index 0fa4652e4c..13f776fbad 100644 --- a/selfdrive/test/process_replay/ref_commit +++ b/selfdrive/test/process_replay/ref_commit @@ -1 +1 @@ -dab93e072903e80f91029a03600430c43c722cb7 +b9d29ac9402cfc04bf3e48867415efa70c144029 From 851df7458fc13e15244a7d83196d70c71e56d712 Mon Sep 17 00:00:00 2001 From: Justin Newberry Date: Wed, 28 Feb 2024 23:22:54 -0500 Subject: [PATCH 29/35] pr comments: only on external prs (#31635) only on external prs --- .github/workflows/auto_pr_review.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/auto_pr_review.yaml b/.github/workflows/auto_pr_review.yaml index 0720c1e676..42ef4dbc1c 100644 --- a/.github/workflows/auto_pr_review.yaml +++ b/.github/workflows/auto_pr_review.yaml @@ -39,6 +39,7 @@ jobs: steps: - name: comment uses: thollander/actions-comment-pull-request@fabd468d3a1a0b97feee5f6b9e499eab0dd903f6 + if: github.event.pull_request.head.repo.full_name != 'commaai/openpilot' with: message: | From f20bfacb9434d5f9d2a6692352c1f686dec9327f Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 28 Feb 2024 20:22:59 -0800 Subject: [PATCH 30/35] move CarControllerBase up with other car classes --- selfdrive/car/interfaces.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 77912e478b..491138f788 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -456,6 +456,15 @@ class CarStateBase(ABC): return None +SendCan = tuple[int, int, bytes, int] + + +class CarControllerBase(ABC): + @abstractmethod + def update(self, CC, CS, now_nanos) -> tuple[car.CarControl.Actuators, list[SendCan]]: + pass + + INTERFACE_ATTR_FILE = { "FINGERPRINTS": "fingerprints", "FW_VERSIONS": "fingerprints", @@ -519,12 +528,3 @@ class NanoFFModel: pred = x[0] pred = pred * (self.weights['output_norm_mat'][1] - self.weights['output_norm_mat'][0]) + self.weights['output_norm_mat'][0] return pred - - -SendCan = tuple[int, int, bytes, int] - - -class CarControllerBase(ABC): - @abstractmethod - def update(self, CC, CS, now_nanos) -> tuple[car.CarControl.Actuators, list[SendCan]]: - pass From e4e9243f8d25711627bb4490ebb5255770e5f92c Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 28 Feb 2024 20:23:05 -0800 Subject: [PATCH 31/35] bump cereal --- cereal | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cereal b/cereal index 2ad942be5b..bfbb0cab83 160000 --- a/cereal +++ b/cereal @@ -1 +1 @@ -Subproject commit 2ad942be5b42532d7919c2127cb531e7178cbd2b +Subproject commit bfbb0cab83e3ad49d85ad1a34ee1241bf1ff782f From 7e7a6b1526ef8e3628a8125ca8f95919993fa6f6 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 28 Feb 2024 20:34:44 -0800 Subject: [PATCH 32/35] bump panda --- panda | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/panda b/panda index 0c7d5f11d7..ea156f7c62 160000 --- a/panda +++ b/panda @@ -1 +1 @@ -Subproject commit 0c7d5f11d7187904022ea49b6a76b54d7b280345 +Subproject commit ea156f7c628a371bea9a15a29f9068d5392534ba From e0a80d34d993fb4e7f2247ed3fc853d6e925f08e Mon Sep 17 00:00:00 2001 From: vanillagorillaa <31773928+vanillagorillaa@users.noreply.github.com> Date: Wed, 28 Feb 2024 20:45:48 -0800 Subject: [PATCH 33/35] Honda: add CanBus class (#31528) * init canbus class * zero * put back after rebase * cmt * ordering * fix bsm bus --------- Co-authored-by: Shane Smiskol --- selfdrive/car/honda/carcontroller.py | 15 +++---- selfdrive/car/honda/carstate.py | 8 ++-- selfdrive/car/honda/hondacan.py | 63 ++++++++++++++++++---------- selfdrive/car/honda/interface.py | 12 +++--- 4 files changed, 59 insertions(+), 39 deletions(-) diff --git a/selfdrive/car/honda/carcontroller.py b/selfdrive/car/honda/carcontroller.py index 8170e1e9ef..547abcd9b9 100644 --- a/selfdrive/car/honda/carcontroller.py +++ b/selfdrive/car/honda/carcontroller.py @@ -110,6 +110,7 @@ class CarController(CarControllerBase): self.CP = CP self.packer = CANPacker(dbc_name) self.params = CarControllerParams(CP) + self.CAN = hondacan.CanBus(CP) self.frame = 0 self.braking = False @@ -168,7 +169,7 @@ class CarController(CarControllerBase): can_sends.append((0x18DAB0F1, 0, b"\x02\x3E\x80\x00\x00\x00\x00\x00", 1)) # Send steering command. - can_sends.append(hondacan.create_steering_control(self.packer, apply_steer, CC.latActive, self.CP.carFingerprint, + can_sends.append(hondacan.create_steering_control(self.packer, self.CAN, apply_steer, CC.latActive, self.CP.carFingerprint, CS.CP.openpilotLongitudinalControl)) # wind brake from air resistance decel at high speed @@ -202,12 +203,12 @@ class CarController(CarControllerBase): if not self.CP.openpilotLongitudinalControl: if self.frame % 2 == 0 and self.CP.carFingerprint not in HONDA_BOSCH_RADARLESS: # radarless cars don't have supplemental message - can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, self.CP.carFingerprint)) + can_sends.append(hondacan.create_bosch_supplemental_1(self.packer, self.CAN, self.CP.carFingerprint)) # If using stock ACC, spam cancel command to kill gas when OP disengages. if pcm_cancel_cmd: - can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.CANCEL, self.CP.carFingerprint)) + can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.CANCEL, self.CP.carFingerprint)) elif CC.cruiseControl.resume: - can_sends.append(hondacan.spam_buttons_command(self.packer, CruiseButtons.RES_ACCEL, self.CP.carFingerprint)) + can_sends.append(hondacan.spam_buttons_command(self.packer, self.CAN, CruiseButtons.RES_ACCEL, self.CP.carFingerprint)) else: # Send gas and brake commands. @@ -220,7 +221,7 @@ class CarController(CarControllerBase): stopping = actuators.longControlState == LongCtrlState.stopping self.stopping_counter = self.stopping_counter + 1 if stopping else 0 - can_sends.extend(hondacan.create_acc_commands(self.packer, CC.enabled, CC.longActive, self.accel, self.gas, + can_sends.extend(hondacan.create_acc_commands(self.packer, self.CAN, CC.enabled, CC.longActive, self.accel, self.gas, self.stopping_counter, self.CP.carFingerprint)) else: apply_brake = clip(self.brake_last - wind_brake, 0.0, 1.0) @@ -228,7 +229,7 @@ class CarController(CarControllerBase): pump_on, self.last_pump_ts = brake_pump_hysteresis(apply_brake, self.apply_brake_last, self.last_pump_ts, ts) pcm_override = True - can_sends.append(hondacan.create_brake_command(self.packer, apply_brake, pump_on, + can_sends.append(hondacan.create_brake_command(self.packer, self.CAN, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw_display, self.CP.carFingerprint, CS.stock_brake)) self.apply_brake_last = apply_brake @@ -251,7 +252,7 @@ class CarController(CarControllerBase): if self.frame % 10 == 0: hud = HUDData(int(pcm_accel), int(round(hud_v_cruise)), hud_control.leadVisible, hud_control.lanesVisible, fcw_display, acc_alert, steer_required) - can_sends.extend(hondacan.create_ui_commands(self.packer, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, CS.acc_hud, CS.lkas_hud)) + can_sends.extend(hondacan.create_ui_commands(self.packer, self.CAN, self.CP, CC.enabled, pcm_speed, hud, CS.is_metric, CS.acc_hud, CS.lkas_hud)) if self.CP.openpilotLongitudinalControl and self.CP.carFingerprint not in HONDA_BOSCH: self.speed = pcm_speed diff --git a/selfdrive/car/honda/carstate.py b/selfdrive/car/honda/carstate.py index 4f5337813b..7784581e1c 100644 --- a/selfdrive/car/honda/carstate.py +++ b/selfdrive/car/honda/carstate.py @@ -5,7 +5,7 @@ from openpilot.common.conversions import Conversions as CV from openpilot.common.numpy_fast import interp from opendbc.can.can_define import CANDefine from opendbc.can.parser import CANParser -from openpilot.selfdrive.car.honda.hondacan import get_cruise_speed_conversion, get_pt_bus +from openpilot.selfdrive.car.honda.hondacan import CanBus, get_cruise_speed_conversion from openpilot.selfdrive.car.honda.values import CAR, DBC, STEER_THRESHOLD, HONDA_BOSCH, \ HONDA_NIDEC_ALT_SCM_MESSAGES, HONDA_BOSCH_RADARLESS, \ HondaFlags @@ -267,7 +267,7 @@ class CarState(CarStateBase): def get_can_parser(self, CP): messages = get_can_messages(CP, self.gearbox_msg) - return CANParser(DBC[CP.carFingerprint]["pt"], messages, get_pt_bus(CP.carFingerprint)) + return CANParser(DBC[CP.carFingerprint]["pt"], messages, CanBus(CP).pt) @staticmethod def get_cam_can_parser(CP): @@ -287,7 +287,7 @@ class CarState(CarStateBase): ("BRAKE_COMMAND", 50), ] - return CANParser(DBC[CP.carFingerprint]["pt"], messages, 2) + return CANParser(DBC[CP.carFingerprint]["pt"], messages, CanBus(CP).camera) @staticmethod def get_body_can_parser(CP): @@ -296,6 +296,6 @@ class CarState(CarStateBase): ("BSM_STATUS_LEFT", 3), ("BSM_STATUS_RIGHT", 3), ] - bus_body = 0 # B-CAN is forwarded to ACC-CAN radar side (CAN 0 on fake ethernet port) + bus_body = CanBus(CP).radar # B-CAN is forwarded to ACC-CAN radar side (CAN 0 on fake ethernet port) return CANParser(DBC[CP.carFingerprint]["body"], messages, bus_body) return None diff --git a/selfdrive/car/honda/hondacan.py b/selfdrive/car/honda/hondacan.py index a8cbad78ce..d10d5576d9 100644 --- a/selfdrive/car/honda/hondacan.py +++ b/selfdrive/car/honda/hondacan.py @@ -1,4 +1,5 @@ from openpilot.common.conversions import Conversions as CV +from openpilot.selfdrive.car import CanBusBase from openpilot.selfdrive.car.honda.values import HondaFlags, HONDA_BOSCH, HONDA_BOSCH_RADARLESS, CAR, CarControllerParams # CAN bus layout with relay @@ -8,15 +9,34 @@ from openpilot.selfdrive.car.honda.values import HondaFlags, HONDA_BOSCH, HONDA_ # 3 = F-CAN A - OBDII port -def get_pt_bus(car_fingerprint): - return 1 if car_fingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) else 0 +class CanBus(CanBusBase): + def __init__(self, CP=None, fingerprint=None) -> None: + # use fingerprint if specified + super().__init__(CP if fingerprint is None else None, fingerprint) + + if CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS): + self._pt, self._radar = self.offset + 1, self.offset + else: + self._pt, self._radar = self.offset, self.offset + 1 + + @property + def pt(self) -> int: + return self._pt + + @property + def radar(self) -> int: + return self._radar + + @property + def camera(self) -> int: + return self.offset + 2 -def get_lkas_cmd_bus(car_fingerprint, radar_disabled=False): +def get_lkas_cmd_bus(CAN, car_fingerprint, radar_disabled=False): no_radar = car_fingerprint in HONDA_BOSCH_RADARLESS if radar_disabled or no_radar: # when radar is disabled, steering commands are sent directly to powertrain bus - return get_pt_bus(car_fingerprint) + return CAN.pt # normally steering commands are sent to radar, which forwards them to powertrain bus return 0 @@ -26,7 +46,7 @@ def get_cruise_speed_conversion(car_fingerprint: str, is_metric: bool) -> float: return CV.MPH_TO_MS if car_fingerprint in HONDA_BOSCH_RADARLESS and not is_metric else CV.KPH_TO_MS -def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, car_fingerprint, stock_brake): +def create_brake_command(packer, CAN, apply_brake, pump_on, pcm_override, pcm_cancel_cmd, fcw, car_fingerprint, stock_brake): # TODO: do we loose pressure if we keep pump off for long? brakelights = apply_brake > 0 brake_rq = apply_brake > 0 @@ -47,13 +67,11 @@ def create_brake_command(packer, apply_brake, pump_on, pcm_override, pcm_cancel_ "AEB_REQ_2": 0, "AEB_STATUS": 0, } - bus = get_pt_bus(car_fingerprint) - return packer.make_can_msg("BRAKE_COMMAND", bus, values) + return packer.make_can_msg("BRAKE_COMMAND", CAN.pt, values) -def create_acc_commands(packer, enabled, active, accel, gas, stopping_counter, car_fingerprint): +def create_acc_commands(packer, CAN, enabled, active, accel, gas, stopping_counter, car_fingerprint): commands = [] - bus = get_pt_bus(car_fingerprint) min_gas_accel = CarControllerParams.BOSCH_GAS_LOOKUP_BP[0] control_on = 5 if enabled else 0 @@ -90,37 +108,36 @@ def create_acc_commands(packer, enabled, active, accel, gas, stopping_counter, c "SET_TO_75": 0x75, "SET_TO_30": 0x30, } - commands.append(packer.make_can_msg("ACC_CONTROL_ON", bus, acc_control_on_values)) + commands.append(packer.make_can_msg("ACC_CONTROL_ON", CAN.pt, acc_control_on_values)) - commands.append(packer.make_can_msg("ACC_CONTROL", bus, acc_control_values)) + commands.append(packer.make_can_msg("ACC_CONTROL", CAN.pt, acc_control_values)) return commands -def create_steering_control(packer, apply_steer, lkas_active, car_fingerprint, radar_disabled): +def create_steering_control(packer, CAN, apply_steer, lkas_active, car_fingerprint, radar_disabled): values = { "STEER_TORQUE": apply_steer if lkas_active else 0, "STEER_TORQUE_REQUEST": lkas_active, } - bus = get_lkas_cmd_bus(car_fingerprint, radar_disabled) + bus = get_lkas_cmd_bus(CAN, car_fingerprint, radar_disabled) return packer.make_can_msg("STEERING_CONTROL", bus, values) -def create_bosch_supplemental_1(packer, car_fingerprint): +def create_bosch_supplemental_1(packer, CAN, car_fingerprint): # non-active params values = { "SET_ME_X04": 0x04, "SET_ME_X80": 0x80, "SET_ME_X10": 0x10, } - bus = get_lkas_cmd_bus(car_fingerprint) + bus = get_lkas_cmd_bus(CAN, car_fingerprint) return packer.make_can_msg("BOSCH_SUPPLEMENTAL_1", bus, values) -def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, lkas_hud): +def create_ui_commands(packer, CAN, CP, enabled, pcm_speed, hud, is_metric, acc_hud, lkas_hud): commands = [] - bus_pt = get_pt_bus(CP.carFingerprint) radar_disabled = CP.carFingerprint in (HONDA_BOSCH - HONDA_BOSCH_RADARLESS) and CP.openpilotLongitudinalControl - bus_lkas = get_lkas_cmd_bus(CP.carFingerprint, radar_disabled) + bus_lkas = get_lkas_cmd_bus(CAN, CP.carFingerprint, radar_disabled) if CP.openpilotLongitudinalControl: acc_hud_values = { @@ -144,7 +161,7 @@ def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, acc_hud_values['FCM_OFF_2'] = acc_hud['FCM_OFF_2'] acc_hud_values['FCM_PROBLEM'] = acc_hud['FCM_PROBLEM'] acc_hud_values['ICONS'] = acc_hud['ICONS'] - commands.append(packer.make_can_msg("ACC_HUD", bus_pt, acc_hud_values)) + commands.append(packer.make_can_msg("ACC_HUD", CAN.pt, acc_hud_values)) lkas_hud_values = { 'SET_ME_X41': 0x41, @@ -173,19 +190,19 @@ def create_ui_commands(packer, CP, enabled, pcm_speed, hud, is_metric, acc_hud, 'CMBS_OFF': 0x01, 'SET_TO_1': 0x01, } - commands.append(packer.make_can_msg('RADAR_HUD', bus_pt, radar_hud_values)) + commands.append(packer.make_can_msg('RADAR_HUD', CAN.pt, radar_hud_values)) if CP.carFingerprint == CAR.CIVIC_BOSCH: - commands.append(packer.make_can_msg("LEGACY_BRAKE_COMMAND", bus_pt, {})) + commands.append(packer.make_can_msg("LEGACY_BRAKE_COMMAND", CAN.pt, {})) return commands -def spam_buttons_command(packer, button_val, car_fingerprint): +def spam_buttons_command(packer, CAN, button_val, car_fingerprint): values = { 'CRUISE_BUTTONS': button_val, 'CRUISE_SETTING': 0, } # send buttons to camera on radarless cars - bus = 2 if car_fingerprint in HONDA_BOSCH_RADARLESS else get_pt_bus(car_fingerprint) + bus = CAN.camera if car_fingerprint in HONDA_BOSCH_RADARLESS else CAN.pt return packer.make_can_msg("SCM_BUTTONS", bus, values) diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 041ab67a97..a4cf647c0f 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -3,7 +3,7 @@ from cereal import car from panda import Panda from openpilot.common.conversions import Conversions as CV from openpilot.common.numpy_fast import interp -from openpilot.selfdrive.car.honda.hondacan import get_pt_bus +from openpilot.selfdrive.car.honda.hondacan import CanBus from openpilot.selfdrive.car.honda.values import CarControllerParams, CruiseButtons, HondaFlags, CAR, HONDA_BOSCH, HONDA_NIDEC_ALT_SCM_MESSAGES, \ HONDA_BOSCH_RADARLESS from openpilot.selfdrive.car import create_button_events, get_safety_config @@ -36,6 +36,8 @@ class CarInterface(CarInterfaceBase): def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): ret.carName = "honda" + CAN = CanBus(ret, fingerprint) + if candidate in HONDA_BOSCH: ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaBosch)] ret.radarUnavailable = True @@ -47,20 +49,20 @@ class CarInterface(CarInterfaceBase): ret.pcmCruise = not ret.openpilotLongitudinalControl else: ret.safetyConfigs = [get_safety_config(car.CarParams.SafetyModel.hondaNidec)] - ret.enableGasInterceptor = 0x201 in fingerprint[0] + ret.enableGasInterceptor = 0x201 in fingerprint[CAN.pt] ret.openpilotLongitudinalControl = True ret.pcmCruise = not ret.enableGasInterceptor if candidate == CAR.CRV_5G: - ret.enableBsm = 0x12f8bfa7 in fingerprint[0] + ret.enableBsm = 0x12f8bfa7 in fingerprint[CAN.radar] # Detect Bosch cars with new HUD msgs if any(0x33DA in f for f in fingerprint.values()): ret.flags |= HondaFlags.BOSCH_EXT_HUD.value # Accord ICE 1.5T CVT has different gearbox message - if candidate == CAR.ACCORD and 0x191 in fingerprint[1]: + if candidate == CAR.ACCORD and 0x191 in fingerprint[CAN.pt]: ret.transmissionType = TransmissionType.cvt # Certain Hondas have an extra steering sensor at the bottom of the steering rack, @@ -276,7 +278,7 @@ class CarInterface(CarInterfaceBase): raise ValueError(f"unsupported car {candidate}") # These cars use alternate user brake msg (0x1BE) - if 0x1BE in fingerprint[get_pt_bus(candidate)] and candidate in HONDA_BOSCH: + if 0x1BE in fingerprint[CAN.pt] and candidate in HONDA_BOSCH: ret.flags |= HondaFlags.BOSCH_ALT_BRAKE.value ret.safetyConfigs[0].safetyParam |= Panda.FLAG_HONDA_ALT_BRAKE From 7687cafe8cc805a8be139c4d8a797bffd0df3fc8 Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Wed, 28 Feb 2024 20:47:49 -0800 Subject: [PATCH 34/35] Ford: remove unnecessary __init__ --- selfdrive/car/ford/fordcan.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/selfdrive/car/ford/fordcan.py b/selfdrive/car/ford/fordcan.py index c5ef0900f3..e99ae084e6 100644 --- a/selfdrive/car/ford/fordcan.py +++ b/selfdrive/car/ford/fordcan.py @@ -5,9 +5,6 @@ HUDControl = car.CarControl.HUDControl class CanBus(CanBusBase): - def __init__(self, CP=None, fingerprint=None) -> None: - super().__init__(CP, fingerprint) - @property def main(self) -> int: return self.offset From b8c9d3bd09171a5b9a30cb91a262e9c089d28cfd Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Wed, 28 Feb 2024 21:13:26 -0800 Subject: [PATCH 35/35] Revert "Ford: remove unnecessary __init__" This reverts commit 7687cafe8cc805a8be139c4d8a797bffd0df3fc8. --- selfdrive/car/ford/fordcan.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/selfdrive/car/ford/fordcan.py b/selfdrive/car/ford/fordcan.py index e99ae084e6..c5ef0900f3 100644 --- a/selfdrive/car/ford/fordcan.py +++ b/selfdrive/car/ford/fordcan.py @@ -5,6 +5,9 @@ HUDControl = car.CarControl.HUDControl class CanBus(CanBusBase): + def __init__(self, CP=None, fingerprint=None) -> None: + super().__init__(CP, fingerprint) + @property def main(self) -> int: return self.offset