diff --git a/selfdrive/car/chrysler/interface.py b/selfdrive/car/chrysler/interface.py index eb1f6703cd..e74513c176 100755 --- a/selfdrive/car/chrysler/interface.py +++ b/selfdrive/car/chrysler/interface.py @@ -26,7 +26,7 @@ class CarInterface(CarInterfaceBase): elif candidate in RAM_DT: ret.safetyConfigs[0].safetyParam |= Panda.FLAG_CHRYSLER_RAM_DT - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) 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. new_eps_platform = candidate in (CAR.CHRYSLER_PACIFICA_2019_HYBRID, CAR.CHRYSLER_PACIFICA_2020, CAR.JEEP_GRAND_CHEROKEE_2019, CAR.DODGE_DURANGO) diff --git a/selfdrive/car/data_structures.py b/selfdrive/car/data_structures.py index bd740ca325..4417466227 100644 --- a/selfdrive/car/data_structures.py +++ b/selfdrive/car/data_structures.py @@ -98,10 +98,16 @@ class CarParams: tireStiffnessFront: float = auto_field() # [N/rad] front tire coeff of stiff tireStiffnessRear: float = auto_field() # [N/rad] rear tire coeff of stiff - longitudinalTuning: 'LongitudinalPIDTuning' = field(default_factory=lambda: CarParams.LongitudinalPIDTuning()) - # lateralParams: LateralParams = auto_field() + longitudinalTuning: 'CarParams.LongitudinalPIDTuning' = field(default_factory=lambda: CarParams.LongitudinalPIDTuning()) + lateralParams: 'CarParams.LateralParams' = field(default_factory=lambda: CarParams.LateralParams()) lateralTuning: 'CarParams.LateralPIDTuning | CarParams.LateralTorqueTuning' = field(default_factory=lambda: CarParams.LateralPIDTuning()) + @dataclass + @apply_auto_fields + class LateralParams: + torqueBP: list[int] = auto_field() + torqueV: list[int] = auto_field() + @dataclass @apply_auto_fields class LateralPIDTuning: diff --git a/selfdrive/car/gm/interface.py b/selfdrive/car/gm/interface.py index 0124a2afdf..4fee31ead3 100755 --- a/selfdrive/car/gm/interface.py +++ b/selfdrive/car/gm/interface.py @@ -140,9 +140,9 @@ class CarInterface(CarInterfaceBase): (ret.networkLocation == NetworkLocation.gateway and ret.radarUnavailable) # Start with a baseline tuning for all GM vehicles. Override tuning as needed in each model section below. - ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.00]] - ret.lateralTuning.pid.kf = 0.00004 # full torque for 20 deg at 80mph means 0.00007818594 + ret.lateralTuning.kiBP, ret.lateralTuning.kpBP = [[0.], [0.]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.2], [0.00]] + ret.lateralTuning.kf = 0.00004 # full torque for 20 deg at 80mph means 0.00007818594 ret.steerActuatorDelay = 0.1 # Default delay, not measured yet ret.steerLimitTimer = 0.4 @@ -150,39 +150,39 @@ class CarInterface(CarInterfaceBase): ret.longitudinalActuatorDelay = 0.5 # large delay to initially start braking if candidate == CAR.CHEVROLET_VOLT: - ret.lateralTuning.pid.kpBP = [0., 40.] - ret.lateralTuning.pid.kpV = [0., 0.17] - ret.lateralTuning.pid.kiBP = [0.] - ret.lateralTuning.pid.kiV = [0.] - ret.lateralTuning.pid.kf = 1. # get_steer_feedforward_volt() + ret.lateralTuning.kpBP = [0., 40.] + ret.lateralTuning.kpV = [0., 0.17] + ret.lateralTuning.kiBP = [0.] + ret.lateralTuning.kiV = [0.] + ret.lateralTuning.kf = 1. # get_steer_feedforward_volt() ret.steerActuatorDelay = 0.2 elif candidate == CAR.GMC_ACADIA: ret.minEnableSpeed = -1. # engage speed is decided by pcm ret.steerActuatorDelay = 0.2 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.BUICK_LACROSSE: - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.CADILLAC_ESCALADE: ret.minEnableSpeed = -1. # engage speed is decided by pcm - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate in (CAR.CADILLAC_ESCALADE_ESV, CAR.CADILLAC_ESCALADE_ESV_2019): ret.minEnableSpeed = -1. # engage speed is decided by pcm if candidate == CAR.CADILLAC_ESCALADE_ESV: - ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[10., 41.0], [10., 41.0]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.13, 0.24], [0.01, 0.02]] - ret.lateralTuning.pid.kf = 0.000045 + ret.lateralTuning.kiBP, ret.lateralTuning.kpBP = [[10., 41.0], [10., 41.0]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.13, 0.24], [0.01, 0.02]] + ret.lateralTuning.kf = 0.000045 else: ret.steerActuatorDelay = 0.2 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.CHEVROLET_BOLT_EUV: ret.steerActuatorDelay = 0.2 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.CHEVROLET_SILVERADO: # On the Bolt, the ECM and camera independently check that you are either above 5 kph or at a stop @@ -190,14 +190,14 @@ class CarInterface(CarInterfaceBase): # TODO: check if this is split by EV/ICE with more platforms in the future if ret.openpilotLongitudinalControl: ret.minEnableSpeed = -1. - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.CHEVROLET_EQUINOX: - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) elif candidate == CAR.CHEVROLET_TRAILBLAZER: ret.steerActuatorDelay = 0.2 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) return ret diff --git a/selfdrive/car/honda/interface.py b/selfdrive/car/honda/interface.py index 3eefd8f862..8c99887251 100755 --- a/selfdrive/car/honda/interface.py +++ b/selfdrive/car/honda/interface.py @@ -2,6 +2,7 @@ from cereal import car from panda import Panda from openpilot.selfdrive.car.conversions import Conversions as CV +from openpilot.selfdrive.car.data_structures import CarParams from openpilot.selfdrive.car.helpers import interp from openpilot.selfdrive.car.honda.hondacan import CanBus from openpilot.selfdrive.car.honda.values import CarControllerParams, CruiseButtons, CruiseSettings, HondaFlags, CAR, HONDA_BOSCH, \ @@ -32,7 +33,7 @@ class CarInterface(CarInterfaceBase): return CarControllerParams.NIDEC_ACCEL_MIN, interp(current_speed, ACCEL_MAX_BP, ACCEL_MAX_VALS) @staticmethod - def _get_params(ret, candidate, fingerprint, car_fw, experimental_long, docs): + def _get_params(ret: CarParams, candidate, fingerprint, car_fw, experimental_long, docs): ret.carName = "honda" CAN = CanBus(ret, fingerprint) @@ -68,8 +69,8 @@ class CarInterface(CarInterfaceBase): # Tire stiffness factor fictitiously lower if it includes the steering column torsion effect. # For modeling details, see p.198-200 in "The Science of Vehicle Dynamics (2014), M. Guiggiani" ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0], [0]] - ret.lateralTuning.pid.kiBP, ret.lateralTuning.pid.kpBP = [[0.], [0.]] - ret.lateralTuning.pid.kf = 0.00006 # conservative feed-forward + ret.lateralTuning.kiBP, ret.lateralTuning.kpBP = [[0.], [0.]] + ret.lateralTuning.kf = 0.00006 # conservative feed-forward if candidate in HONDA_BOSCH: ret.longitudinalActuatorDelay = 0.5 # s @@ -94,30 +95,30 @@ class CarInterface(CarInterfaceBase): # modified filter output values: 0x009F, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0108, 0x0400, 0x0480 # note: max request allowed is 4096, but request is capped at 3840 in firmware, so modifications result in 2x max ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 8000], [0, 2560, 3840]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.1]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.3], [0.1]] else: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560], [0, 2560]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[1.1], [0.33]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[1.1], [0.33]] elif candidate in (CAR.HONDA_CIVIC_BOSCH, CAR.HONDA_CIVIC_BOSCH_DIESEL, CAR.HONDA_CIVIC_2022): 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]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.8], [0.24]] elif candidate == CAR.HONDA_ACCORD: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] # TODO: determine if there is a dead zone at the top end if eps_modified: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.3], [0.09]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.3], [0.09]] else: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.6], [0.18]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.6], [0.18]] elif candidate == CAR.ACURA_ILX: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] # TODO: determine if there is a dead zone at the top end - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.8], [0.24]] elif candidate in (CAR.HONDA_CRV, CAR.HONDA_CRV_EU): ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.8], [0.24]] ret.wheelSpeedFactor = 1.025 elif candidate == CAR.HONDA_CRV_5G: @@ -126,43 +127,43 @@ class CarInterface(CarInterfaceBase): # stock request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x129A, 0x134D, 0x1400 # modified request output values: 0x0000, 0x0500, 0x0A15, 0x0E6D, 0x1100, 0x1200, 0x1ACD, 0x239A, 0x2800 ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 2560, 10000], [0, 2560, 3840]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.21], [0.07]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.21], [0.07]] else: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.64], [0.192]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.64], [0.192]] ret.wheelSpeedFactor = 1.025 elif candidate == CAR.HONDA_CRV_HYBRID: 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.6], [0.18]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.6], [0.18]] ret.wheelSpeedFactor = 1.025 elif candidate == CAR.HONDA_FIT: 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.2], [0.05]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.2], [0.05]] elif candidate == CAR.HONDA_FREED: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.05]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.2], [0.05]] elif candidate in (CAR.HONDA_HRV, CAR.HONDA_HRV_3G): ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 4096], [0, 4096]] if candidate == CAR.HONDA_HRV: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.16], [0.025]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.16], [0.025]] ret.wheelSpeedFactor = 1.025 else: - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] # TODO: can probably use some tuning + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.8], [0.24]] # TODO: can probably use some tuning elif candidate == CAR.ACURA_RDX: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 1000], [0, 1000]] # TODO: determine if there is a dead zone at the top end - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.8], [0.24]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.8], [0.24]] elif candidate == CAR.ACURA_RDX_3G: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 3840], [0, 3840]] - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.2], [0.06]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.2], [0.06]] elif candidate in (CAR.HONDA_ODYSSEY, CAR.HONDA_ODYSSEY_CHN): - ret.lateralTuning.pid.kpV, ret.lateralTuning.pid.kiV = [[0.28], [0.08]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.28], [0.08]] if candidate == CAR.HONDA_ODYSSEY_CHN: ret.lateralParams.torqueBP, ret.lateralParams.torqueV = [[0, 32767], [0, 32767]] # TODO: determine if there is a dead zone at the top end else: @@ -170,19 +171,19 @@ class CarInterface(CarInterfaceBase): elif candidate == CAR.HONDA_PILOT: 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.38], [0.11]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.38], [0.11]] elif candidate == CAR.HONDA_RIDGELINE: 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.38], [0.11]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.38], [0.11]] elif candidate == CAR.HONDA_INSIGHT: 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.6], [0.18]] + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.6], [0.18]] elif candidate == CAR.HONDA_E: 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.6], [0.18]] # TODO: can probably use some tuning + ret.lateralTuning.kpV, ret.lateralTuning.kiV = [[0.6], [0.18]] # TODO: can probably use some tuning else: raise ValueError(f"unsupported car {candidate}") diff --git a/selfdrive/car/hyundai/interface.py b/selfdrive/car/hyundai/interface.py index c3590ebb2e..e610218570 100644 --- a/selfdrive/car/hyundai/interface.py +++ b/selfdrive/car/hyundai/interface.py @@ -74,7 +74,7 @@ class CarInterface(CarInterfaceBase): ret.steerActuatorDelay = 0.1 # Default delay ret.steerLimitTimer = 0.4 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) if candidate == CAR.KIA_OPTIMA_G4_FL: ret.steerActuatorDelay = 0.2 diff --git a/selfdrive/car/interfaces.py b/selfdrive/car/interfaces.py index 5bab332117..4b56b26469 100644 --- a/selfdrive/car/interfaces.py +++ b/selfdrive/car/interfaces.py @@ -178,7 +178,7 @@ class CarInterfaceBase(ABC): # returns a set of default params to avoid repetition in car specific params @staticmethod - def get_std_params(candidate) -> CarParams: + def get_std_params(candidate: str) -> CarParams: ret = CarParams() ret.carFingerprint = candidate @@ -189,6 +189,7 @@ class CarInterfaceBase(ABC): # standard ALC params ret.tireStiffnessFactor = 1.0 ret.steerControlType = CarParams.SteerControlType.torque + ret.lateralParams = CarParams.LateralPIDTuning() ret.minSteerSpeed = 0. ret.wheelSpeedFactor = 1.0 diff --git a/selfdrive/car/mazda/interface.py b/selfdrive/car/mazda/interface.py index fcec6b18b0..43112bf5dc 100755 --- a/selfdrive/car/mazda/interface.py +++ b/selfdrive/car/mazda/interface.py @@ -21,7 +21,7 @@ class CarInterface(CarInterfaceBase): ret.steerActuatorDelay = 0.1 ret.steerLimitTimer = 0.8 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) if candidate not in (CAR.MAZDA_CX5_2022, ): ret.minSteerSpeed = LKAS_LIMITS.DISABLE_SPEED * CV.KPH_TO_MS diff --git a/selfdrive/car/subaru/interface.py b/selfdrive/car/subaru/interface.py index 0ea71e812f..a6c49ae5d6 100644 --- a/selfdrive/car/subaru/interface.py +++ b/selfdrive/car/subaru/interface.py @@ -38,7 +38,7 @@ class CarInterface(CarInterfaceBase): if ret.flags & SubaruFlags.LKAS_ANGLE: ret.steerControlType = car.CarParams.SteerControlType.angle else: - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) if candidate in (CAR.SUBARU_ASCENT, CAR.SUBARU_ASCENT_2023): ret.steerActuatorDelay = 0.3 # end-to-end angle controller diff --git a/selfdrive/car/toyota/interface.py b/selfdrive/car/toyota/interface.py index fed3476f89..8b2a7d58d7 100644 --- a/selfdrive/car/toyota/interface.py +++ b/selfdrive/car/toyota/interface.py @@ -55,7 +55,7 @@ class CarInterface(CarInterfaceBase): for fw in car_fw: if fw.ecu == "eps" and not fw.fwVersion == b'8965B47060\x00\x00\x00\x00\x00\x00': ret.steerActuatorDelay = 0.25 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning, steering_angle_deadzone_deg=0.2) + CarInterfaceBase.configure_torque_tune(candidate, ret, steering_angle_deadzone_deg=0.2) elif candidate in (CAR.LEXUS_RX, CAR.LEXUS_RX_TSS2): stop_and_go = True diff --git a/selfdrive/car/volkswagen/interface.py b/selfdrive/car/volkswagen/interface.py index 77e56875bf..1c11ab6746 100644 --- a/selfdrive/car/volkswagen/interface.py +++ b/selfdrive/car/volkswagen/interface.py @@ -72,14 +72,14 @@ class CarInterface(CarInterfaceBase): ret.steerLimitTimer = 0.4 if ret.flags & VolkswagenFlags.PQ: ret.steerActuatorDelay = 0.2 - CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning) + CarInterfaceBase.configure_torque_tune(candidate, ret) else: ret.steerActuatorDelay = 0.1 - ret.lateralTuning.pid.kpBP = [0.] - ret.lateralTuning.pid.kiBP = [0.] - ret.lateralTuning.pid.kf = 0.00006 - ret.lateralTuning.pid.kpV = [0.6] - ret.lateralTuning.pid.kiV = [0.2] + ret.lateralTuning.kpBP = [0.] + ret.lateralTuning.kiBP = [0.] + ret.lateralTuning.kf = 0.00006 + ret.lateralTuning.kpV = [0.6] + ret.lateralTuning.kiV = [0.2] # Global longitudinal tuning defaults, can be overridden per-vehicle