long: split acc and blended

This commit is contained in:
rav4kumar
2026-08-17 16:01:59 -07:00
parent eb7d6dbbe9
commit 1dc5ee4368
3 changed files with 43 additions and 4 deletions
@@ -37,7 +37,10 @@ def get_coast_accel(pitch):
def get_cruise_accel(e2e, v_cruise, v_ego, a_cruise_prev, angle_steers, CP, dt, accel_coast, allow_throttle,
max_accel_override=None, min_accel_override=None):
max_accel = ACCEL_MAX if e2e else (get_max_accel(v_ego) if max_accel_override is None else max_accel_override)
if max_accel_override is not None:
max_accel = max_accel_override
else:
max_accel = ACCEL_MAX if e2e else get_max_accel(v_ego)
min_accel = A_CRUISE_MIN if e2e or min_accel_override is None else min_accel_override
if not e2e:
@@ -146,7 +149,7 @@ class LongitudinalPlanner(LongitudinalPlannerSP):
is_e2e = self.is_e2e(sm)
max_accel_override = self.get_max_accel_override(v_ego, is_e2e)
max_accel_override = self.get_max_accel_override(v_ego)
min_accel_override = self.get_min_accel_override(v_ego, is_e2e, force_decel)
self.accel_controller_active = max_accel_override is not None or min_accel_override is not None
self.a_cruise = get_cruise_accel(is_e2e, v_cruise, v_ego,
@@ -13,6 +13,11 @@ still force full ACCEL_MIN braking regardless. Lead-relevance checks, an SLC-sha
floor beyond that, and controller-internal Params writes are NOT ported from the
reference designs this was built from - do not backfill them here without revisiting
scope.
Ceiling vs floor apply on different policies: ACC (non-e2e) uses the controller's
ceiling AND floor; blended (e2e) uses the controller's ceiling but always the stock
floor (A_CRUISE_MIN), never the controller's -- final, don't try to make the floor
work under blended again.
"""
import unittest
@@ -141,6 +146,10 @@ class TestOffEqualsStock(OpenpilotTestCase):
planner = _bare_planner()
self.assertIsNone(planner.get_min_accel_override(v_ego=5.0, e2e=False, force_decel=False))
def test_disabled_max_accel_override_is_none(self):
planner = _bare_planner()
self.assertIsNone(planner.get_max_accel_override(v_ego=5.0))
def test_force_decel_excludes_min_accel_override_even_when_enabled(self):
self.params.put_bool("AccelPersonalityEnabled", True, block=True)
planner = _bare_planner()
@@ -158,6 +167,33 @@ class TestOffEqualsStock(OpenpilotTestCase):
self.assertIsNotNone(override)
self.assertLess(override, 0.0)
def test_enabled_max_accel_override_applies_in_acc_and_blended(self):
# Policy: max ceiling comes from AccelController in both ACC and blended (e2e) modes --
# only the min floor is blended-vs-stock. get_max_accel_override no longer takes an e2e
# arg because of this; the caller applies it unconditionally.
self.params.put_bool("AccelPersonalityEnabled", True, block=True)
planner = _bare_planner()
override = planner.get_max_accel_override(v_ego=5.0)
self.assertIsNotNone(override)
self.assertGreater(override, 0.0)
def test_blended_min_accel_uses_stock_not_controller(self):
# e2e/blended braking floor is deliberately left at stock's A_CRUISE_MIN, never the
# controller's floor -- this is the "acc policy = controller min+max, blended policy =
# controller max + stock min" split, final per product decision.
from openpilot.selfdrive.controls.lib.longitudinal_planner import get_cruise_accel, A_CRUISE_MIN
args = dict(v_cruise=-100.0, v_ego=20.0, a_cruise_prev=0.0, angle_steers=0.0, CP=_fake_cp(),
dt=DT_MDL, accel_coast=1.0, allow_throttle=True)
target = get_cruise_accel(True, **args, min_accel_override=-0.3)
self.assertAlmostEqual(target, A_CRUISE_MIN, places=6)
def test_blended_max_accel_uses_controller_override(self):
from openpilot.selfdrive.controls.lib.longitudinal_planner import get_cruise_accel
args = dict(v_cruise=100.0, v_ego=20.0, a_cruise_prev=0.0, angle_steers=0.0, CP=_fake_cp(),
dt=DT_MDL, accel_coast=1.0, allow_throttle=True)
target = get_cruise_accel(True, **args, max_accel_override=0.4)
self.assertAlmostEqual(target, 0.4, places=6)
class TestLeadGapWiden(OpenpilotTestCase):
def setUp(self):
@@ -44,8 +44,8 @@ class LongitudinalPlannerSP:
return experimental_mode and self.dec.mode() == "blended"
def get_max_accel_override(self, v_ego: float, e2e: bool) -> float | None:
if e2e or not self.accel_controller.is_enabled():
def get_max_accel_override(self, v_ego: float) -> float | None:
if not self.accel_controller.is_enabled():
return None
return self.accel_controller.get_max_accel(v_ego)