From c541313f2aa8e16fa635a2c7ce63c77d08871320 Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Sun, 4 Oct 2026 05:50:29 -0500 Subject: [PATCH] Honda Modified EPS --- .../opendbc/car/honda/carcontroller.py | 8 +- .../opendbc/car/honda/fingerprints.py | 5 + opendbc_repo/opendbc/car/honda/interface.py | 21 ++- .../car/honda/modified_civic_steering.py | 87 +++++++++++ .../car/honda/tests/test_modified_eps.py | 137 ++++++++++++++++++ .../tests/test_modified_eps_controller.py | 47 ++++++ .../car/honda/tests/test_startup_profiles.py | 30 +++- opendbc_repo/opendbc/car/honda/values.py | 18 +++ 8 files changed, 338 insertions(+), 15 deletions(-) create mode 100644 opendbc_repo/opendbc/car/honda/modified_civic_steering.py create mode 100644 opendbc_repo/opendbc/car/honda/tests/test_modified_eps.py create mode 100644 opendbc_repo/opendbc/car/honda/tests/test_modified_eps_controller.py diff --git a/opendbc_repo/opendbc/car/honda/carcontroller.py b/opendbc_repo/opendbc/car/honda/carcontroller.py index 09a1681174..c532716f79 100644 --- a/opendbc_repo/opendbc/car/honda/carcontroller.py +++ b/opendbc_repo/opendbc/car/honda/carcontroller.py @@ -3,6 +3,7 @@ import numpy as np from opendbc.can import CANPacker from opendbc.car import Bus, DT_CTRL, rate_limit, make_tester_present_msg, structs from opendbc.car.honda import hondacan +from opendbc.car.honda.modified_civic_steering import ModifiedCivicSteering from opendbc.car.honda.bosch_longitudinal import BoschLongitudinal, qualified as bosch_long_qualified from opendbc.car.honda.values import CAR, CruiseButtons, HondaFlags, CarControllerParams from opendbc.car.interfaces import CarControllerBase @@ -97,6 +98,8 @@ class CarController(CarControllerBase): self.bosch_longitudinal = BoschLongitudinal(CP, self.params) if bosch_long_qualified(CP) else None self.bosch_learning_params = None self.tja_control = bool(CP.flags & HondaFlags.BOSCH_TJA_CONTROL) + self.modified_civic_steering = (ModifiedCivicSteering() if CP.carFingerprint == CAR.HONDA_CIVIC_BOSCH and + CP.flags & HondaFlags.EPS_MODIFIED and not CP.passive and not CP.dashcamOnly and not CP.notCar else None) self.braking = False self.brake_steady = 0. @@ -127,7 +130,8 @@ class CarController(CarControllerBase): gas, brake = 0.0, 0.0 # *** rate limit steer *** - limited_torque = rate_limit(actuators.torque, self.last_torque, -self.params.STEER_DELTA_DOWN * DT_CTRL, + torque_cmd = self.modified_civic_steering.update(CC, CS) if self.modified_civic_steering is not None else actuators.torque + limited_torque = rate_limit(torque_cmd, self.last_torque, -self.params.STEER_DELTA_DOWN * DT_CTRL, self.params.STEER_DELTA_UP * DT_CTRL) self.last_torque = limited_torque @@ -145,7 +149,7 @@ class CarController(CarControllerBase): # steer torque is converted back to CAN reference (positive when steering right) # Preserve integer CAN rounding while steering limits are owned by the platform. apply_torque = int(np.interp(-limited_torque * self.params.STEER_MAX, - self.params.STEER_LOOKUP, self.params.STEER_LOOKUP)) + self.params.STEER_LOOKUP, self.params.STEER_LOOKUP_V)) # Send CAN commands can_sends = [] diff --git a/opendbc_repo/opendbc/car/honda/fingerprints.py b/opendbc_repo/opendbc/car/honda/fingerprints.py index 9a06621511..ff09519d1e 100644 --- a/opendbc_repo/opendbc/car/honda/fingerprints.py +++ b/opendbc_repo/opendbc/car/honda/fingerprints.py @@ -92,6 +92,7 @@ FW_VERSIONS = { b'39990-TVA-X040\x00\x00', b'39990-TVE-H130\x00\x00', b'39990-TWB-H120\x00\x00', + b'39990-TVA,A150\x00\x00', ], (Ecu.srs, 0x18da53f1, None): [ b'77959-TBX-H230\x00\x00', @@ -168,6 +169,7 @@ FW_VERSIONS = { b'39990-TBG-A030\x00\x00', b'39990-TEA-T020\x00\x00', b'39990-TEG-A010\x00\x00', + b'39990-TBA,A030\x00\x00', ], (Ecu.srs, 0x18da53f1, None): [ b'77959-TBA-A030\x00\x00', @@ -247,6 +249,8 @@ FW_VERSIONS = { b'39990-TGH-J530\x00\x00', b'39990-TGL-E130\x00\x00', b'39990-TGN-E120\x00\x00', + b'39990-TGG,A020\x00\x00', + b'39990-TGG,A120\x00\x00', ], (Ecu.srs, 0x18da53f1, None): [ b'77959-TBA-A060\x00\x00', @@ -385,6 +389,7 @@ FW_VERSIONS = { b'39990-TME-T030\x00\x00', b'39990-TME-T120\x00\x00', b'39990-TMT-T010\x00\x00', + b'39990-TLA,A040\x00\x00', ], (Ecu.electricBrakeBooster, 0x18da2bf1, None): [ b'46114-TLA-A040\x00\x00', diff --git a/opendbc_repo/opendbc/car/honda/interface.py b/opendbc_repo/opendbc/car/honda/interface.py index 9f683eca5a..242dde5731 100755 --- a/opendbc_repo/opendbc/car/honda/interface.py +++ b/opendbc_repo/opendbc/car/honda/interface.py @@ -4,7 +4,7 @@ from opendbc.car import get_safety_config, structs, uds from opendbc.car.common.conversions import Conversions as CV from opendbc.car.disable_ecu import disable_ecu from opendbc.car.honda.hondacan import CanBus -from opendbc.car.honda.values import CarControllerParams, HondaFlags, CAR, HondaSafetyFlags, MANUAL_TRANS_CARS +from opendbc.car.honda.values import CarControllerParams, HondaFlags, CAR, HondaSafetyFlags, MANUAL_TRANS_CARS, MODIFIED_EPS_FW from opendbc.car.honda.carcontroller import CarController from opendbc.car.honda.carstate import CarState from opendbc.car.honda.radar_interface import RadarInterface @@ -90,13 +90,18 @@ class CarInterface(CarInterfaceBase): ret.longitudinalTuning.kiBP = [0., 5., 35.] ret.longitudinalTuning.kiV = [1.2, 0.8, 0.5] - # Disable control if EPS mod detected - for fw in car_fw: - if fw.ecu == "eps" and b"," in fw.fwVersion: - ret.dashcamOnly = True + eps_observations = [fw for fw in car_fw if fw.ecu == "eps"] + modified_eps = any(b"," in fw.fwVersion for fw in eps_observations) + eps_modified = bool(modified_eps) and all( + fw.address == 0x18DA30F1 and fw.subAddress == 0 and + fw.fwVersion in MODIFIED_EPS_FW.get(candidate, ()) for fw in eps_observations) + if eps_modified: + ret.flags |= HondaFlags.EPS_MODIFIED.value + elif modified_eps: + ret.dashcamOnly = True if candidate == CAR.HONDA_CIVIC: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[1.1], [0.33]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = ([[0.3], [0.1]] if eps_modified else [[1.1], [0.33]]) elif candidate in (CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_BOSCH_DIESEL): ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] @@ -106,7 +111,7 @@ class CarInterface(CarInterfaceBase): ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kiV = [[0, 10], [0.0125, 0.125]] elif candidate == CAR.HONDA_ACCORD: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = ([[0.3], [0.09]] if eps_modified else [[0.6], [0.18]]) elif candidate == CAR.ACURA_ILX: ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] @@ -116,7 +121,7 @@ class CarInterface(CarInterfaceBase): ret.wheelSpeedFactor = 1.025 elif candidate == CAR.HONDA_CRV_5G: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]] + ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = ([[0.21], [0.07]] if eps_modified else [[0.64], [0.192]]) ret.wheelSpeedFactor = 1.025 elif candidate == CAR.HONDA_CRV_HYBRID: diff --git a/opendbc_repo/opendbc/car/honda/modified_civic_steering.py b/opendbc_repo/opendbc/car/honda/modified_civic_steering.py new file mode 100644 index 0000000000..fa524e902c --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/modified_civic_steering.py @@ -0,0 +1,87 @@ +from opendbc.car import DT_CTRL + + +def get_civic_bosch_modified_torque_lpf_tau(torque_cmd: float, prev_torque_cmd: float, v_ego: float) -> float: + torque_delta = abs(float(torque_cmd) - float(prev_torque_cmd)) + torque_cmd_abs = abs(float(torque_cmd)) + sign_change = float(torque_cmd) * float(prev_torque_cmd) < 0.0 + highway = v_ego > 50.0 * 0.44704 + low_speed = v_ego < 30.0 * 0.44704 + if highway: + if torque_cmd_abs < 0.12: + return 0.18 if sign_change else 0.16 + if sign_change and torque_delta > 0.15: + return 0.1 + return 0.12 + if sign_change and torque_cmd_abs < 0.25: + return 0.28 if low_speed else 0.22 + if torque_cmd_abs < 0.12: + return 0.28 if low_speed else 0.2 + if low_speed: + if torque_delta > 0.5: + return 0.14 + elif torque_delta > 0.2: + return 0.16 + elif torque_delta > 0.05: + return 0.18 + else: + return 0.22 + if torque_delta > 0.5: + return 0.12 + elif torque_delta > 0.2: + return 0.13 + elif torque_delta > 0.05: + return 0.15 + else: + return 0.18 + +def get_civic_bosch_modified_steering_pressed(raw_pressed: bool, steering_torque: float, torque_cmd: float, + filter_s: float, was_pressed: bool) -> tuple[float, bool]: + torque_product = steering_torque * torque_cmd + torque_cmd_abs = abs(torque_cmd) + if raw_pressed: + if torque_product < 0.0: + trigger_s = 0.08 if was_pressed else 0.1 + rise_rate = 1.0 + elif torque_cmd_abs < 0.1: + trigger_s = 0.2 if was_pressed else 0.24 + rise_rate = 0.75 + else: + trigger_s = 0.7 if was_pressed else 0.8 + rise_rate = 0.5 + filter_s = min(1.0, filter_s + rise_rate * DT_CTRL) + steering_pressed = filter_s >= trigger_s + else: + filter_s = max(0.0, filter_s - 8.0 * DT_CTRL) + steering_pressed = filter_s > 0.04 and was_pressed + return (filter_s, steering_pressed) + + +class ModifiedCivicSteering: + def __init__(self): + self.reset() + + def reset(self): + self.torque_lpf = 0.0 + self.prev_torque_cmd = 0.0 + self.steering_pressed_filter_s = 0.0 + self.steering_pressed_robust_prev = False + + def update(self, CC, CS): + torque_cmd = float(CC.actuators.torque) + if not CC.latActive: + self.reset() + return torque_cmd + self.steering_pressed_filter_s, pressed = get_civic_bosch_modified_steering_pressed( + bool(CS.out.steeringPressed), float(CS.out.steeringTorque), torque_cmd, + self.steering_pressed_filter_s, self.steering_pressed_robust_prev) + self.steering_pressed_robust_prev = pressed + if pressed: + self.torque_lpf = 0.0 + self.prev_torque_cmd = 0.0 + return 0.0 + tau = get_civic_bosch_modified_torque_lpf_tau(torque_cmd, self.prev_torque_cmd, CS.out.vEgo) + alpha = DT_CTRL / (tau + DT_CTRL) + self.torque_lpf = alpha * torque_cmd + (1.0 - alpha) * self.torque_lpf + self.prev_torque_cmd = torque_cmd + return self.torque_lpf diff --git a/opendbc_repo/opendbc/car/honda/tests/test_modified_eps.py b/opendbc_repo/opendbc/car/honda/tests/test_modified_eps.py new file mode 100644 index 0000000000..a4fc42ef39 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/tests/test_modified_eps.py @@ -0,0 +1,137 @@ +import pytest + +from opendbc.car import gen_empty_fingerprint, structs +from opendbc.car.fw_versions import match_fw_to_car +from opendbc.car.honda.hondacan import CanBus +from opendbc.car.honda.interface import CarInterface +from opendbc.car.honda.values import CAR, CarControllerParams, HondaFlags, MODIFIED_EPS_FW + +Ecu = structs.CarParams.Ecu +SOURCE_BASELINES = { + CAR.HONDA_CIVIC: { + (Ecu.transmission, 416947953, None): b'28101-5CG-A040\x00\x00', + (Ecu.vsa, 416950513, None): b'57114-TBA-A540\x00\x00', + (Ecu.eps, 416952561, None): b'39990-TBA,A030\x00\x00', + (Ecu.srs, 416961521, None): b'77959-TBA-A030\x00\x00', + (Ecu.fwdRadar, 416985329, None): b'36161-TBA-A020\x00\x00', + (Ecu.gateway, 417001457, None): b'38897-TBA-A010\x00\x00', + }, + CAR.HONDA_ACCORD: { + (Ecu.shiftByWire, 416943089, None): b'54008-TVC-A910\x00\x00', + (Ecu.transmission, 416947953, None): b'28101-6A7-A220\x00\x00', + (Ecu.electricBrakeBooster, 416951281, None): b'46114-TVA-A050\x00\x00', + (Ecu.vsa, 416950513, None): b'57114-TVA-B040\x00\x00', + (Ecu.eps, 416952561, None): b'39990-TBX-H120\x00\x00', + (Ecu.srs, 416961521, None): b'77959-TBX-H230\x00\x00', + (Ecu.hud, 416965105, None): b'78209-TVA-A010\x00\x00', + (Ecu.fwdRadar, 416985329, None): b'36802-TBX-H140\x00\x00', + (Ecu.fwdCamera, 416986609, None): b'36161-TBX-H130\x00\x00', + (Ecu.gateway, 417001457, None): b'38897-TVA-A010\x00\x00', + }, + CAR.HONDA_CIVIC_BOSCH: { + (Ecu.transmission, 416947953, None): b'28101-5CG-A920\x00\x00', + (Ecu.vsa, 416950513, None): b'57114-TBG-A330\x00\x00', + (Ecu.eps, 416952561, None): b'39990-TBA-C120\x00\x00', + (Ecu.srs, 416961521, None): b'77959-TBA-A060\x00\x00', + (Ecu.fwdRadar, 416985329, None): b'36802-TBA-A150\x00\x00', + (Ecu.fwdCamera, 416986609, None): b'36161-TBA-A130\x00\x00', + (Ecu.gateway, 417001457, None): b'38897-TBA-A020\x00\x00', + (Ecu.electricBrakeBooster, 416951281, None): b'39494-TGL-G030\x00\x00', + }, + CAR.HONDA_CRV_5G: { + (Ecu.transmission, 416947953, None): b'28101-5RG-A020\x00\x00', + (Ecu.vsa, 416950513, None): b'57114-TLA-A040\x00\x00', + (Ecu.eps, 416952561, None): b'39990-TLA,A040\x00\x00', + (Ecu.electricBrakeBooster, 416951281, None): b'46114-TLA-A040\x00\x00', + (Ecu.gateway, 417001457, None): b'38897-TLA-A010\x00\x00', + (Ecu.fwdRadar, 416985329, None): b'36802-TLA-A040\x00\x00', + (Ecu.fwdCamera, 416986609, None): b'36161-TLA-A060\x00\x00', + (Ecu.srs, 416961521, None): b'77959-TLA-A240\x00\x00', + }, +} + +KNOWN_CASES = ( + (CAR.HONDA_CIVIC, b'39990-TBA,A030\x00\x00'), + (CAR.HONDA_ACCORD, b'39990-TVA,A150\x00\x00'), + (CAR.HONDA_CIVIC_BOSCH, b'39990-TGG,A020\x00\x00'), + (CAR.HONDA_CIVIC_BOSCH, b'39990-TGG,A120\x00\x00'), + (CAR.HONDA_CRV_5G, b'39990-TLA,A040\x00\x00'), +) + + +def params(candidate, firmware): + fingerprint = gen_empty_fingerprint() + initial = CarInterface.get_params(candidate, fingerprint, [], False, False, False) + fingerprint[CanBus(initial).pt][0x1A3] = 8 + return CarInterface.get_params(candidate, fingerprint, firmware, False, False, False) + + +def eps(version, address=0x18DA30F1, sub=0): + return structs.CarParams.CarFw(ecu=Ecu.eps, address=address, subAddress=sub, fwVersion=version, brand="honda") + + +@pytest.mark.parametrize("candidate,version", KNOWN_CASES) +def test_exact_modified_eps_full_cohort_joint_matcher_and_final_cp(candidate, version): + cohort = dict(SOURCE_BASELINES[candidate]) + cohort[(Ecu.eps, 0x18DA30F1, None)] = version + firmware = [ + structs.CarParams.CarFw(ecu=ecu, address=address, subAddress=0 if sub is None else sub, fwVersion=value, brand="honda") + for (ecu, address, sub), value in cohort.items() + ] + for allow_exact in (True, False): + assert match_fw_to_car(firmware, "", allow_exact=allow_exact, log=False)[1] == {candidate} + stock = params(candidate, []) + cp = params(candidate, firmware) + assert cp.flags & HondaFlags.EPS_MODIFIED + assert not cp.dashcamOnly + assert [(config.safetyModel.raw, config.safetyParam) for config in cp.safetyConfigs] == [ + (config.safetyModel.raw, config.safetyParam) for config in stock.safetyConfigs + ] + assert cp.openpilotLongitudinalControl == stock.openpilotLongitudinalControl + assert cp.pcmCruise == stock.pcmCruise + expected = { + CAR.HONDA_CIVIC: (0.3, 0.1), + CAR.HONDA_ACCORD: (0.3, 0.09), + CAR.HONDA_CIVIC_BOSCH: (0.8, 0.24), + CAR.HONDA_CRV_5G: (0.21, 0.07), + }[candidate] + assert list(cp.lateralTuning.pid.kpV) == pytest.approx([expected[0]]) + assert list(cp.lateralTuning.pid.kiV) == pytest.approx([expected[1]]) + lookup = CarControllerParams(cp) + if candidate == CAR.HONDA_CIVIC: + assert lookup.STEER_MAX == 8000 + assert lookup.STEER_LOOKUP == [-8000, -2560, 0, 2560, 8000] + assert lookup.STEER_LOOKUP_V == [-3840, -2560, 0, 2560, 3840] + elif candidate == CAR.HONDA_CRV_5G: + assert lookup.STEER_MAX == 10000 + assert lookup.STEER_LOOKUP == [-10000, -2560, 0, 2560, 10000] + assert lookup.STEER_LOOKUP_V == [-3840, -2560, 0, 2560, 3840] + else: + assert lookup.STEER_LOOKUP_V == lookup.STEER_LOOKUP + + +@pytest.mark.parametrize("candidate,version", KNOWN_CASES) +@pytest.mark.parametrize("case", ("unknown", "wrong-identity", "wrong-address", "wrong-subaddress", "mixed", "mixed-stock")) +def test_unrecognized_or_inconsistent_modified_eps_remains_dashcam(candidate, version, case): + actual_candidate = CAR.HONDA_CRV_HYBRID if case == "wrong-identity" else candidate + value = b"39990-UNKNOWN,0000\x00\x00" if case == "unknown" else version + firmware = [eps(value, 0x18DA31F1 if case == "wrong-address" else 0x18DA30F1, 1 if case == "wrong-subaddress" else 0)] + if case == "mixed": + firmware.append(eps(b"39990-UNKNOWN,0000\x00\x00")) + if case == "mixed-stock": + firmware.append(eps(b"39990-UNKNOWN-0000\x00\x00")) + cp = params(actual_candidate, firmware) + assert cp.dashcamOnly + assert not cp.flags & HondaFlags.EPS_MODIFIED + + +@pytest.mark.parametrize("candidate", tuple(SOURCE_BASELINES)) +def test_stock_lookup_and_tunes_do_not_acquire_modified_marker(candidate): + cp = params(candidate, []) + assert not cp.flags & HondaFlags.EPS_MODIFIED + lookup = CarControllerParams(cp) + assert lookup.STEER_LOOKUP_V == lookup.STEER_LOOKUP + + +def test_recognized_modified_eps_inventory_is_exact_original_subset(): + assert set(KNOWN_CASES) == {(car, version) for car, versions in MODIFIED_EPS_FW.items() for version in versions} diff --git a/opendbc_repo/opendbc/car/honda/tests/test_modified_eps_controller.py b/opendbc_repo/opendbc/car/honda/tests/test_modified_eps_controller.py new file mode 100644 index 0000000000..d05ded8b91 --- /dev/null +++ b/opendbc_repo/opendbc/car/honda/tests/test_modified_eps_controller.py @@ -0,0 +1,47 @@ +import pytest + +from opendbc.car import structs +from opendbc.car.honda.interface import CarInterface +from opendbc.car.honda.tests.test_modified_eps import KNOWN_CASES, eps, params +from opendbc.car.honda.values import CAR + + +@pytest.mark.parametrize("identity,firmware", KNOWN_CASES) +def test_actual_modified_factory_controller_consumes_separate_lookup(identity, firmware): + cp = params(identity, [eps(firmware)]) + ci = CarInterface(cp) + ci.update([]) + cc = structs.CarControl(latActive=True) + cc.actuators.torque = 1.0 + emitted = [] + for tick in range(250): + actuators, frames = ci.apply(cc.as_reader(), 1_000_000_000 + tick * 10_000_000) + assert frames + emitted.append(actuators.torqueOutputCan) + expected_max = 3840 if identity in (CAR.HONDA_CIVIC, CAR.HONDA_CRV_5G) else ci.CC.params.STEER_MAX + assert max(abs(value) for value in emitted) <= expected_max + assert abs(emitted[-1]) >= expected_max - 1 + assert (ci.CC.modified_civic_steering is not None) == (identity == CAR.HONDA_CIVIC_BOSCH) + + +def test_actual_modified_civic_driver_override_and_inactive_reset(): + cp = params(CAR.HONDA_CIVIC_BOSCH, [eps(b'39990-TGG,A020\x00\x00')]) + ci = CarInterface(cp) + ci.update([]) + cc = structs.CarControl(latActive=True) + cc.actuators.torque = 0.8 + for tick in range(20): + ci.CS.out = structs.CarState(vEgo=15.0, steeringPressed=True, steeringTorque=-1.0).as_reader() + ci.apply(cc.as_reader(), 1_000_000_000 + tick * 10_000_000) + owner = ci.CC.modified_civic_steering + assert owner.steering_pressed_robust_prev + assert owner.torque_lpf == owner.prev_torque_cmd == 0.0 + cc.latActive = False + ci.apply(cc.as_reader(), 1_200_000_000) + assert owner.steering_pressed_filter_s == 0.0 + assert not owner.steering_pressed_robust_prev + + +def test_ordinary_civic_has_no_modified_filter_owner(): + ci = CarInterface(params(CAR.HONDA_CIVIC_BOSCH, [eps(b'39990-TBA-C120\x00\x00')])) + assert ci.CC.modified_civic_steering is None diff --git a/opendbc_repo/opendbc/car/honda/tests/test_startup_profiles.py b/opendbc_repo/opendbc/car/honda/tests/test_startup_profiles.py index b2aeb2003e..bbbc8490d1 100644 --- a/opendbc_repo/opendbc/car/honda/tests/test_startup_profiles.py +++ b/opendbc_repo/opendbc/car/honda/tests/test_startup_profiles.py @@ -34,8 +34,7 @@ STARTUP_CASES = ( ) -@pytest.mark.parametrize("identity", STARTUP_CASES) -def test_final_cp_publication_and_disabled_startup(identity, monkeypatch): +def exercise_final_cp_publication_and_disabled_startup(identity, monkeypatch, firmware=()): from opendbc.car import car_helpers from openpilot.cereal import messaging from openpilot.common.params import Params @@ -58,9 +57,12 @@ def test_final_cp_publication_and_disabled_startup(identity, monkeypatch): selected_gear = messages.get("GEARBOX_AUTO") or messages.get("GEARBOX_CVT") assert selected_gear is not None fingerprint[pt_bus][selected_gear.address] = selected_gear.size - initial = CarInterface.get_params(identity, fingerprint, [], False, False, False) + initial = CarInterface.get_params(identity, fingerprint, list(firmware), False, False, False) initial.carVin = "0" * 17 - initial.carFw = [] + initial.carFw = list(firmware) + if firmware: + assert initial.flags & HondaFlags.EPS_MODIFIED + assert not initial.dashcamOnly expected = initial.to_dict() with OpenpilotPrefix(): saved = Params() @@ -69,7 +71,7 @@ def test_final_cp_publication_and_disabled_startup(identity, monkeypatch): subscriber = messaging.sub_sock("carParams", timeout=100, conflate=True) card = ci = controls = None try: - observed = (identity, fingerprint, initial.carVin, [], initial.fingerprintSource, True) + observed = (identity, fingerprint, initial.carVin, list(firmware), initial.fingerprintSource, True) with monkeypatch.context() as discovery: discovery.setattr(car_helpers, "fingerprint", lambda *args: observed) discovery.setattr(card_module, "can_comm_callbacks", lambda *args: (lambda *args: [], lambda frames: None)) @@ -100,3 +102,21 @@ def test_final_cp_publication_and_disabled_startup(identity, monkeypatch): finally: del controls, card, ci, subscriber gc.collect() + + +@pytest.mark.parametrize("identity", STARTUP_CASES) +def test_final_cp_publication_and_disabled_startup(identity, monkeypatch): + exercise_final_cp_publication_and_disabled_startup(identity, monkeypatch) + + +@pytest.mark.parametrize("identity,version", ( + (CAR.HONDA_CIVIC, b"39990-TBA,A030\x00\x00"), + (CAR.HONDA_ACCORD, b"39990-TVA,A150\x00\x00"), + (CAR.HONDA_CIVIC_BOSCH, b"39990-TGG,A020\x00\x00"), + (CAR.HONDA_CIVIC_BOSCH, b"39990-TGG,A120\x00\x00"), + (CAR.HONDA_CRV_5G, b"39990-TLA,A040\x00\x00"), +)) +def test_known_modified_eps_final_cp_publication_and_disabled_startup(identity, version, monkeypatch): + firmware = (structs.CarParams.CarFw(ecu=structs.CarParams.Ecu.eps, address=0x18DA30F1, + subAddress=0, fwVersion=version, brand="honda"),) + exercise_final_cp_publication_and_disabled_startup(identity, monkeypatch, firmware) diff --git a/opendbc_repo/opendbc/car/honda/values.py b/opendbc_repo/opendbc/car/honda/values.py index 0586333fc6..b1cec75a33 100644 --- a/opendbc_repo/opendbc/car/honda/values.py +++ b/opendbc_repo/opendbc/car/honda/values.py @@ -65,6 +65,16 @@ class CarControllerParams: # Odyssey MMR uses up to 2560 for LKA; higher RDM commands are nonlinear and also apply brake drag. self.STEER_MAX = 2560 self.STEER_LOOKUP = [-self.STEER_MAX, 0, self.STEER_MAX] + self.STEER_LOOKUP_V = list(self.STEER_LOOKUP) + if CP.flags & HondaFlags.EPS_MODIFIED: + if CP.carFingerprint == CAR.HONDA_CIVIC: + self.STEER_MAX = 8000 + self.STEER_LOOKUP = [-8000, -2560, 0, 2560, 8000] + self.STEER_LOOKUP_V = [-3840, -2560, 0, 2560, 3840] + elif CP.carFingerprint == CAR.HONDA_CRV_5G: + self.STEER_MAX = 10000 + self.STEER_LOOKUP = [-10000, -2560, 0, 2560, 10000] + self.STEER_LOOKUP_V = [-3840, -2560, 0, 2560, 3840] class HondaSafetyFlags(IntFlag): @@ -97,6 +107,7 @@ class HondaFlags(IntFlag): HAS_BSM = 1024 # blind spot monitoring HYBRID = 2048 BOSCH_TJA_CONTROL = 4096 + EPS_MODIFIED = 8192 # Car button codes @@ -472,6 +483,13 @@ class CAR(Platforms): ) +MODIFIED_EPS_FW = { + CAR.HONDA_CIVIC: (b'39990-TBA,A030\x00\x00',), + CAR.HONDA_ACCORD: (b'39990-TVA,A150\x00\x00',), + CAR.HONDA_CIVIC_BOSCH: (b'39990-TGG,A020\x00\x00', b'39990-TGG,A120\x00\x00'), + CAR.HONDA_CRV_5G: (b'39990-TLA,A040\x00\x00',), +} + MANUAL_TRANS_CARS = frozenset((CAR.HONDA_ACCORD, CAR.HONDA_CIVIC_2022)) DBC = CAR.create_dbc_map()