Dead Cow Gully

This commit is contained in:
firestar5683
2026-06-29 19:57:24 -05:00
parent b4dc28a45e
commit 1c2627e1ae
15 changed files with 197 additions and 20 deletions
+2
View File
@@ -61,6 +61,8 @@ inline static std::unordered_map<std::string, ParamKeyAttributes> keys = {
{"HardwareSerial", {PERSISTENT, STRING}},
{"HasAcceptedTerms", {PERSISTENT, STRING, "0"}},
{"HondaGasFactorParams", {PERSISTENT, FLOAT}},
{"HondaLateralPidKiScale", {PERSISTENT, FLOAT, "1.0", "1.0", 3}},
{"HondaLateralPidKpScale", {PERSISTENT, FLOAT, "1.0", "1.0", 3}},
{"HondaWindFactorParams", {PERSISTENT, FLOAT}},
{"InstallDate", {PERSISTENT, TIME}},
{"IsDriverViewEnabled", {CLEAR_ON_MANAGER_START, BOOL}},
+14 -2
View File
@@ -187,13 +187,19 @@ def get_testing_ground_1_brake_switch_bias(v_ego: float) -> int:
return int(round(np.interp(v_ego, [0.0, 6.0, 15.0, 30.0], [40.0, 85.0, 130.0, 170.0])))
def shape_truck_positive_accel(accel: float, v_ego: float, enabled: bool) -> float:
def shape_truck_positive_accel(accel: float, v_ego: float, enabled: bool,
lead_visible: bool = False, set_speed_error: float = 0.0) -> float:
if not enabled or accel <= 0.0 or v_ego < 12.0:
return accel
low_scale = float(np.interp(v_ego, [12.0, 18.0, 25.0, 35.0], [0.95, 0.88, 0.82, 0.76]))
mid_scale = float(np.interp(v_ego, [12.0, 18.0, 25.0, 35.0], [0.98, 0.94, 0.89, 0.84]))
if lead_visible and set_speed_error > 0.0:
follow_relief = float(np.interp(set_speed_error, [0.0, 1.0, 2.5, 4.0, 6.0], [0.0, 0.08, 0.18, 0.35, 0.55]))
low_scale += (1.0 - low_scale) * follow_relief
mid_scale += (1.0 - mid_scale) * follow_relief
if accel <= 0.12:
return accel * low_scale
if accel <= 0.35:
@@ -939,7 +945,13 @@ class CarController(CarControllerBase):
getattr(self.CP, "transmissionType", None) == TransmissionType.automatic and
not self.CP.enableGasInterceptorDEPRECATED
):
accel_input = shape_truck_positive_accel(accel_input, CS.out.vEgo, True)
accel_input = shape_truck_positive_accel(
accel_input,
CS.out.vEgo,
True,
lead_visible=CC.hudControl.leadVisible,
set_speed_error=max(CC.hudControl.setSpeed - CS.out.vEgo, 0.0),
)
accel_cmd = float(np.clip(accel_input, self.params.ACCEL_MIN, accel_max))
torque = self.tireRadius * ((self.mass * accel_cmd) + (0.5 * self.coeffDrag * self.frontalArea * self.airDensity * CS.out.vEgo ** 2))
@@ -817,6 +817,21 @@ def test_shape_truck_positive_accel_is_inactive_when_disabled_or_low_speed():
assert shape_truck_positive_accel(0.12, 6.0, True) == 0.12
def test_shape_truck_positive_accel_preserves_more_follow_authority_with_lead():
base = shape_truck_positive_accel(0.28, 26.0, True)
relieved = shape_truck_positive_accel(0.28, 26.0, True, lead_visible=True, set_speed_error=6.0)
assert relieved > base
assert relieved < 0.28
def test_shape_truck_positive_accel_does_not_relax_without_speed_error():
base = shape_truck_positive_accel(0.28, 26.0, True)
no_error = shape_truck_positive_accel(0.28, 26.0, True, lead_visible=True, set_speed_error=0.0)
assert no_error == base
def test_use_interceptor_sng_launch_requires_actual_near_stop():
CP = SimpleNamespace(vEgoStarting=0.25)
@@ -69,6 +69,8 @@ DEFAULT_ANGLE_SMOOTHING_ALPHA_V = [0.2, 0.1, 0.0]
EV9_HIGH_ANGLE_GAIN_BP = [70.0, 120.0, 220.0, 320.0]
EV9_HIGH_ANGLE_GAIN_CAP_V = [0.85, 0.55, 0.30, 0.16]
EV9_HIGH_ANGLE_GAIN_MIN = 0.004
EV9_DRIVER_OVERRIDE_GAIN_BP = [125.0, 250.0, 375.0]
EV9_DRIVER_OVERRIDE_GAIN_CAP_V = [0.70, 0.12, 0.0]
def egmp_dynamic_longitudinal_tuning(CP) -> bool:
@@ -246,12 +248,20 @@ def compute_torque_reduction_gain(steering_torque, v_ego, lat_active, last_gain)
return round(gain / 0.004) * 0.004
def apply_ev9_high_angle_gain_cap(CP, gain: float, steering_angle_deg: float, lat_active: bool) -> float:
def apply_ev9_high_angle_gain_cap(CP, gain: float, steering_angle_deg: float, lat_active: bool,
steering_torque: float = 0.0, steering_pressed: bool = False) -> float:
if CP.carFingerprint != CAR.KIA_EV9 or not CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING or not lat_active:
return gain
cap = float(np.interp(abs(steering_angle_deg), EV9_HIGH_ANGLE_GAIN_BP, EV9_HIGH_ANGLE_GAIN_CAP_V))
return max(EV9_HIGH_ANGLE_GAIN_MIN, min(gain, cap))
gain = max(EV9_HIGH_ANGLE_GAIN_MIN, min(gain, cap))
if steering_pressed or abs(steering_torque) >= EV9_DRIVER_OVERRIDE_GAIN_BP[0]:
driver_override_cap = float(np.interp(abs(steering_torque), EV9_DRIVER_OVERRIDE_GAIN_BP,
EV9_DRIVER_OVERRIDE_GAIN_CAP_V))
gain = min(gain, driver_override_cap)
return gain
def process_hud_alert(enabled, fingerprint, hud_control):
@@ -410,7 +420,8 @@ class CarController(CarControllerBase):
CS.out.steeringAngleDeg, CC.latActive, self.params, self.BASELINE_VM)
apply_torque = compute_torque_reduction_gain(CS.out.steeringTorque, v_ego_raw, CC.latActive, self.apply_torque_last)
apply_torque = apply_ev9_high_angle_gain_cap(self.CP, apply_torque, CS.out.steeringAngleDeg, CC.latActive)
apply_torque = apply_ev9_high_angle_gain_cap(self.CP, apply_torque, CS.out.steeringAngleDeg, CC.latActive,
CS.out.steeringTorque, CS.out.steeringPressed)
apply_steer_req = CC.latActive and apply_torque != 0.0
torque_fault = False
@@ -138,7 +138,7 @@ def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque,
"LKA_RHLnWrnSta": 0,
"LKA_HndsoffSnd": 0,
"LKA_StrSnd": 0,
"LKA_SysIndReq": 2 if enabled else 1,
"LKA_SysIndReq": 2 if enabled or lat_active else 1,
"StrTqReqVal": 0,
"ActToiSta": 0,
"ToiFltSta": 0,
@@ -148,6 +148,8 @@ class CarInterface(CarInterfaceBase):
if ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
ret.steerControlType = structs.CarParams.SteerControlType.angle
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ANGLE_STEERING.value
if candidate == CAR.KIA_EV9:
ret.steerAtStandstill = True
if ret.flags & HyundaiFlags.CCNC and not ret.flags & HyundaiFlags.CANFD_LKA_STEERING:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CCNC.value
@@ -297,7 +297,17 @@ class TestHyundaiFingerprint:
assert apply_ev9_high_angle_gain_cap(ev9_cp, 0.70, 320.0, True) == pytest.approx(0.16)
assert apply_ev9_high_angle_gain_cap(ev9_cp, 0.0, 320.0, True) > 0.0
assert apply_ev9_high_angle_gain_cap(ev9_cp, 0.70, 320.0, False) == pytest.approx(0.70)
assert apply_ev9_high_angle_gain_cap(ev9_cp, 0.70, 30.0, True, 250.0, True) == pytest.approx(0.12)
assert apply_ev9_high_angle_gain_cap(ev9_cp, 0.70, 30.0, True, 400.0, True) == pytest.approx(0.0)
assert apply_ev9_high_angle_gain_cap(sportage_cp, 0.70, 320.0, True) == pytest.approx(0.70)
assert apply_ev9_high_angle_gain_cap(sportage_cp, 0.70, 30.0, True, 400.0, True) == pytest.approx(0.70)
def test_ev9_allows_lateral_at_standstill_without_changing_other_angle_platforms(self):
ev9_cp = CarInterface.get_params(CAR.KIA_EV9, gen_empty_fingerprint(), [], False, False, False, None)
sportage_cp = CarInterface.get_params(CAR.KIA_SPORTAGE_HEV_2026, gen_empty_fingerprint(), [], False, False, False, None)
assert ev9_cp.steerAtStandstill
assert not sportage_cp.steerAtStandstill
def test_ccnc_hda2_lka_layout_does_not_set_ccnc_safety_param(self):
fingerprint = gen_empty_fingerprint()
@@ -1848,7 +1858,7 @@ class TestHyundaiFingerprint:
"DAMP_FACTOR": 0,
}
msgs = hyundaicanfd.create_steering_messages(packer, CP, can_bus, True, True, 0.44, -31.5,
msgs = hyundaicanfd.create_steering_messages(packer, CP, can_bus, False, True, 0.44, -31.5,
lkas_base_values=stock_lkas, lka_icon=2)
lkas_msgs = [msg for msg in msgs if msg[0] == 0x110]
assert len(lkas_msgs) == 1
@@ -26,7 +26,7 @@ ACCEL_WINDDOWN_LIMIT = -4.0 * DT_CTRL * 3 # m/s^2 / frame
ACCEL_PID_UNWIND = 0.03 * DT_CTRL * 3 # m/s^2 / frame
PRIUS_INTEGRAL_MISMATCH_UNWIND = 8.0
PRIUS_POSITIVE_FEEDFORWARD_SCALE = 0.7
PRIUS_CRUISE_FEEDFORWARD_SCALE = 0.85
PRIUS_CRUISE_FEEDFORWARD_SCALE = 1.0
MAX_PITCH_COMPENSATION = 1.5 # m/s^2
TOYOTA_COAST_BRAKE_MIN_SPEED = 15.0 # m/s
@@ -306,7 +306,7 @@ class TestToyotaCarController:
def test_prius_positive_feedforward_scale_restores_cruise_authority(self):
assert get_prius_positive_feedforward_scale(20.0) > get_prius_positive_feedforward_scale(8.0)
assert abs(get_prius_positive_feedforward_scale(20.0) - 0.85) < 1e-6
assert abs(get_prius_positive_feedforward_scale(20.0) - 1.0) < 1e-6
def test_sng_hack_clears_existing_standstill_latch(self):
controller = self._make_controller(standstill_req=True, last_standstill=True)
+42 -2
View File
@@ -7,11 +7,28 @@ from openpilot.starpilot.common.testing_grounds import testing_ground
from openpilot.selfdrive.controls.lib.latcontrol import LatControl
from openpilot.common.pid import PIDController
HONDA_PID_GAIN_SCALE_MIN = 0.1
HONDA_PID_GAIN_SCALE_MAX = 4.0
def civic_bosch_modified_lateral_testing_ground_active() -> bool:
return testing_ground.use("8", "B")
def get_honda_lateral_pid_gain_scale(value) -> float:
try:
scale = float(value)
except (TypeError, ValueError):
return 1.0
if not math.isfinite(scale):
return 1.0
return min(max(scale, HONDA_PID_GAIN_SCALE_MIN), HONDA_PID_GAIN_SCALE_MAX)
def scale_lateral_pid_gain_values(values, scale: float) -> list[float]:
return [float(value) * scale for value in values]
def get_civic_bosch_modified_pid_output_scale(desired_angle_deg: float, desired_angle_delta_deg: float, v_ego: float) -> float:
abs_angle = abs(desired_angle_deg)
speed_weight = min(max((v_ego - 4.0) / 10.0, 0.0), 1.0)
@@ -67,18 +84,41 @@ def get_civic_bosch_modified_pid_output_alpha(desired_angle_deg: float, desired_
class LatControlPID(LatControl):
def __init__(self, CP, CI, dt):
super().__init__(CP, CI, dt)
self.pid = PIDController((CP.lateralTuning.pid.kpBP, CP.lateralTuning.pid.kpV),
(CP.lateralTuning.pid.kiBP, CP.lateralTuning.pid.kiV),
self.base_kp_bp = [float(value) for value in CP.lateralTuning.pid.kpBP]
self.base_kp_v = [float(value) for value in CP.lateralTuning.pid.kpV]
self.base_ki_bp = [float(value) for value in CP.lateralTuning.pid.kiBP]
self.base_ki_v = [float(value) for value in CP.lateralTuning.pid.kiV]
self.pid = PIDController((self.base_kp_bp, self.base_kp_v),
(self.base_ki_bp, self.base_ki_v),
pos_limit=self.steer_max, neg_limit=-self.steer_max)
self.ff_factor = CP.lateralTuning.pid.kf
self.get_steer_feedforward = CI.get_steer_feedforward_function()
self.is_honda_pid_lateral = CP.brand == "honda"
self.honda_lateral_pid_kp_scale = 1.0
self.honda_lateral_pid_ki_scale = 1.0
self.is_civic_bosch_modified = CP.carFingerprint == HONDA.HONDA_CIVIC_BOSCH and bool(CP.flags & HondaFlags.EPS_MODIFIED)
self.prev_angle_steers_des_no_offset = 0.0
self.modified_civic_steering_pressed_filter_s = 0.0
self.modified_civic_steering_pressed_prev = False
self.prev_output_torque = 0.0
def update_honda_lateral_pid_gain_scale(self, starpilot_toggles):
if not self.is_honda_pid_lateral:
return
kp_scale = get_honda_lateral_pid_gain_scale(getattr(starpilot_toggles, "honda_lateral_pid_kp_scale", 1.0))
ki_scale = get_honda_lateral_pid_gain_scale(getattr(starpilot_toggles, "honda_lateral_pid_ki_scale", 1.0))
if math.isclose(kp_scale, self.honda_lateral_pid_kp_scale) and math.isclose(ki_scale, self.honda_lateral_pid_ki_scale):
return
self.honda_lateral_pid_kp_scale = kp_scale
self.honda_lateral_pid_ki_scale = ki_scale
self.pid._k_p = [self.base_kp_bp, scale_lateral_pid_gain_values(self.base_kp_v, kp_scale)]
self.pid._k_i = [self.base_ki_bp, scale_lateral_pid_gain_values(self.base_ki_v, ki_scale)]
def update(self, active, CS, VM, params, steer_limited_by_safety, desired_curvature, curvature_limited, lat_delay, calibrated_pose, model_data, starpilot_toggles):
self.update_honda_lateral_pid_gain_scale(starpilot_toggles)
pid_log = log.ControlsState.LateralPIDState.new_message()
pid_log.steeringAngleDeg = float(CS.steeringAngleDeg)
pid_log.steeringRateDeg = float(CS.steeringRateDeg)
+24 -6
View File
@@ -45,6 +45,27 @@ def get_bolt_acc_pedal_friction_bias(output_accel, a_target, v_ego):
return float(min(authority_gap * 0.30, max_bias) * speed_factor)
def get_bolt_acc_pedal_feedforward_gain(feedforward_gain, a_target, v_ego, pedal_regen_limit, last_output_accel):
effective_gain = feedforward_gain
if a_target >= 0.0:
return effective_gain
restore = 0.0
if a_target < pedal_regen_limit:
friction_gap = pedal_regen_limit - a_target
restore = float(interp(friction_gap, [0.0, 0.25, 0.75], [0.0, 0.6, 1.0]))
if v_ego > 5.0 and a_target < -1.10:
authority_gap = max(0.0, abs(a_target) - abs(min(last_output_accel, 0.0)))
target_restore = float(interp(abs(a_target), [1.1, 1.6, 2.2, 3.0], [0.0, 0.25, 0.55, 1.0]))
gap_restore = float(interp(authority_gap, [0.2, 0.6, 1.0, 1.6], [0.0, 0.25, 0.60, 1.0]))
speed_factor = float(interp(v_ego, [5.0, 8.0, 12.0, 18.0], [0.0, 0.35, 0.75, 1.0]))
restore = max(restore, max(target_restore, gap_restore) * speed_factor)
return float(feedforward_gain + ((1.0 - feedforward_gain) * clip(restore, 0.0, 1.0)))
def long_control_state_trans(CP, active, long_control_state, v_ego,
should_stop, brake_pressed, cruise_standstill, starpilot_toggles,
allow_stopping_release=True):
@@ -346,12 +367,9 @@ class LongControl:
return feedforward
pedal_regen_limit = float(interp(v_ego, BOLT_ACC_PEDAL_REGEN_LIMIT_BP, BOLT_ACC_PEDAL_REGEN_LIMIT_V))
if a_target >= pedal_regen_limit:
return feedforward
friction_gap = pedal_regen_limit - a_target
gain_restore = float(interp(friction_gap, [0.0, 0.25, 0.75], [0.0, 0.6, 1.0]))
effective_gain = self.feedforward_gain + ((1.0 - self.feedforward_gain) * gain_restore)
effective_gain = get_bolt_acc_pedal_feedforward_gain(
self.feedforward_gain, a_target, v_ego, pedal_regen_limit, self.last_output_accel,
)
return a_target * effective_gain
def update(self, active, CS, a_target, should_stop, accel_limits, starpilot_toggles):
@@ -707,6 +707,24 @@ class TestLatControl:
assert tapered_output == pytest.approx(base_output)
def test_honda_pid_gain_scales_update_live_from_opendbc_baseline(self):
controller, VM, CS, params, _ = self._build_pid_controller(HONDA.HONDA_ACCORD)
base_kp_v = list(controller.base_kp_v)
base_ki_v = list(controller.base_ki_v)
starpilot_toggles = SimpleNamespace(honda_lateral_pid_kp_scale=1.5, honda_lateral_pid_ki_scale=0.75)
controller.update(True, CS, VM, params, False, 0.0025, False, 0.2, None, None, starpilot_toggles)
assert controller.pid._k_p[1] == pytest.approx([value * 1.5 for value in base_kp_v])
assert controller.pid._k_i[1] == pytest.approx([value * 0.75 for value in base_ki_v])
starpilot_toggles.honda_lateral_pid_kp_scale = 2.0
starpilot_toggles.honda_lateral_pid_ki_scale = 1.25
controller.update(True, CS, VM, params, False, 0.0025, False, 0.2, None, None, starpilot_toggles)
assert controller.pid._k_p[1] == pytest.approx([value * 2.0 for value in base_kp_v])
assert controller.pid._k_i[1] == pytest.approx([value * 1.25 for value in base_ki_v])
def test_modified_civic_b_torque_path_uses_fixed_friction_threshold(self, monkeypatch):
CarInterface = interfaces[HONDA.HONDA_CIVIC_BOSCH]
CP = CarInterface.get_non_essential_params(HONDA.HONDA_CIVIC_BOSCH)
+25 -3
View File
@@ -5,7 +5,11 @@ import pytest
import openpilot.selfdrive.controls.lib.longcontrol as longcontrol
from opendbc.car.gm.values import CAR, GMFlags
from openpilot.selfdrive.controls.lib.longcontrol import LongControl, LongCtrlState, long_control_state_trans
from openpilot.selfdrive.controls.lib.longcontrol import (
LongControl,
LongCtrlState,
long_control_state_trans,
)
def make_toggles(**overrides):
@@ -510,12 +514,30 @@ def test_bolt_acc_pedal_friction_feedforward_blends_back_in_for_small_friction_r
pedal_regen_limit = float(longcontrol.interp(20.0, longcontrol.BOLT_ACC_PEDAL_REGEN_LIMIT_BP,
longcontrol.BOLT_ACC_PEDAL_REGEN_LIMIT_V))
a_target = pedal_regen_limit - 0.10
gain_restore = float(longcontrol.interp(0.10, [0.0, 0.25, 0.75], [0.0, 0.6, 1.0]))
expected = a_target * (0.20 + ((1.0 - 0.20) * gain_restore))
expected_gain = longcontrol.get_bolt_acc_pedal_feedforward_gain(0.20, a_target, 20.0, pedal_regen_limit, 0.0)
expected = a_target * expected_gain
assert lc._get_longitudinal_feedforward(a_target, 20.0) == pytest.approx(expected)
def test_bolt_acc_pedal_feedforward_gain_stays_base_for_mild_regen():
gain = longcontrol.get_bolt_acc_pedal_feedforward_gain(0.2, -1.0, 10.0, -2.75, -0.4)
assert gain == pytest.approx(0.2)
def test_bolt_acc_pedal_feedforward_gain_restores_for_authority_gap():
gain = longcontrol.get_bolt_acc_pedal_feedforward_gain(0.2, -1.83, 12.38, -2.79, -0.70)
assert gain > 0.55
def test_bolt_acc_pedal_feedforward_gain_restores_near_friction_handoff():
gain = longcontrol.get_bolt_acc_pedal_feedforward_gain(0.2, -2.63, 9.35, -2.69, -1.30)
assert gain > 0.45
def test_bolt_cc_pedal_friction_feedforward_remains_fully_scaled_by_kf():
CP = make_longcontrol_cp(
brand="gm",
+5
View File
@@ -686,6 +686,9 @@ class StarPilotVariables:
toggle.use_custom_latAccelFactor = bool(round(toggle.latAccelFactor, 2) != round(latAccelFactor, 2)) and is_torque_car and not toggle.force_auto_tune or toggle.force_auto_tune_off
toggle.steerRatio = self.get_value("SteerRatio", cast=float, condition=advanced_lateral_tuning, default=steerRatio, min=steerRatio * 0.5, max=steerRatio * 1.5)
toggle.use_custom_steerRatio = bool(round(toggle.steerRatio, 2) != round(steerRatio, 2)) and not toggle.force_auto_tune or toggle.force_auto_tune_off
honda_pid_lateral = toggle.car_make == "honda" and CP.lateralTuning.which() == "pid" and not is_angle_car
toggle.honda_lateral_pid_kp_scale = self.get_value("HondaLateralPidKpScale", cast=float, condition=honda_pid_lateral, default=1.0, min=0.1, max=4.0)
toggle.honda_lateral_pid_ki_scale = self.get_value("HondaLateralPidKiScale", cast=float, condition=honda_pid_lateral, default=1.0, min=0.1, max=4.0)
advanced_longitudinal_tuning = toggle.openpilot_longitudinal and self.get_value("AdvancedLongitudinalTune")
ev_vehicle = default_ev_tuning_enabled(CP)
@@ -1357,6 +1360,8 @@ class StarPilotVariables:
toggle.radar_tracks = False
toggle.show_stopping_point = False
toggle.show_stopping_point_metrics = False
toggle.honda_lateral_pid_kp_scale = 1.0
toggle.honda_lateral_pid_ki_scale = 1.0
toggle.goat_scream_alert = False
toggle.goat_scream_critical_alerts = False
@@ -3616,6 +3616,28 @@
"step": 0.01,
"precision": 2
},
{
"key": "HondaLateralPidKpScale",
"label": "Honda PID Kp Scale",
"description": "Scale the active Honda lateralTuning.pid.kpV values from openDBC. Applies live to Honda PID lateral only.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.1,
"max": 4.0,
"step": 0.05,
"precision": 2
},
{
"key": "HondaLateralPidKiScale",
"label": "Honda PID Ki Scale",
"description": "Scale the active Honda lateralTuning.pid.kiV values from openDBC. Applies live to Honda PID lateral only.",
"data_type": "float",
"ui_type": "numeric",
"min": 0.1,
"max": 4.0,
"step": 0.05,
"precision": 2
},
{
"key": "AllowImpossibleAcceleration",
"label": "Allow Impossible Acceleration",