From 60aa4aad49b0faddd28e354e345bd03d256983dc Mon Sep 17 00:00:00 2001 From: firestar5683 <168790843+firestar5683@users.noreply.github.com> Date: Tue, 25 Aug 2026 15:37:25 -0500 Subject: [PATCH] Add VOACC takeoff safety regression coverage Co-authored-by: Robin Dittrich --- .../controls/tests/test_lead_follow_policy.py | 18 +++++++++-- .../tests/test_longitudinal_planner.py | 31 +++++++++++++++++++ 2 files changed, 47 insertions(+), 2 deletions(-) diff --git a/selfdrive/controls/tests/test_lead_follow_policy.py b/selfdrive/controls/tests/test_lead_follow_policy.py index 1c77e9bba..188cc2bdb 100644 --- a/selfdrive/controls/tests/test_lead_follow_policy.py +++ b/selfdrive/controls/tests/test_lead_follow_policy.py @@ -77,12 +77,26 @@ def test_follow_policy_never_relaxes_material_braking(): assert result.target == pytest.approx(-1.2) -def test_follow_policy_leaves_low_speed_vision_follow_uncapped(): - result = run(lead(d_rel=8.0, v_lead=4.0), v_ego=2.0, raw=1.4) +def test_follow_policy_leaves_low_speed_vision_departure_uncapped(): + # This is the range the old vision-only cap affected; below 4.5 m/s the + # longitudinal planner still has its independent weak-lead safety cap. + result = run(lead(d_rel=12.0, v_lead=6.0), v_ego=5.0, raw=1.4) assert result.accel_cap is None assert result.target == pytest.approx(1.4) +@pytest.mark.parametrize("v_ego", [0.0, 2.0, 4.5, 6.0, 7.9]) +def test_follow_policy_low_speed_vision_never_relaxes_braking(v_ego): + result = run( + lead(d_rel=8.0, v_lead=max(v_ego - 0.8, 0.0), a_lead=-0.8), + v_ego=v_ego, + previous=0.3, + raw=-0.6, + ) + + assert result.target <= -0.6 + + def test_follow_policy_bypasses_post_departure_handoff(): result = run(lead(d_rel=46.0, v_lead=22.0), v_ego=20.0, previous=0.0, raw=0.6, post_departure=True) assert result.target == pytest.approx(0.6) diff --git a/selfdrive/controls/tests/test_longitudinal_planner.py b/selfdrive/controls/tests/test_longitudinal_planner.py index 0ecd5b851..5d740fe40 100644 --- a/selfdrive/controls/tests/test_longitudinal_planner.py +++ b/selfdrive/controls/tests/test_longitudinal_planner.py @@ -1309,6 +1309,37 @@ def test_low_speed_weak_departure_accel_cap_softens_voacc_follow_pulse(model_ver assert planner.output_a_target <= 0.22 +@pytest.mark.parametrize("model_version", ["v11", "v12", "v13", "v14", "v15"]) +@pytest.mark.parametrize("v_ego,v_lead,d_rel", [ + (4.5, 3.7, 12.0), + (6.0, 5.2, 12.0), + (7.5, 6.7, 12.0), +]) +def test_acc_mode_low_speed_vision_takeoff_never_relaxes_closing_lead(model_version, v_ego, v_lead, d_rel): + """The takeoff change must not turn a closing vision lead into acceleration.""" + CP = CarInterface.get_non_essential_params(CAR.HONDA_CIVIC) + planner = LongitudinalPlanner(CP, init_v=v_ego) + sm = make_sm( + v_ego, + desired_accel=1.4, + min_accel=-1.0, + experimental_mode=False, + tracking_lead=True, + lead_one=make_lead( + status=True, d_rel=d_rel, v_lead=v_lead, a_lead=0.0, + radar=False, model_prob=0.99, y_rel=0.0, + ), + ) + sm["starpilotPlan"].vCruise = v_ego + 10.0 + + for _ in range(3): + planner.update(sm, make_toggles(model_version)) + + assert planner.mode == "acc" + assert planner.output_a_target <= 0.0 + assert not planner.output_should_stop + + @pytest.mark.parametrize("model_version", ["v11", "v12", "v13", "v14", "v15"]) def test_acc_mode_pretracking_vision_far_slower_lead_starts_braking_before_tracking(model_version): v_ego = 21.48