fede with speed

This commit is contained in:
rav4kumar
2026-11-07 10:49:21 -07:00
parent 2a33051f0f
commit 13dfd1bc3d
2 changed files with 69 additions and 7 deletions
@@ -9,16 +9,35 @@ import numpy as np
from openpilot.common.realtime import DT_CTRL
from openpilot.selfdrive.controls.lib.longcontrol import LongControl, LongCtrlState
TAPER_JERK = 0.25
TAPER_MAX_DECEL = 1.0
MAX_JERK = 2.0
class LongControlSP(LongControl):
def __init__(self, CP, CP_SP):
super().__init__(CP, CP_SP)
self.was_tapering = False
def update(self, active, CS, a_target, should_stop, accel_limits):
prev_output_accel = self.last_output_accel
smooth_stop = self.CP_SP.smoothStopDecelRate > 0.0
tapering = smooth_stop and not should_stop and -TAPER_MAX_DECEL < a_target < 0.0
if tapering:
accel_limits = (max(accel_limits[0], -float(np.sqrt(2.0 * TAPER_JERK * max(CS.vEgo, 0.0)))), accel_limits[1])
output_accel = super().update(active, CS, a_target, should_stop, accel_limits)
if self.long_control_state == LongCtrlState.stopping and self.CP_SP.smoothStopDecelRate > 0.0:
output_accel = self.stopping_accel(prev_output_accel, accel_limits)
if smooth_stop:
if self.long_control_state == LongCtrlState.stopping:
output_accel = self.stopping_accel(prev_output_accel, accel_limits)
elif self.long_control_state == LongCtrlState.pid and (tapering or self.was_tapering):
max_change = MAX_JERK * DT_CTRL
output_accel = float(np.clip(output_accel, prev_output_accel - max_change, prev_output_accel + max_change))
self.last_output_accel = output_accel
self.was_tapering = tapering
return float(output_accel)
def stopping_accel(self, accel, accel_limits):
@@ -12,7 +12,7 @@ from opendbc.car.structs import car
from openpilot.common.realtime import DT_CTRL
from openpilot.cereal import custom
from openpilot.selfdrive.controls.lib.longcontrol import LongCtrlState
from openpilot.sunnypilot.selfdrive.controls.lib.longcontrol_sp import LongControlSP
from openpilot.sunnypilot.selfdrive.controls.lib.longcontrol_sp import LongControlSP, MAX_JERK, TAPER_JERK, TAPER_MAX_DECEL
SMOOTH_STOP_DECEL_RATE = 0.3
@@ -35,8 +35,9 @@ def make_cs(v_ego, standstill=False):
def start_stopping(loc, a_target=-0.5):
loc.update(True, make_cs(0.5), a_target, False, LIMITS)
return loc.update(True, make_cs(0.3), a_target, True, LIMITS)
for _ in range(100):
loc.update(True, make_cs(0.5, a_target), a_target, False, LIMITS)
return loc.update(True, make_cs(0.3, a_target), a_target, True, LIMITS)
def test_decel_ramps_at_stopping_rate():
@@ -50,8 +51,9 @@ def test_decel_ramps_at_stopping_rate():
def test_no_step_at_handover():
loc = make_control()
out = loc.update(True, make_cs(0.5), -0.5, False, LIMITS)
assert abs(start_stopping(loc) - out) <= SMOOTH_STOP_DECEL_RATE * DT_CTRL + 1e-6
for _ in range(100):
out = loc.update(True, make_cs(0.5, -0.5), -0.5, False, LIMITS)
assert abs(loc.update(True, make_cs(0.3, -0.5), -0.5, True, LIMITS) - out) <= SMOOTH_STOP_DECEL_RATE * DT_CTRL + 1e-6
def test_decel_never_fades_to_zero_while_stopping():
@@ -96,3 +98,44 @@ def test_rate_comes_from_car_params(rate):
loc = make_control(rate=rate)
out = start_stopping(loc)
assert loc.update(True, make_cs(0.1), -0.5, True, LIMITS) == pytest.approx(out - rate * DT_CTRL)
def settle(loc, v, a_target, frames=600):
for _ in range(frames):
out = loc.update(True, make_cs(v, a_target), a_target, False, LIMITS)
return out
def test_gentle_braking_fades_with_speed():
loc = make_control()
outs = [settle(loc, v, -0.6) for v in (1.0, 0.4, 0.15, 0.05)]
assert outs[0] < outs[1] < outs[2] < outs[3]
assert abs(outs[3]) < 0.2
def test_decel_never_exceeds_profile_while_tapering():
loc = make_control()
for v in (0.8, 0.5, 0.2, 0.1):
assert settle(loc, v, -0.6) >= -((2.0 * TAPER_JERK * v) ** 0.5) - 1e-6
def test_hard_braking_is_not_tapered():
loc = make_control()
target = -(TAPER_MAX_DECEL + 0.5)
assert settle(loc, 0.1, target) <= target
def test_taper_off_without_smooth_stop():
loc = make_control(rate=0.0)
assert settle(loc, 0.1, -0.6) <= -0.6
def test_taper_never_steps_the_output():
loc = make_control()
prev, v = None, 1.0
for target in [-1.2] * 30 + [-0.9] * 300:
v = max(v - 0.4 * DT_CTRL, 0.1)
out = loc.update(True, make_cs(v, -0.4), target, False, LIMITS)
if prev is not None:
assert abs(out - prev) <= MAX_JERK * DT_CTRL + 1e-6
prev = out