Files
StarPilot/selfdrive/controls/tests/test_g70_friction_threshold.py
firestar5683 0c6ee69362 Long day
2026-09-24 17:12:32 -05:00

69 lines
3.2 KiB
Python

import math
import numpy as np
import pytest
from opendbc.car import structs
from opendbc.car.lateral import get_friction
from openpilot.selfdrive.controls.lib import latcontrol_vehicle_tunes as tunes
def legacy_threshold(speed, accel, jerk):
def sigmoid(x):
return 1.0 / (1.0 + math.exp(-x))
gain = (0.10 * sigmoid((speed - 10.0) / 3.0) * sigmoid((35.0 - speed) / 6.0) *
sigmoid((0.28 - abs(accel)) / 0.10) * sigmoid((0.35 - abs(jerk)) / 0.10))
return tunes.get_standard_friction_threshold(speed) * (1.0 + gain)
@pytest.mark.parametrize('speed,scale', [(0, 1), (5, 1), (10, 1), (15, 1.5), (20, 2), (35, 2), (45, 2)])
@pytest.mark.parametrize('accel,jerk', [(0, 0), (0.1, 0.2), (0.8, 0.3), (1.5, -0.5), (-0.8, -0.3)])
def test_speed_blend(speed, scale, accel, jerk):
assert tunes.get_genesis_g70_friction_threshold(speed, accel, jerk) == pytest.approx(
legacy_threshold(speed, accel, jerk) * scale)
def test_small_error_gain_and_full_compensation():
params = structs.CarParams.LateralTorqueTuning.new_message(friction=0.08, latAccelFactor=2.96)
old = legacy_threshold(30, 0.8, 0.2)
new = tunes.get_genesis_g70_friction_threshold(30, 0.8, 0.2)
for error in (-0.1, 0.1):
assert get_friction(error, 0, new, params) == pytest.approx(get_friction(error, 0, old, params) / 2)
for error in (-2, 2):
assert get_friction(error, 0, new, params) == pytest.approx(get_friction(error, 0, old, params))
def test_symmetric_and_continuous():
for speed in np.linspace(0, 45, 100):
assert tunes.get_genesis_g70_friction_threshold(speed, 0.8, 0.2) == pytest.approx(
tunes.get_genesis_g70_friction_threshold(speed, -0.8, -0.2))
for speed in (10, 20):
assert abs(tunes.get_genesis_g70_friction_threshold(speed + 1e-6) -
tunes.get_genesis_g70_friction_threshold(speed - 1e-6)) < 1e-6
@pytest.mark.parametrize('speed,accel,jerk,actual', [
(30, 0.2, 0.8, 0.1), (30, 0.35, 0.8, 0.3), (20, 1.0, 0.8, 0.8),
(10, 1.0, 0.8, 0.8), (30, 1.0, -0.8, 1.2), (30, 1.0, 0.0, 1.2),
])
def test_turn_in_preserves_center_low_speed_and_unwind(monkeypatch, speed, accel, jerk, actual):
revised = tunes.get_genesis_g70_friction_jerk_deadzone(speed, accel, jerk, actual)
monkeypatch.setattr(tunes, 'GENESIS_G70_CURVE_TURN_IN_JERK_REDUCTION', 0.0)
assert revised == tunes.get_genesis_g70_friction_jerk_deadzone(speed, accel, jerk, actual)
@pytest.mark.parametrize('direction', [-1, 1])
@pytest.mark.parametrize('jerk', [0.1, 0.5, 1.0])
def test_curve_turn_in_halves_remaining_jerk(monkeypatch, direction, jerk):
revised = tunes.get_genesis_g70_friction_jerk_deadzone(30, direction, direction * jerk, direction * 0.8)
monkeypatch.setattr(tunes, 'GENESIS_G70_CURVE_TURN_IN_JERK_REDUCTION', 0.0)
original = tunes.get_genesis_g70_friction_jerk_deadzone(30, direction, direction * jerk, direction * 0.8)
assert max(jerk - revised, 0) == pytest.approx(0.5 * max(jerk - original, 0))
@pytest.mark.parametrize('speed,accel', [(20, 0.8), (25, 0.8), (30, 0.35), (30, 0.7)])
def test_curve_turn_in_blend_continuity(speed, accel):
low = tunes.get_genesis_g70_friction_jerk_deadzone(speed - 1e-6, accel - 1e-6, 0.8)
high = tunes.get_genesis_g70_friction_jerk_deadzone(speed + 1e-6, accel + 1e-6, 0.8)
assert abs(high - low) < 1e-5