diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index b5550649d2..94deba4783 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -7,13 +7,9 @@ on: - master-new pull_request: -# TODO: enable this -#env: -# PYTHONWARNINGS: error,default::DeprecationWarning - jobs: - unit-tests: - name: unit tests + tests: + name: ./test.sh runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -22,31 +18,4 @@ jobs: steps: - uses: commaai/timeout@v1 - uses: actions/checkout@v4 - - name: install uv and dependencies - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - # TODO: remove setuptools once https://github.com/cython/cython/issues/5751 is fixed - uv pip install -e .[testing,docs] setuptools - - run: uv run scons -j8 - - run: uv run pytest . - - static-analysis: - name: static analysis - runs-on: ubuntu-24.04 - steps: - - uses: commaai/timeout@v1 - - uses: actions/checkout@v4 - - name: setup python - run: | - curl -LsSf https://astral.sh/uv/install.sh | sh - uv venv - uv pip install -e . pre-commit - - name: cache pre-commit environments - uses: actions/cache@v4 - with: - path: ~/.cache/pre-commit - key: ${{ runner.os }}-pre-commit-${{ hashFiles('.pre-commit-config.yaml') }} - restore-keys: | - ${{ runner.os }}-pre-commit- - - run: uv run pre-commit run --all + - run: ./test.sh diff --git a/README.md b/README.md index 9e19db75f5..0b6af2f39f 100644 --- a/README.md +++ b/README.md @@ -39,11 +39,15 @@ Everything you need to know to use, contribute, and extend opendbc are in these git clone https://github.com/commaai/opendbc.git cd opendbc +# you probably just want to use this. it's an all-in-one for dependency +# installation, compiling, linting, and tests. it's also what runs in CI +./test.sh + +# here are the individual commands it runs pip3 install -e .[testing,docs] # install dependencies scons -j8 # build with 8 cores pytest . # run the tests pre-commit run --all-files # run the linter -./test.sh # all-in-one for setup, build, lint, and test ``` [`examples/`](examples/) contains small example programs that can read state from the car and control the steering, gas, and brakes. diff --git a/docs/CARS.md b/docs/CARS.md index 1322bf9499..0a1a187866 100644 --- a/docs/CARS.md +++ b/docs/CARS.md @@ -1,6 +1,6 @@ -# Support Information for 343 Known Cars +# Support Information for 344 Known Cars |Make|Model|Package|Support Level| |---|---|---|:---:| @@ -30,12 +30,12 @@ |comma|body|All|[Upstream](#upstream)| |CUPRA|Ateca 2018-23|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| |Dodge|Durango 2020-21|Adaptive Cruise Control (ACC)|[Upstream](#upstream)| -|Ford|Bronco Sport 2021-23|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Bronco Sport 2021-24|Co-Pilot360 Assist+|[Upstream](#upstream)| |Ford|Escape 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| |Ford|Escape Hybrid 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| |Ford|Escape Plug-in Hybrid 2020-22|Co-Pilot360 Assist+|[Upstream](#upstream)| -|Ford|Explorer 2020-23|Co-Pilot360 Assist+|[Upstream](#upstream)| -|Ford|Explorer Hybrid 2020-23|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Explorer 2020-24|Co-Pilot360 Assist+|[Upstream](#upstream)| +|Ford|Explorer Hybrid 2020-24|Co-Pilot360 Assist+|[Upstream](#upstream)| |Ford|F-150 2022-23|Co-Pilot360 Active 2.0|[Under review](#under-review)| |Ford|F-150 Hybrid 2022-23|Co-Pilot360 Active 2.0|[Under review](#under-review)| |Ford|F-150 Lightning 2021-23|Co-Pilot360 Active 2.0|[Under review](#under-review)| @@ -64,6 +64,7 @@ |Genesis|GV70 Electrified (with HDA II) 2023|Highway Driving Assist II|[Upstream](#upstream)| |Genesis|GV80 2023|All|[Upstream](#upstream)| |GMC|Sierra 1500 2020-21|Driver Alert Package II|[Upstream](#upstream)| +|GMC|Yukon 2019-20|Adaptive Cruise Control (ACC) & LKAS|[Dashcam mode](#dashcam)| |Honda|Accord 2018-22|All|[Upstream](#upstream)| |Honda|Accord 2023-24|All|[Community](#community)| |Honda|Accord Hybrid 2018-22|All|[Upstream](#upstream)| @@ -76,7 +77,7 @@ |Honda|CR-V 2015-16|Touring Trim|[Upstream](#upstream)| |Honda|CR-V 2017-22|Honda Sensing|[Upstream](#upstream)| |Honda|CR-V 2024|All|[Community](#community)| -|Honda|CR-V Hybrid 2017-21|Honda Sensing|[Upstream](#upstream)| +|Honda|CR-V Hybrid 2017-22|Honda Sensing|[Upstream](#upstream)| |Honda|CR-V Hybrid 2024|All|[Community](#community)| |Honda|e 2020|All|[Upstream](#upstream)| |Honda|Fit 2018-20|Honda Sensing|[Upstream](#upstream)| @@ -181,7 +182,7 @@ |Lexus|ES 2017-18|All|[Upstream](#upstream)| |Lexus|ES 2019-24|All|[Upstream](#upstream)| |Lexus|ES Hybrid 2017-18|All|[Upstream](#upstream)| -|Lexus|ES Hybrid 2019-24|All|[Upstream](#upstream)| +|Lexus|ES Hybrid 2019-25|All|[Upstream](#upstream)| |Lexus|GS F 2016|All|[Upstream](#upstream)| |Lexus|IS 2017-19|All|[Upstream](#upstream)| |Lexus|IS 2022-23|All|[Upstream](#upstream)| @@ -199,14 +200,14 @@ |Lexus|RX Hybrid 2017-19|All|[Upstream](#upstream)| |Lexus|RX Hybrid 2020-22|All|[Upstream](#upstream)| |Lexus|UX Hybrid 2019-23|All|[Upstream](#upstream)| -|Lincoln|Aviator 2020-23|Co-Pilot360 Plus|[Upstream](#upstream)| -|Lincoln|Aviator Plug-in Hybrid 2020-23|Co-Pilot360 Plus|[Upstream](#upstream)| +|Lincoln|Aviator 2020-24|Co-Pilot360 Plus|[Upstream](#upstream)| +|Lincoln|Aviator Plug-in Hybrid 2020-24|Co-Pilot360 Plus|[Upstream](#upstream)| |MAN|eTGE 2020-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| |MAN|TGE 2017-24|Adaptive Cruise Control (ACC) & Lane Assist|[Upstream](#upstream)| |Mazda|3 2017-18|All|[Dashcam mode](#dashcam)| |Mazda|6 2017-20|All|[Dashcam mode](#dashcam)| |Mazda|CX-5 2017-21|All|[Dashcam mode](#dashcam)| -|Mazda|CX-5 2022-24|All|[Upstream](#upstream)| +|Mazda|CX-5 2022-25|All|[Upstream](#upstream)| |Mazda|CX-9 2016-20|All|[Dashcam mode](#dashcam)| |Mazda|CX-9 2021-23|All|[Upstream](#upstream)| |Nissan|Altima 2019-20|ProPILOT Assist|[Upstream](#upstream)| diff --git a/opendbc/car/docs.py b/opendbc/car/docs.py index 26f4333083..00428f5c81 100755 --- a/opendbc/car/docs.py +++ b/opendbc/car/docs.py @@ -11,7 +11,7 @@ from opendbc.car.common.basedir import BASEDIR from opendbc.car import gen_empty_fingerprint from opendbc.car.structs import CarParams -from opendbc.car.docs_definitions import CarDocs, ExtraCarDocs, Column, ExtraCarsColumn, CommonFootnote, PartType +from opendbc.car.docs_definitions import CarDocs, Device, ExtraCarDocs, Column, ExtraCarsColumn, CommonFootnote, PartType from opendbc.car.car_helpers import interfaces, get_interface_attr from opendbc.car.values import Platform, PLATFORMS from opendbc.car.mock.values import CAR as MOCK @@ -89,7 +89,7 @@ def generate_cars_md(all_car_docs: list[CarDocs], template_fn: str) -> str: footnotes = [fn.value.text for fn in get_all_footnotes()] cars_md: str = template.render(all_car_docs=all_car_docs, PartType=PartType, group_by_make=group_by_make, footnotes=footnotes, - Column=Column) + Device=Device, Column=Column) return cars_md diff --git a/opendbc/car/gm/carstate.py b/opendbc/car/gm/carstate.py index 42cb1c145e..4c517c06bb 100644 --- a/opendbc/car/gm/carstate.py +++ b/opendbc/car/gm/carstate.py @@ -5,7 +5,7 @@ from opendbc.car.common.conversions import Conversions as CV from opendbc.car.common.numpy_fast import mean from opendbc.car.interfaces import CarStateBase -from opendbc.car.gm.values import DBC, AccState, CruiseButtons, STEER_THRESHOLD, SDGM_CAR +from opendbc.car.gm.values import DBC, AccState, CruiseButtons, STEER_THRESHOLD, SDGM_CAR, ALT_ACCS ButtonType = structs.CarState.ButtonEvent.Type TransmissionType = structs.CarParams.TransmissionType @@ -123,14 +123,18 @@ def update(self, can_parsers) -> structs.CarState: ret.cruiseState.enabled = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] != AccState.OFF ret.cruiseState.standstill = pt_cp.vl["AcceleratorPedal2"]["CruiseState"] == AccState.STANDSTILL if self.CP.networkLocation == NetworkLocation.fwdCamera: - ret.cruiseState.speed = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCSpeedSetpoint"] * CV.KPH_TO_MS - # This FCW signal only works for SDGM cars. CAM cars send FCW on GMLAN but this bit is always 0 for them - ret.stockFcw = cam_cp.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"] != 0 + if self.CP.carFingerprint not in ALT_ACCS: + ret.cruiseState.speed = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCSpeedSetpoint"] * CV.KPH_TO_MS + # This FCW signal only works for SDGM cars. CAM cars send FCW on GMLAN but this bit is always 0 for them + ret.stockFcw = cam_cp.vl["ASCMActiveCruiseControlStatus"]["FCWAlert"] != 0 + if self.CP.pcmCruise: + # openpilot controls nonAdaptive when not pcmCruise + ret.cruiseState.nonAdaptive = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCCruiseState"] not in (2, 3) + else: + ret.cruiseState.speed = pt_cp.vl["ECMCruiseControl"]["CruiseSetSpeed"] * CV.KPH_TO_MS + if self.CP.carFingerprint not in SDGM_CAR: ret.stockAeb = cam_cp.vl["AEBCmd"]["AEBCmdActive"] != 0 - # openpilot controls nonAdaptive when not pcmCruise - if self.CP.pcmCruise: - ret.cruiseState.nonAdaptive = cam_cp.vl["ASCMActiveCruiseControlStatus"]["ACCCruiseState"] not in (2, 3) if self.CP.enableBsm: ret.leftBlindspot = pt_cp.vl["BCMBlindSpotMonitor"]["LeftBSM"] == 1 @@ -166,24 +170,26 @@ def get_can_parsers(CP): ("ECMAcceleratorPos", 80), ] + if CP.transmissionType == TransmissionType.direct: + pt_messages.append(("EBCMRegenPaddle", 50)) + if CP.enableBsm: pt_messages.append(("BCMBlindSpotMonitor", 10)) - # Used to read back last counter sent to PT by camera + cam_messages = [] if CP.networkLocation == NetworkLocation.fwdCamera: pt_messages += [ ("ASCMLKASteeringCmd", 0), ] - - if CP.transmissionType == TransmissionType.direct: - pt_messages.append(("EBCMRegenPaddle", 50)) - - cam_messages = [] - if CP.networkLocation == NetworkLocation.fwdCamera: cam_messages += [ ("ASCMLKASteeringCmd", 10), - ("ASCMActiveCruiseControlStatus", 25), ] + + if CP.carFingerprint in ALT_ACCS: + pt_messages.append(("ECMCruiseControl", 10)) + else: + cam_messages.append(("ASCMActiveCruiseControlStatus", 25)) + if CP.carFingerprint not in SDGM_CAR: cam_messages += [ ("AEBCmd", 10), diff --git a/opendbc/car/gm/fingerprints.py b/opendbc/car/gm/fingerprints.py index 9a55b22705..89bde82006 100644 --- a/opendbc/car/gm/fingerprints.py +++ b/opendbc/car/gm/fingerprints.py @@ -66,6 +66,9 @@ CAR.CHEVROLET_TRAVERSE: [{ 190: 6, 193: 8, 197: 8, 199: 4, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 257: 8, 288: 5, 289: 8, 292: 2, 298: 8, 304: 3, 309: 8, 313: 8, 320: 4, 322: 7, 328: 1, 331: 3, 352: 5, 368: 3, 381: 8, 384: 4, 386: 8, 388: 8, 393: 7, 398: 8, 401: 8, 407: 7, 413: 8, 417: 7, 419: 1, 422: 4, 426: 7, 431: 8, 442: 8, 451: 8, 452: 8, 453: 6, 454: 8, 455: 7, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 499: 3, 500: 6, 501: 8, 508: 8, 510: 8, 532: 6, 554: 3, 560: 8, 562: 8, 563: 5, 564: 5, 567: 5, 573: 1, 577: 8, 578: 8, 579: 8, 587: 8, 603: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 647: 6, 707: 8, 715: 8, 717: 5, 723: 4, 730: 4, 753: 5, 761: 7, 840: 5, 842: 5, 844: 8, 866: 4, 869: 4, 880: 6, 961: 8, 969: 8, 975: 2, 977: 8, 979: 8, 985: 5, 1001: 8, 1005: 6, 1009: 8, 1011: 6, 1013: 5, 1017: 8, 1020: 8, 1033: 7, 1034: 7, 1105: 5, 1217: 8, 1221: 5, 1223: 3, 1225: 7, 1233: 8, 1236: 8, 1249: 8, 1257: 6, 1259: 8, 1261: 7, 1263: 4, 1265: 8, 1267: 1, 1268: 2, 1271: 8, 1279: 4, 1280: 4, 1296: 4, 1300: 8, 1322: 6, 1323: 4, 1328: 4, 1345: 8, 1346: 8, 1347: 8, 1355: 8, 1362: 8, 1417: 8, 1512: 8, 1514: 8, 1601: 8, 1602: 8, 1603: 7, 1609: 8, 1611: 8, 1613: 8, 1618: 8, 1649: 8, 1792: 8, 1793: 8, 1798: 8, 1799: 8, 1810: 8, 1813: 8, 1824: 8, 1825: 8, 1840: 8, 1842: 8, 1856: 8, 1858: 8, 1859: 8, 1860: 8, 1862: 8, 1863: 8, 1871: 8, 1872: 8, 1875: 8, 1879: 8, 1882: 8, 1888: 8, 1889: 8, 1892: 8, 1906: 7, 1907: 7, 1912: 7, 1919: 7, 1920: 7, 1927: 8, 1930: 7, 1937: 8, 1953: 8, 1954: 8, 1955: 8, 1968: 8, 1969: 8, 1971: 8, 1975: 8, 1988: 8, 1990: 8, 2000: 8, 2001: 8, 2004: 8, 2016: 8, 2017: 8, 2018: 8, 2019: 8, 2020: 8, 2024: 8, 2026: 8 }], + CAR.GMC_YUKON: [{ + 190: 6, 193: 8, 197: 8, 201: 8, 208: 8, 209: 7, 211: 2, 241: 6, 249: 8, 288: 5, 289: 8, 298: 8, 304: 1, 309: 8, 311: 8, 313: 8, 320: 3, 328: 1, 352: 5, 381: 8, 384: 4, 386: 8, 388: 8, 413: 8, 451: 8, 452: 8, 453: 6, 455: 7, 460: 5, 463: 3, 479: 3, 481: 7, 485: 8, 489: 8, 497: 8, 500: 6, 501: 8, 510: 8, 528: 5, 532: 6, 534: 2, 562: 8, 563: 5, 587: 8, 608: 8, 609: 6, 610: 6, 611: 6, 612: 8, 613: 8, 707: 8, 761: 7, 800: 6, 801: 8, 810: 8, 840: 5, 842: 5, 844: 8, 848: 4, 977: 8, 1001: 8, 1017: 8, 1020: 8, 1217: 8, 1221: 5, 1233: 8, 1249: 8, 1265: 8, 1267: 1, 1280: 4, 1300: 8, 1355: 8, 1611: 8 + }], } FW_VERSIONS: dict[str, dict[tuple, list[bytes]]] = { diff --git a/opendbc/car/gm/interface.py b/opendbc/car/gm/interface.py index f3953c0eb9..04f77187c2 100755 --- a/opendbc/car/gm/interface.py +++ b/opendbc/car/gm/interface.py @@ -7,7 +7,7 @@ from opendbc.car.common.basedir import BASEDIR from opendbc.car.common.conversions import Conversions as CV from opendbc.car.gm.radar_interface import RADAR_HEADER_MSG -from opendbc.car.gm.values import CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, CanBus +from opendbc.car.gm.values import CAR, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, SDGM_CAR, ALT_ACCS, CanBus from opendbc.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD, LatControlInputs, NanoFFModel TransmissionType = structs.CarParams.TransmissionType @@ -113,6 +113,11 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime ret.openpilotLongitudinalControl = True ret.safetyConfigs[0].safetyParam |= Panda.FLAG_GM_HW_CAM_LONG + if candidate in ALT_ACCS: + ret.experimentalLongitudinalAvailable = False + ret.openpilotLongitudinalControl = False + ret.minEnableSpeed = -1. # engage speed is decided by PCM + else: # ASCM, OBD-II harness ret.openpilotLongitudinalControl = True ret.networkLocation = NetworkLocation.gateway @@ -203,4 +208,9 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime ret.steerActuatorDelay = 0.2 CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + elif candidate == CAR.GMC_YUKON: + ret.steerActuatorDelay = 0.5 + CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + ret.dashcamOnly = True # Needs steerRatio, tireStiffness, and lat accel factor tuning + return ret diff --git a/opendbc/car/gm/values.py b/opendbc/car/gm/values.py index 79b583a51a..4d58a27125 100644 --- a/opendbc/car/gm/values.py +++ b/opendbc/car/gm/values.py @@ -175,6 +175,10 @@ class CAR(Platforms): [GMCarDocs("Chevrolet Traverse 2022-23", "RS, Premier, or High Country Trim")], GMCarSpecs(mass=1955, wheelbase=3.07, steerRatio=17.9, centerToFrontRatio=0.4), ) + GMC_YUKON = GMPlatformConfig( + [GMCarDocs("GMC Yukon 2019-20", "Adaptive Cruise Control (ACC) & LKAS")], + GMCarSpecs(mass=2490, wheelbase=2.94, steerRatio=17.3, centerToFrontRatio=0.5, tireStiffnessFactor=1.0), + ) class CruiseButtons: @@ -253,7 +257,10 @@ class CanBus: EV_CAR = {CAR.CHEVROLET_VOLT, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_BOLT_EUV} # We're integrated at the camera with VOACC on these cars (instead of ASCM w/ OBD-II harness) -CAMERA_ACC_CAR = {CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_SILVERADO, CAR.CHEVROLET_EQUINOX, CAR.CHEVROLET_TRAILBLAZER} +CAMERA_ACC_CAR = {CAR.CHEVROLET_BOLT_EUV, CAR.CHEVROLET_SILVERADO, CAR.CHEVROLET_EQUINOX, CAR.CHEVROLET_TRAILBLAZER, CAR.GMC_YUKON} + +# Alt ASCMActiveCruiseControlStatus +ALT_ACCS = {CAR.GMC_YUKON} # We're integrated at the Safety Data Gateway Module on these cars SDGM_CAR = {CAR.CADILLAC_XT4, CAR.CHEVROLET_VOLT_2019, CAR.CHEVROLET_TRAVERSE} diff --git a/opendbc/car/honda/fingerprints.py b/opendbc/car/honda/fingerprints.py index 663bf65107..c95efce0c5 100644 --- a/opendbc/car/honda/fingerprints.py +++ b/opendbc/car/honda/fingerprints.py @@ -800,11 +800,13 @@ (Ecu.srs, 0x18da53f1, None): [ b'77959-3M0-K840\x00\x00', b'77959-3V0-A820\x00\x00', + b'77959-3V0-A910\x00\x00', ], (Ecu.fwdRadar, 0x18dab0f1, None): [ b'8S102-3M6-P030\x00\x00', b'8S102-3W0-A060\x00\x00', b'8S102-3W0-AB10\x00\x00', + b'8S102-3W0-AB20\x00\x00', ], (Ecu.vsa, 0x18da28f1, None): [ b'57114-3M6-M010\x00\x00', @@ -812,10 +814,12 @@ ], (Ecu.transmission, 0x18da1ef1, None): [ b'28101-6EH-A010\x00\x00', + b'28101-6EH-A110\x00\x00', b'28101-6JC-M310\x00\x00', ], (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ b'46114-3W0-A020\x00\x00', + b'46114-3W0-A050\x00\x00', ], }, CAR.ACURA_ILX: { diff --git a/opendbc/car/hyundai/carcontroller.py b/opendbc/car/hyundai/carcontroller.py index 78e71029d0..ee88a399b8 100644 --- a/opendbc/car/hyundai/carcontroller.py +++ b/opendbc/car/hyundai/carcontroller.py @@ -97,7 +97,7 @@ def update(self, CC, CS, now_nanos): # *** common hyundai stuff *** # tester present - w/ no response (keeps relevant ECU disabled) - if self.frame % 100 == 0 and not ((self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) or self.ESCC.enabled) and \ + if self.frame % 100 == 0 and not ((self.CP.flags & HyundaiFlags.CANFD_CAMERA_SCC) or self.ESCC.enabled) and \ self.CP.openpilotLongitudinalControl: # for longitudinal control, either radar or ADAS driving ECU addr, bus = 0x7d0, 0 @@ -157,7 +157,7 @@ def update(self, CC, CS, now_nanos): use_fca = self.CP.flags & HyundaiFlags.USE_FCA.value can_sends.extend(hyundaican.create_acc_commands(self.packer, CC.enabled, accel, jerk, int(self.frame / 2), hud_control, set_speed_in_units, stopping, - CC.cruiseControl.override, use_fca, + CC.cruiseControl.override, use_fca, self.CP, CS.main_cruise_enabled, self.ESCC)) # 20 Hz LFA MFA message @@ -166,7 +166,7 @@ def update(self, CC, CS, now_nanos): # 5 Hz ACC options if self.frame % 20 == 0 and self.CP.openpilotLongitudinalControl: - can_sends.extend(hyundaican.create_acc_opt(self.packer, self.ESCC)) + can_sends.extend(hyundaican.create_acc_opt(self.packer, self.CP, self.ESCC)) # 2 Hz front radar options if self.frame % 50 == 0 and self.CP.openpilotLongitudinalControl and not self.ESCC.enabled: diff --git a/opendbc/car/hyundai/carstate.py b/opendbc/car/hyundai/carstate.py index ef1247fdee..29edc7fccd 100644 --- a/opendbc/car/hyundai/carstate.py +++ b/opendbc/car/hyundai/carstate.py @@ -39,11 +39,13 @@ def __init__(self, CP): "GEAR_SHIFTER" if CP.flags & HyundaiFlags.CANFD: self.shifter_values = can_define.dv[self.gear_msg_canfd]["GEAR"] + elif CP.flags & (HyundaiFlags.HYBRID | HyundaiFlags.EV): + self.shifter_values = can_define.dv["ELECT_GEAR"]["Elect_Gear_Shifter"] elif self.CP.flags & HyundaiFlags.CLUSTER_GEARS: self.shifter_values = can_define.dv["CLU15"]["CF_Clu_Gear"] elif self.CP.flags & HyundaiFlags.TCU_GEARS: self.shifter_values = can_define.dv["TCU12"]["CUR_GR"] - else: # preferred and elect gear methods use same definition + else: self.shifter_values = can_define.dv["LVR12"]["CF_Lvr_Gear"] self.accelerator_msg_canfd = "ACCELERATOR" if CP.flags & HyundaiFlags.EV else \ @@ -158,7 +160,7 @@ def update(self, can_parsers) -> structs.CarState: ret.gearShifter = self.parse_gear_shifter(self.shifter_values.get(gear)) - if not self.CP.openpilotLongitudinalControl: + if not self.CP.openpilotLongitudinalControl or self.CP.flags & HyundaiFlags.CAMERA_SCC: aeb_src = "FCA11" if self.CP.flags & HyundaiFlags.USE_FCA.value else "SCC12" aeb_sig = "FCA_CmdAct" if self.CP.flags & HyundaiFlags.USE_FCA.value else "AEB_CmdAct" aeb_warning = cp_cruise.vl[aeb_src]["CF_VSM_Warn"] != 0 @@ -389,7 +391,7 @@ def get_can_parsers(self, CP): ("LKAS11", 100) ] - if not CP.openpilotLongitudinalControl and CP.flags & HyundaiFlags.CAMERA_SCC: + if CP.flags & HyundaiFlags.CAMERA_SCC: cam_messages += [ ("SCC11", 50), ("SCC12", 50), diff --git a/opendbc/car/hyundai/fingerprints.py b/opendbc/car/hyundai/fingerprints.py index 256441f70c..9a56dba4d2 100644 --- a/opendbc/car/hyundai/fingerprints.py +++ b/opendbc/car/hyundai/fingerprints.py @@ -576,6 +576,7 @@ (Ecu.eps, 0x7d4, None): [ b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3110 4DLAC101', b'\xf1\x00DL3 MDPS C 1.00 1.01 56310-L3220 4DLAC101', + b'\xf1\x00DL3 MDPS C 1.00 1.01 56310L3220\x00 4DLAC101', b'\xf1\x00DL3 MDPS C 1.00 1.02 56310-L2220 4DLDC102', b'\xf1\x00DL3 MDPS C 1.00 1.02 56310L3220\x00 4DLAC102', b'\xf1\x00DL3 MDPS R 1.00 1.02 57700-L3000 4DLAP102', @@ -1005,12 +1006,14 @@ CAR.HYUNDAI_IONIQ_6: { (Ecu.fwdRadar, 0x7d0, None): [ b'\xf1\x00CE__ RDR ----- 1.00 1.01 99110-KL000 ', + b'\xf1\x00CE__ RDR ----- 1.00 1.02 99110-KL000 ', ], (Ecu.fwdCamera, 0x7c4, None): [ b'\xf1\x00CE MFC AT CAN LHD 1.00 1.04 99211-KL000 221213', b'\xf1\x00CE MFC AT EUR LHD 1.00 1.03 99211-KL000 221011', b'\xf1\x00CE MFC AT EUR LHD 1.00 1.04 99211-KL000 221213', b'\xf1\x00CE MFC AT USA LHD 1.00 1.04 99211-KL000 221213', + b'\xf1\x00CE MFC AT USA LHD 1.00 1.06 99211-KL000 230915', ], }, CAR.HYUNDAI_TUCSON_4TH_GEN: { diff --git a/opendbc/car/hyundai/hyundaican.py b/opendbc/car/hyundai/hyundaican.py index befa4755c9..f5a48ac424 100644 --- a/opendbc/car/hyundai/hyundaican.py +++ b/opendbc/car/hyundai/hyundaican.py @@ -126,8 +126,9 @@ def create_lfahda_mfc(packer, enabled, lfa_icon): } return packer.make_can_msg("LFAHDA_MFC", 0, values) -def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, +def create_acc_commands(packer, enabled, accel, upper_jerk, idx, hud_control, set_speed, stopping, long_override, use_fca, CP, main_cruise_enabled, ESCC: EnhancedSmartCruiseControl = None): + commands = [] def get_scc11_values(): return { @@ -203,9 +204,10 @@ def calculate_fca11_checksum(values): scc14_values = get_scc14_values() commands.append(packer.make_can_msg("SCC14", 0, scc14_values)) - # Only send FCA11 on cars where it exists on the bus, and - # if we don't use ESCC since ESCC does not block FCA11 from stock radar - if use_fca and not (ESCC and ESCC.enabled): + # Only send FCA11 on cars where it exists on the bus + # On Camera SCC cars, FCA11 is not disabled, so we forward stock FCA11 back to the car forward hooks + # If we don't use ESCC since ESCC does not block FCA11 from stock radar + if use_fca and not ((CP.flags & HyundaiFlags.CAMERA_SCC) or (ESCC and ESCC.enabled)): # note that some vehicles most likely have an alternate checksum/counter definition # https://github.com/commaai/opendbc/commit/9ddcdb22c4929baf310295e832668e6e7fcfa602 fca11_values = get_fca11_values() @@ -214,7 +216,7 @@ def calculate_fca11_checksum(values): return commands -def create_acc_opt(packer, ESCC: EnhancedSmartCruiseControl = None): +def create_acc_opt(packer, CP, ESCC: EnhancedSmartCruiseControl = None): """ Creates SCC13 and FCA12. If ESCC is enabled, it will only create SCC13 since ESCC does not block FCA12. :param packer: @@ -245,8 +247,10 @@ def get_fca12_values(): return commands # TODO: this needs to be detected and conditionally sent on unsupported long cars - fca12_values = get_fca12_values() - commands.append(packer.make_can_msg("FCA12", 0, fca12_values)) + # On Camera SCC cars, FCA12 is not disabled, so we forward stock FCA12 back to the car forward hooks + if not (CP.flags & HyundaiFlags.CAMERA_SCC): + fca12_values = get_fca12_values() + commands.append(packer.make_can_msg("FCA12", 0, fca12_values)) return commands diff --git a/opendbc/car/hyundai/interface.py b/opendbc/car/hyundai/interface.py index 9419990e59..3ebbcdddec 100644 --- a/opendbc/car/hyundai/interface.py +++ b/opendbc/car/hyundai/interface.py @@ -1,7 +1,7 @@ from panda import Panda from opendbc.car import Bus, get_safety_config, structs from opendbc.car.hyundai.hyundaicanfd import CanBus -from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CAMERA_SCC_CAR, CANFD_RADAR_SCC_CAR, \ +from opendbc.car.hyundai.values import HyundaiFlags, CAR, DBC, CANFD_RADAR_SCC_CAR, \ CANFD_UNSUPPORTED_LONGITUDINAL_CAR, \ UNSUPPORTED_LONGITUDINAL_CAR from opendbc.car.hyundai.radar_interface import RADAR_START_ADDR @@ -71,7 +71,7 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime else: # Shared configuration for non CAN-FD cars - ret.experimentalLongitudinalAvailable = candidate not in (UNSUPPORTED_LONGITUDINAL_CAR | CAMERA_SCC_CAR) + ret.experimentalLongitudinalAvailable = candidate not in UNSUPPORTED_LONGITUDINAL_CAR ret.enableBsm = 0x58b in fingerprint[0] # Send LFA message on cars with HDA @@ -142,7 +142,7 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime @staticmethod def init(CP, can_recv, can_send): - if CP.openpilotLongitudinalControl and not ((CP.flags & HyundaiFlags.CANFD_CAMERA_SCC.value) or + if CP.openpilotLongitudinalControl and not ((CP.flags & (HyundaiFlags.CANFD_CAMERA_SCC | HyundaiFlags.CAMERA_SCC)) or (CP.sunnypilotFlags & HyundaiFlagsSP.ENHANCED_SCC.value)): addr, bus = 0x7d0, 0 if CP.flags & HyundaiFlags.CANFD_HDA2.value: diff --git a/opendbc/car/tests/routes.py b/opendbc/car/tests/routes.py index 2e1eca29a0..4430bfef88 100644 --- a/opendbc/car/tests/routes.py +++ b/opendbc/car/tests/routes.py @@ -76,6 +76,7 @@ class CarTestRoute(NamedTuple): CarTestRoute("162796f1469f2f1b/00000005--6f334eda14", GM.CADILLAC_XT4), CarTestRoute("477dd485611d1e6e/00000009--85fc06e10a", GM.CHEVROLET_VOLT_2019), CarTestRoute("a40976dc9f28ba62/0000001f--160e210119", GM.CHEVROLET_TRAVERSE), + CarTestRoute("36c62b5da6f08154/00000052--983c17c5b2", GM.GMC_YUKON), CarTestRoute("0e7a2ba168465df5|2020-10-18--14-14-22", HONDA.ACURA_RDX_3G), CarTestRoute("a74b011b32b51b56|2020-07-26--17-09-36", HONDA.HONDA_CIVIC), diff --git a/opendbc/car/torque_data/override.toml b/opendbc/car/torque_data/override.toml index aad06e8e3e..f4bcea748a 100644 --- a/opendbc/car/torque_data/override.toml +++ b/opendbc/car/torque_data/override.toml @@ -54,6 +54,7 @@ legend = ["LAT_ACCEL_FACTOR", "MAX_LAT_ACCEL_MEASURED", "FRICTION"] "KIA_SPORTAGE_5TH_GEN" = [2.6, 2.6, 0.1] "GENESIS_GV70_1ST_GEN" = [2.42, 2.42, 0.1] "GENESIS_GV60_EV_1ST_GEN" = [2.5, 2.5, 0.1] +"GMC_YUKON" = [1.2, 2.5, 0.26] "KIA_SORENTO_4TH_GEN" = [2.5, 2.5, 0.1] "KIA_SORENTO_HEV_4TH_GEN" = [2.5, 2.5, 0.1] "KIA_NIRO_HEV_2ND_GEN" = [2.42, 2.5, 0.12] diff --git a/opendbc/car/toyota/interface.py b/opendbc/car/toyota/interface.py index 4707a580ad..4a038a54fc 100644 --- a/opendbc/car/toyota/interface.py +++ b/opendbc/car/toyota/interface.py @@ -50,10 +50,6 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime if Ecu.hybrid in found_ecus: ret.flags |= ToyotaFlags.HYBRID.value - # TODO: expand to the rest of the cars - if candidate in (CAR.LEXUS_ES_TSS2,) and not (ret.flags & ToyotaFlags.HYBRID.value): - ret.flags |= ToyotaFlags.RAISED_ACCEL_LIMIT.value - if candidate == CAR.TOYOTA_PRIUS: stop_and_go = True # Only give steer angle deadzone to for bad angle sensor prius @@ -138,6 +134,8 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, experime ret.minEnableSpeed = -1. if stop_and_go else MIN_ACC_SPEED if candidate in TSS2_CAR: + ret.flags |= ToyotaFlags.RAISED_ACCEL_LIMIT.value + ret.vEgoStopping = 0.25 ret.vEgoStarting = 0.25 ret.stoppingDecelRate = 0.3 # reach stopping target smoothly diff --git a/opendbc/car/volkswagen/fingerprints.py b/opendbc/car/volkswagen/fingerprints.py index 78cda7aab6..83dd2dcbb4 100644 --- a/opendbc/car/volkswagen/fingerprints.py +++ b/opendbc/car/volkswagen/fingerprints.py @@ -9,6 +9,7 @@ FW_VERSIONS = { CAR.VOLKSWAGEN_ARTEON_MK1: { (Ecu.engine, 0x7e0, None): [ + b'\xf1\x8704L906026TM\xf1\x896847', b'\xf1\x873G0906259AH\xf1\x890001', b'\xf1\x873G0906259F \xf1\x890004', b'\xf1\x873G0906259G \xf1\x890004', @@ -27,10 +28,12 @@ b'\xf1\x870GC300014M \xf1\x892802', b'\xf1\x870GC300019G \xf1\x892804', b'\xf1\x870GC300040P \xf1\x891401', + b'\xf1\x870GC300043 \xf1\x892303', ], (Ecu.srs, 0x715, None): [ b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1616001613121157161111572900', b'\xf1\x873Q0959655BK\xf1\x890703\xf1\x82\x0e1616001613121177161113772900', + b'\xf1\x873Q0959655BK\xf1\x890712\xf1\x82\x0e1616001613121157161111572C00', b'\xf1\x873Q0959655CK\xf1\x890711\xf1\x82\x0e1712141712141105121122052900', b'\xf1\x873Q0959655CR\xf1\x890720\xf1\x82\x0e1616001613121105161111052900', b'\xf1\x873Q0959655DA\xf1\x890720\xf1\x82\x0e1712141712141105121122052900', @@ -50,6 +53,7 @@ b'\xf1\x872Q0907572AA\xf1\x890396', b'\xf1\x872Q0907572T \xf1\x890383', b'\xf1\x875Q0907572J \xf1\x890654', + b'\xf1\x875Q0907572P \xf1\x890682', b'\xf1\x875Q0907572R \xf1\x890771', ], }, diff --git a/opendbc/dbc/generator/test_generator.py b/opendbc/dbc/generator/test_generator.py deleted file mode 100755 index 1cfc70128b..0000000000 --- a/opendbc/dbc/generator/test_generator.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env python3 -import os -import filecmp -import tempfile -from opendbc.dbc.generator.generator import create_all, opendbc_root - - -def test_generator(): - with tempfile.TemporaryDirectory() as d: - create_all(d) - - ignore = [f for f in os.listdir(opendbc_root) if not f.endswith('_generated.dbc')] - comp = filecmp.dircmp(opendbc_root, d, ignore=ignore) - - err = "Generated DBC mismatch\n\n" - err += f"Different files: {comp.diff_files}\n\n" - err += "Run opendbc/dbc/generator/generator.py to regenerate DBC files." - assert len(comp.diff_files) == 0, err - - -if __name__ == "__main__": - test_generator() diff --git a/opendbc/dbc/hyundai_kia_generic.dbc b/opendbc/dbc/hyundai_kia_generic.dbc index 5cbd33616b..5bb4d36029 100644 --- a/opendbc/dbc/hyundai_kia_generic.dbc +++ b/opendbc/dbc/hyundai_kia_generic.dbc @@ -112,7 +112,7 @@ BO_ 1265 CLU11: 4 CLU BO_ 1260 Sign_Detection: 8 XXX SG_ SpeedLim_Nav_Cam : 40|8@1+ (1,0) [0|255] "km/h / mph" XXX SG_ SpeedLim_Nav_Cam2 : 48|8@1+ (1,0) [0|255] "km/h / mph" XXX - + BO_ 1492 TMU_GW_PE_01: 8 CLU SG_ TMU_IVRActivity : 0|2@1+ (1.0,0.0) [0.0|3.0] "" DATC SG_ TMU_PhoneActivity : 2|2@1+ (1.0,0.0) [0.0|3.0] "" DATC @@ -1676,7 +1676,7 @@ VAL_ 274 CUR_GR 1 "D" 2 "D" 3 "D" 4 "D" 5 "D" 6 "D" 7 "D" 8 "D" 14 "R" 0 "P"; VAL_ 512 HYDROGEN_GEAR_SHIFTER 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; VAL_ 871 CF_Lvr_IsgState 0 "enabled" 1 "activated" 2 "unknown" 3 "disabled"; VAL_ 871 CF_Lvr_Gear 12 "T" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; -VAL_ 882 Elect_Gear_Shifter 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; +VAL_ 882 Elect_Gear_Shifter 4 "S" 5 "D" 8 "S" 6 "N" 7 "R" 0 "P"; VAL_ 905 ACCMode 0 "off" 1 "enabled" 2 "driver_override" 3 "off_maybe_fault" 4 "cancelled"; VAL_ 909 CF_VSM_Warn 2 "FCW" 3 "AEB"; VAL_ 916 ACCEnable 0 "SCC ready" 1 "SCC temp fault" 2 "SCC permanent fault" 3 "SCC permanent fault, communication issue"; diff --git a/pyproject.toml b/pyproject.toml index 8b692e584c..452ed2de3d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,7 +85,7 @@ select = [ "E", "F", "W", "PIE", "C4", "ISC", "A", "B", "NPY", # numpy "UP", # pyupgrade - "TRY302", "TRY400", "TRY401", # try/excepts + "TRY203", "TRY400", "TRY401", # try/excepts "RUF008", "RUF100", "TID251", "PLR1704", @@ -99,6 +99,7 @@ ignore = [ "ISC003", "B027", "B024", + "UP031", "NPY002", # new numpy random syntax is worse ] flake8-implicit-str-concat.allow-multiline=false diff --git a/test.sh b/test.sh index 6b6265b16d..3b2b847e6b 100755 --- a/test.sh +++ b/test.sh @@ -4,15 +4,30 @@ set -e DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" >/dev/null && pwd)" cd $DIR -# ensure we're up to date +# TODO: why doesn't uv do this? +export PYTHONPATH=$DIR + +# *** dependencies install *** +if ! command -v uv &>/dev/null; then + echo "'uv' is not installed. Installing 'uv'..." + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + uv sync --all-extras source .venv/bin/activate +# *** build *** uv run scons -j8 -uv run pre-commit run --all-files +# *** lint *** +# TODO: pre-commit is slow; replace it with openpilot's "op lint" +#uv run pre-commit run --all-files +uv run ruff check . + +# *** test *** uv run pytest -n8 +# *** all done *** GREEN='\033[0;32m' NC='\033[0m' printf "\n${GREEN}All good!${NC} Finished build, lint, and test in ${SECONDS}s\n"