mirror of
https://github.com/sunnypilot/sunnypilot.git
synced 2026-02-18 18:53:55 +08:00
Bolt EUV: Non-linear torque function (#27696)
* add erf based ff
* silly bug; diff of nonlinear != nonlinear of diff
* add sigmoid based ff, ensure slope at 0 > 1
* reduce steer down limit and increase driver allowance
* rebase panda
* atry without friction, and with tanh nonlinear
* finalize the nonlinear function
* do not disable friction compensation in the ff
* bump panda
* bump panda
* update refs
* update refs
* resolve comments
* Add type hints
---------
Co-authored-by: Adeeb Shihadeh <adeebshihadeh@gmail.com>
old-commit-hash: 15b880c0ea
This commit is contained in:
2
panda
2
panda
Submodule panda updated: db6c50cd09...a1e1451d1c
@@ -1,13 +1,14 @@
|
||||
#!/usr/bin/env python3
|
||||
from cereal import car
|
||||
from math import fabs
|
||||
from math import fabs, exp
|
||||
from panda import Panda
|
||||
|
||||
from common.conversions import Conversions as CV
|
||||
from selfdrive.car import STD_CARGO_KG, create_button_event, scale_tire_stiffness, get_safety_config
|
||||
from selfdrive.car.gm.radar_interface import RADAR_HEADER_MSG
|
||||
from selfdrive.car.gm.values import CAR, CruiseButtons, CarControllerParams, EV_CAR, CAMERA_ACC_CAR, CanBus
|
||||
from selfdrive.car.interfaces import CarInterfaceBase
|
||||
from selfdrive.car.interfaces import CarInterfaceBase, TorqueFromLateralAccelCallbackType, FRICTION_THRESHOLD
|
||||
from selfdrive.controls.lib.drive_helpers import get_friction
|
||||
|
||||
ButtonType = car.CarState.ButtonEvent.Type
|
||||
EventName = car.CarEvent.EventName
|
||||
@@ -44,6 +45,29 @@ class CarInterface(CarInterfaceBase):
|
||||
else:
|
||||
return CarInterfaceBase.get_steer_feedforward_default
|
||||
|
||||
@staticmethod
|
||||
def torque_from_lateral_accel_bolt(lateral_accel_value: float, torque_params: car.CarParams.LateralTorqueTuning,
|
||||
lateral_accel_error: float, lateral_accel_deadzone: float, friction_compensation: bool) -> float:
|
||||
friction = get_friction(lateral_accel_error, lateral_accel_deadzone, FRICTION_THRESHOLD, torque_params, friction_compensation)
|
||||
|
||||
def sig(val):
|
||||
return 1 / (1 + exp(-val)) - 0.5
|
||||
|
||||
# The "lat_accel vs torque" relationship is assumed to be the sum of "sigmoid + linear" curves
|
||||
# An important thing to consider is that the slope at 0 should be > 0 (ideally >1)
|
||||
# This has big effect on the stability about 0 (noise when going straight)
|
||||
# ToDo: To generalize to other GMs, explore tanh function as the nonlinear
|
||||
a, b, c, _ = [2.6531724862969748, 1.0, 0.1919764879840985, 0.009054123646805178] # weights computed offline
|
||||
|
||||
steer_torque = (sig(lateral_accel_value * a) * b) + (lateral_accel_value * c)
|
||||
return float(steer_torque) + friction
|
||||
|
||||
def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType:
|
||||
if self.CP.carFingerprint == CAR.BOLT_EUV:
|
||||
return self.torque_from_lateral_accel_bolt
|
||||
else:
|
||||
return self.torque_from_lateral_accel_linear
|
||||
|
||||
@staticmethod
|
||||
def _get_params(ret, candidate, fingerprint, car_fw, experimental_long):
|
||||
ret.carName = "gm"
|
||||
|
||||
@@ -14,8 +14,8 @@ class CarControllerParams:
|
||||
STEER_STEP = 3 # Active control frames per command (~33hz)
|
||||
INACTIVE_STEER_STEP = 10 # Inactive control frames per command (10hz)
|
||||
STEER_DELTA_UP = 10 # Delta rates require review due to observed EPS weakness
|
||||
STEER_DELTA_DOWN = 25
|
||||
STEER_DRIVER_ALLOWANCE = 50
|
||||
STEER_DELTA_DOWN = 15
|
||||
STEER_DRIVER_ALLOWANCE = 65
|
||||
STEER_DRIVER_MULTIPLIER = 4
|
||||
STEER_DRIVER_FACTOR = 100
|
||||
NEAR_STOP_BRAKE_PHASE = 0.5 # m/s
|
||||
|
||||
@@ -8,10 +8,10 @@ from cereal import car
|
||||
from common.basedir import BASEDIR
|
||||
from common.conversions import Conversions as CV
|
||||
from common.kalman.simple_kalman import KF1D
|
||||
from common.numpy_fast import clip, interp
|
||||
from common.numpy_fast import clip
|
||||
from common.realtime import DT_CTRL
|
||||
from selfdrive.car import apply_hysteresis, gen_empty_fingerprint, scale_rot_inertia, scale_tire_stiffness
|
||||
from selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, apply_center_deadzone
|
||||
from selfdrive.controls.lib.drive_helpers import V_CRUISE_MAX, get_friction
|
||||
from selfdrive.controls.lib.events import Events
|
||||
from selfdrive.controls.lib.vehicle_model import VehicleModel
|
||||
|
||||
@@ -131,15 +131,11 @@ class CarInterfaceBase(ABC):
|
||||
return self.get_steer_feedforward_default
|
||||
|
||||
@staticmethod
|
||||
def torque_from_lateral_accel_linear(lateral_accel_value, torque_params, lateral_accel_error, lateral_accel_deadzone, friction_compensation):
|
||||
def torque_from_lateral_accel_linear(lateral_accel_value: float, torque_params: car.CarParams.LateralTorqueTuning,
|
||||
lateral_accel_error: float, lateral_accel_deadzone: float, friction_compensation: bool) -> float:
|
||||
# The default is a linear relationship between torque and lateral acceleration (accounting for road roll and steering friction)
|
||||
friction_interp = interp(
|
||||
apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone),
|
||||
[-FRICTION_THRESHOLD, FRICTION_THRESHOLD],
|
||||
[-torque_params.friction, torque_params.friction]
|
||||
)
|
||||
friction = friction_interp if friction_compensation else 0.0
|
||||
return (lateral_accel_value / torque_params.latAccelFactor) + friction
|
||||
friction = get_friction(lateral_accel_error, lateral_accel_deadzone, FRICTION_THRESHOLD, torque_params, friction_compensation)
|
||||
return (lateral_accel_value / float(torque_params.latAccelFactor)) + friction
|
||||
|
||||
def torque_from_lateral_accel(self) -> TorqueFromLateralAccelCallbackType:
|
||||
return self.torque_from_lateral_accel_linear
|
||||
|
||||
@@ -190,3 +190,13 @@ def get_lag_adjusted_curvature(CP, v_ego, psis, curvatures, curvature_rates):
|
||||
current_curvature_desired + max_curvature_rate * DT_MDL)
|
||||
|
||||
return safe_desired_curvature, safe_desired_curvature_rate
|
||||
|
||||
|
||||
def get_friction(lateral_accel_error: float, lateral_accel_deadzone: float, friction_threshold: float, torque_params: car.CarParams.LateralTorqueTuning, friction_compensation: bool) -> float:
|
||||
friction_interp = interp(
|
||||
apply_center_deadzone(lateral_accel_error, lateral_accel_deadzone),
|
||||
[-friction_threshold, friction_threshold],
|
||||
[-torque_params.friction, torque_params.friction]
|
||||
)
|
||||
friction = float(friction_interp) if friction_compensation else 0.0
|
||||
return friction
|
||||
|
||||
@@ -61,10 +61,12 @@ class LatControlTorque(LatControl):
|
||||
low_speed_factor = interp(CS.vEgo, LOW_SPEED_X, LOW_SPEED_Y)**2
|
||||
setpoint = desired_lateral_accel + low_speed_factor * desired_curvature
|
||||
measurement = actual_lateral_accel + low_speed_factor * actual_curvature
|
||||
error = setpoint - measurement
|
||||
gravity_adjusted_lateral_accel = desired_lateral_accel - params.roll * ACCELERATION_DUE_TO_GRAVITY
|
||||
pid_log.error = self.torque_from_lateral_accel(error, self.torque_params, error,
|
||||
torque_from_setpoint = self.torque_from_lateral_accel(setpoint, self.torque_params, setpoint,
|
||||
lateral_accel_deadzone, friction_compensation=False)
|
||||
torque_from_measurement = self.torque_from_lateral_accel(measurement, self.torque_params, measurement,
|
||||
lateral_accel_deadzone, friction_compensation=False)
|
||||
pid_log.error = torque_from_setpoint - torque_from_measurement
|
||||
ff = self.torque_from_lateral_accel(gravity_adjusted_lateral_accel, self.torque_params,
|
||||
desired_lateral_accel - actual_lateral_accel,
|
||||
lateral_accel_deadzone, friction_compensation=True)
|
||||
|
||||
@@ -1 +1 @@
|
||||
50f1e873095fe2462d2aadb9c401bda76759c01c
|
||||
1da098f096cee9f2871dafd2788dc9ddac85eeab
|
||||
Reference in New Issue
Block a user