Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
88 commits
Select commit Hold shift + click to select a range
42c98d6
2025-26 gv80/gv80 coupe init
sunnyhaibin Mar 26, 2026
37d100d
Merge branch 'master' into gv80-2025
sunnyhaibin Mar 26, 2026
7ab9364
update them manually
sunnyhaibin Mar 26, 2026
745d32e
dbc
sunnyhaibin Mar 26, 2026
f835a71
Merge remote-tracking branch 'sunnypilot/opendbc/gv80-2025' into gv80…
sunnyhaibin Mar 26, 2026
cfc8649
more
sunnyhaibin Mar 26, 2026
d555422
more
sunnyhaibin Mar 26, 2026
07fbf00
more
sunnyhaibin Mar 26, 2026
0d5e62d
fix
sunnyhaibin Mar 26, 2026
af31fc3
small fixes
sunnyhaibin Mar 27, 2026
c92883e
no
sunnyhaibin Mar 27, 2026
1477eef
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
sunnyhaibin Mar 27, 2026
c24b917
not this one
sunnyhaibin Mar 27, 2026
18303a1
better?
sunnyhaibin Mar 27, 2026
40bb5cc
new parameterized
sunnyhaibin Mar 28, 2026
a593957
more
sunnyhaibin Mar 28, 2026
6fd7354
more
sunnyhaibin Mar 28, 2026
3302ad9
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
sunnyhaibin Mar 28, 2026
4e69afd
Update fingerprints.py
royjr Mar 28, 2026
cc26bae
Merge branch 'master' into gv80-2025
royjr Mar 28, 2026
2fb5784
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
sunnyhaibin Mar 28, 2026
8f8cbf2
fix
sunnyhaibin Mar 28, 2026
42cb0b7
new route
sunnyhaibin Mar 28, 2026
953a7b4
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
sunnyhaibin Mar 28, 2026
ce9b040
Merge branch 'master' into gv80-2025
sunnyhaibin Mar 28, 2026
8be9d7c
new harness
sunnyhaibin Mar 28, 2026
71cd2bf
no json hehe
sunnyhaibin Mar 28, 2026
8fa43d9
more
sunnyhaibin Mar 28, 2026
338a82f
bump steer threshold to 250
sunnyhaibin Mar 28, 2026
2080542
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
sunnyhaibin Mar 28, 2026
f313acd
try this out
sunnyhaibin Mar 28, 2026
1863512
fix
sunnyhaibin Mar 28, 2026
4cf852d
test fix
sunnyhaibin Mar 28, 2026
53556e8
update torque reduction gain logic and parameters
sunnyhaibin Mar 28, 2026
e588db6
different ramp up and down
sunnyhaibin Mar 28, 2026
32b5d41
ignore road noise
sunnyhaibin Mar 28, 2026
c317232
separate gains
sunnyhaibin Mar 28, 2026
55fbcdd
Revert "separate gains"
sunnyhaibin Mar 28, 2026
2dc40c1
Revert "ignore road noise"
sunnyhaibin Mar 28, 2026
2f9b492
Revert "different ramp up and down"
sunnyhaibin Mar 28, 2026
f484cbf
Revert "update torque reduction gain logic and parameters"
sunnyhaibin Mar 28, 2026
0d1ac6c
Revert "test fix"
sunnyhaibin Mar 28, 2026
ad84956
Revert "fix"
sunnyhaibin Mar 28, 2026
8bb2720
Revert "try this out"
sunnyhaibin Mar 28, 2026
9cffacc
don't do this
sunnyhaibin Mar 28, 2026
5e36ac0
Merge branch 'master' into gv80-2025
sunnyhaibin Mar 28, 2026
e413ea3
slight cleanup
sunnyhaibin Mar 28, 2026
f1afb32
Revert "no json hehe"
sunnyhaibin Mar 28, 2026
331ed02
Revert "more"
sunnyhaibin Mar 28, 2026
16f0853
add angle smoothing factor for now for live tuning
sunnyhaibin Mar 28, 2026
1c5617b
add ramp up/down for live tuning
sunnyhaibin Mar 28, 2026
41d26f8
gain based EPS force control
sunnyhaibin Mar 28, 2026
9e677f8
Revert "slight cleanup"
sunnyhaibin Mar 28, 2026
083518d
mdps angle just angle steering for now
sunnyhaibin Mar 28, 2026
2e0d5a2
adjust override factor and dangle handling for smoother EPS control
sunnyhaibin Mar 28, 2026
dc8d41b
refine dangle handling with adjusted breakpoints and added winding logic
sunnyhaibin Mar 28, 2026
4bde0d7
update speed-based EPS gain ceiling and override factor for improved …
sunnyhaibin Mar 28, 2026
dd67aee
implement error-based EPS gain scaling with updated breakpoints for i…
sunnyhaibin Mar 28, 2026
f6926d8
todo
sunnyhaibin Mar 28, 2026
acd8e77
revert
sunnyhaibin Mar 28, 2026
f87d5fd
Revert "revert"
sunnyhaibin Mar 28, 2026
ab8543d
Revert "implement error-based EPS gain scaling with updated breakpoin…
sunnyhaibin Mar 28, 2026
ef3f455
new smoothing
sunnyhaibin Mar 28, 2026
48149a5
Merge branch 'master' into gv80-2025
sunnyhaibin Mar 29, 2026
06e5874
interface cleanup
sunnyhaibin Mar 29, 2026
e10bfd2
Merge remote-tracking branch 'sunnypilot/opendbc/gv80-2025' into gv80…
sunnyhaibin Mar 29, 2026
9d6df3a
safety: torque reduction gain sanity check
sunnyhaibin Mar 29, 2026
4a9689b
refine low-speed angle smoothing logic to reduce EPS noise
sunnyhaibin Mar 29, 2026
808966e
code review suggestions
sunnyhaibin Mar 29, 2026
0d74b9c
Merge branch 'master' into gv80-2025
sunnyhaibin Mar 29, 2026
92dac6e
no ev yet
sunnyhaibin Mar 29, 2026
a386849
refine low-speed angle smoothing breakpoints for improved EPS behavior
sunnyhaibin Mar 29, 2026
e9e83d7
360 and tests
sunnyhaibin Mar 29, 2026
5a2d1ae
refine low-speed smoothing logic to reduce EPS jitter and overshoot
sunnyhaibin Mar 29, 2026
6904a8c
steer limit by safety for hyundai and round incoming desired angle to…
sunnyhaibin Mar 29, 2026
67c7703
needs to be 360
sunnyhaibin Mar 29, 2026
8e3d9bd
s0mple
sshane Mar 29, 2026
0044e2b
rate limit
sshane Mar 29, 2026
d72b018
compute_torque_reduction_gain
sshane Mar 29, 2026
00fd615
testing
Mar 30, 2026
886f79d
best fit
sshane Mar 30, 2026
fd38b08
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
Mar 31, 2026
2886019
unused
Mar 31, 2026
17f1f21
Merge remote-tracking branch 'commaai/opendbc/master' into gv80-2025
Apr 2, 2026
d934a1e
update name
Apr 2, 2026
a937e6a
ruff
Apr 2, 2026
699c170
should be 1
Apr 2, 2026
d0c76cb
signed
Apr 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
119 changes: 102 additions & 17 deletions opendbc/car/hyundai/carcontroller.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
import numpy as np
from opendbc.car.vehicle_model import VehicleModel
from opendbc.car.common.filter_simple import FirstOrderFilter
from opendbc.can import CANPacker
from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs
from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance
from opendbc.car import Bus, DT_CTRL, make_tester_present_msg, structs, apply_hysteresis # , rate_limit
from opendbc.car.lateral import apply_driver_steer_torque_limits, common_fault_avoidance, apply_steer_angle_limits_vm
from opendbc.car.common.conversions import Conversions as CV
from opendbc.car.hyundai import hyundaicanfd, hyundaican
from opendbc.car.hyundai.hyundaicanfd import CanBus
from opendbc.car.hyundai.values import HyundaiFlags, Buttons, CarControllerParams, CAR
from opendbc.car.interfaces import CarControllerBase
from opendbc.car.hyundai.torque_reduction_gain import TorqueReductionGainController

VisualAlert = structs.CarControl.HUDControl.VisualAlert
LongCtrlState = structs.CarControl.Actuators.LongControlState
Expand All @@ -17,6 +20,13 @@
MAX_ANGLE_FRAMES = 89
MAX_ANGLE_CONSECUTIVE_FRAMES = 2

ANGLE_SAFETY_BASELINE_MODEL = "GENESIS_GV80_2025"


def get_baseline_safety_cp():
from opendbc.car.hyundai.interface import CarInterface
return CarInterface.get_non_essential_params(ANGLE_SAFETY_BASELINE_MODEL)


def process_hud_alert(enabled, fingerprint, hud_control):
sys_warning = (hud_control.visualAlert in (VisualAlert.steerRequired, VisualAlert.ldw))
Expand All @@ -42,38 +52,111 @@ def process_hud_alert(enabled, fingerprint, hud_control):
return sys_warning, sys_state, left_lane_warning, right_lane_warning


def compute_torque_reduction_gain(steering_torque, v_ego_kph, lat_active, last_gain):
if lat_active:
ceiling = np.interp(v_ego_kph, [40, 120], [0.85, 1.0])
target = np.interp(abs(steering_torque), [140, 420], [ceiling, 0.19])
else:
target = 0.0
delta = target - last_gain
rate_dn = np.interp(abs(steering_torque), [0, 300, 700], [0.004, 0.01, 0.04])
gain = last_gain + max(-rate_dn, min(0.004, delta))
return round(gain / 0.004) * 0.004


class CarController(CarControllerBase):
def __init__(self, dbc_names, CP):
super().__init__(dbc_names, CP)
self.CAN = CanBus(CP)
self.params = CarControllerParams(CP)
self.packer = CANPacker(dbc_names[Bus.pt])
self.angle_limit_counter = 0
self.angle_filter = FirstOrderFilter(0.0, 0.1, 0.01)
self.angle_steady = 0

self.accel_last = 0
self.apply_torque_last = 0
self.car_fingerprint = CP.carFingerprint
self.last_button_frame = 0

self.apply_angle_last = 0

# Vehicle model used for angle steering lateral limiting
self.VM = VehicleModel(get_baseline_safety_cp())

self.torque_reduction_gain_controller = TorqueReductionGainController()

def update(self, CC, CS, now_nanos):
actuators = CC.actuators
hud_control = CC.hudControl
torque_fault = False

# angle control
if self.CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
# desired_angle = round(actuators.steeringAngleDeg, 1)
desired_angle = actuators.steeringAngleDeg

# Smooth micro-adjustments that cause EPS whine at low speed.
# The model produces ~0.2-0.4°/frame jitter vs stock's ~0.05°. The EPS PID
# overshoots tracking these rapid changes, causing motor direction reversals
# at audible frequencies. Smoothing reduces the jitter to stock levels.
# Skip smoothing for large angle changes (>1°) — those are real steering
# maneuvers, not jitter, and should execute immediately.
# delta = abs(desired_angle - self.apply_angle_last)
# if CC.latActive and 0.05 < delta < 1.0:
# alpha = np.interp(abs(CS.out.vEgoRaw), [0, 2.8, 5.6, 8.3, 11.1, 13.9], [0.15, 0.20, 0.25, 0.35, 0.55, 1.0])
# desired_angle = float(desired_angle * alpha + self.apply_angle_last * (1 - alpha))

if CC.latActive:
#print(apply_angle_last, self.apply_angle_last)
print(desired_angle, self.angle_steady)
deadzone = np.interp(CS.out.vEgo, [10, 15], [3, 0])
desired_angle = apply_hysteresis(desired_angle, self.angle_steady, deadzone)
#desired_angle = self.angle_filter.update(desired_angle)
#print('after', apply_angle_last)
print('after', desired_angle)
self.angle_steady = desired_angle
#print()

self.apply_angle_last = apply_steer_angle_limits_vm(desired_angle, self.apply_angle_last,
CS.out.vEgoRaw, CS.out.steeringAngleDeg,
CC.latActive, self.params, self.VM)

# apply_torque = self.torque_reduction_gain_controller.update(
# CS.out.steeringPressed, CC.latActive, CS.out.vEgoRaw)
# TODO: consider angle direction so you can override in direction and it doesn't reduce torque as much
# TODO: max_allowed_torque
# apply_torque = np.interp(abs(CS.out.steeringTorque), [0, 500], [1.0, 0.2]) if CC.latActive else 0.0
# apply_torque = rate_limit(apply_torque, self.apply_torque_last, -0.012, 0.002) # try 0.004, that's stock
apply_torque = compute_torque_reduction_gain(CS.out.steeringTorque, CS.out.vEgoRaw * CV.MS_TO_KPH,
CC.latActive, self.apply_torque_last)
#self.apply_angle_last = apply_angle_last_tmp
#self.angle_steady = self.apply_angle_last

#self.apply

#self.angle_steady = self.apply_angle_last

apply_steer_req = CC.latActive
if not CC.latActive:
self.angle_filter.x = CS.out.steeringAngleDeg
self.angle_steady = CS.out.steeringAngleDeg
self.apply_angle_last = CS.out.steeringAngleDeg

# torque control
else:
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
self.angle_limit_counter, MAX_ANGLE_FRAMES,
MAX_ANGLE_CONSECUTIVE_FRAMES)
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params)

# steering torque
new_torque = int(round(actuators.torque * self.params.STEER_MAX))
apply_torque = apply_driver_steer_torque_limits(new_torque, self.apply_torque_last, CS.out.steeringTorque, self.params)

# >90 degree steering fault prevention
self.angle_limit_counter, apply_steer_req = common_fault_avoidance(abs(CS.out.steeringAngleDeg) >= MAX_ANGLE, CC.latActive,
self.angle_limit_counter, MAX_ANGLE_FRAMES,
MAX_ANGLE_CONSECUTIVE_FRAMES)

if not CC.latActive:
apply_torque = 0
if not CC.latActive:
apply_torque = 0

# Hold torque with induced temporary fault when cutting the actuation bit
# FIXME: we don't use this with CAN FD?
torque_fault = CC.latActive and not apply_steer_req
# Hold torque with induced temporary fault when cutting the actuation bit
# FIXME: we don't use this with CAN FD?
torque_fault = CC.latActive and not apply_steer_req

self.apply_torque_last = apply_torque

Expand Down Expand Up @@ -109,6 +192,7 @@ def update(self, CC, CS, now_nanos):
new_actuators = actuators.as_builder()
new_actuators.torque = apply_torque / self.params.STEER_MAX
new_actuators.torqueOutputCan = apply_torque
new_actuators.steeringAngleDeg = self.apply_angle_last
new_actuators.accel = accel

self.frame += 1
Expand Down Expand Up @@ -167,7 +251,8 @@ def create_canfd_msgs(self, apply_steer_req, apply_torque, set_speed_in_units, a
lka_steering_long = lka_steering and self.CP.openpilotLongitudinalControl

# steering control
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req, apply_torque))
can_sends.extend(hyundaicanfd.create_steering_messages(self.packer, self.CP, self.CAN, CC.enabled, apply_steer_req,
apply_torque, self.apply_angle_last))

# prevent LFA from activating on LKA steering cars by sending "no lane lines detected" to ADAS ECU
if self.frame % 5 == 0 and lka_steering:
Expand Down
12 changes: 9 additions & 3 deletions opendbc/car/hyundai/carstate.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ def __init__(self, CP):
self.cluster_speed_counter = CLUSTER_SAMPLE_RATE

self.params = CarControllerParams(CP)
self.is_canfd_angle_steering = CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING

def recent_button_interaction(self) -> bool:
# On some newer model years, the CANCEL button acts as a pause/resume button based on the PCM state
Expand Down Expand Up @@ -237,15 +238,20 @@ def update_canfd(self, can_parsers) -> structs.CarState:
cp.vl["WHEEL_SPEEDS"]["WHL_SpdRLVal"] <= STANDSTILL_THRESHOLD and cp.vl["WHEEL_SPEEDS"]["WHL_SpdRRVal"] <= STANDSTILL_THRESHOLD

ret.steeringRateDeg = cp.vl["STEERING_SENSORS"]["STEERING_RATE"]
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"]
ret.steeringTorque = cp.vl["MDPS"]["MDPS_StrTqSnsrVal"]
ret.steeringTorqueEps = cp.vl["MDPS"]["MDPS_OutTqVal"]
ret.steeringPressed = self.update_steering_pressed(abs(ret.steeringTorque) > self.params.STEER_THRESHOLD, 5)
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0

if self.is_canfd_angle_steering:
ret.steeringAngleDeg = cp.vl["MDPS"]["MDPS_EstStrAnglVal"]
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0 or cp.vl["MDPS"]["MDPS_ADAS_AciFltSig_Lv2"] != 0
else:
ret.steeringAngleDeg = cp.vl["STEERING_SENSORS"]["STEERING_ANGLE"]
ret.steerFaultTemporary = cp.vl["MDPS"]["MDPS_LkaFailSta"] != 0

# TODO: alt signal usage may be described by cp.vl['BLINKERS']['USE_ALT_LAMP']
left_blinker_sig, right_blinker_sig = "LEFT_LAMP", "RIGHT_LAMP"
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN:
if self.CP.carFingerprint == CAR.HYUNDAI_KONA_EV_2ND_GEN or self.is_canfd_angle_steering:
left_blinker_sig, right_blinker_sig = "LEFT_LAMP_ALT", "RIGHT_LAMP_ALT"
ret.leftBlinker, ret.rightBlinker = self.update_blinker_from_lamp(50, cp.vl["BLINKERS"][left_blinker_sig],
cp.vl["BLINKERS"][right_blinker_sig])
Expand Down
9 changes: 9 additions & 0 deletions opendbc/car/hyundai/fingerprints.py
Original file line number Diff line number Diff line change
Expand Up @@ -1295,4 +1295,13 @@
b'\xf1\x00T01G00BL T01I00A1 DOS2T16X4XI00NS0\x99L\xeeq',
],
},
CAR.GENESIS_GV80_2025: {
(Ecu.fwdRadar, 0x7d0, None): [
b'\xf1\x00JX__ RDR ----- 1.00 1.03 99110-T6500 ',
],
(Ecu.fwdCamera, 0x7c4, None): [
b'\xf1\x00JX MFC AT USA LHD 1.00 1.03 99211-T6510 240124',
b'\xf1\x00JX MFC AT USA LHD 1.00 1.12 99211-T6600 250423',
],
},
}
17 changes: 15 additions & 2 deletions opendbc/car/hyundai/hyundaicanfd.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,31 @@ def CAM(self):
return self._cam


def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque):
def create_steering_messages(packer, CP, CAN, enabled, lat_active, apply_torque, apply_angle):
values = {
"LKA_OptUsmSta": 2,
"LKA_SysIndReq": 2 if enabled else 1,
"StrTqReqVal": apply_torque,
"LKA_SysWrn": 0,
"ActToiSta": 1 if lat_active else 0,
"LKA_UsmMod": 0, # hide LKAS settings
"LKA_RcgSta": 0,
"LKA_RcgSta": 0, # lane recognition status (0 for "not recognized")
"Damping_Gain": 100, # can potentially tuned for better perf [3, 200]
}

# Angle control doesn't support using LFA yet
if CP.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
# LKAS messages take priority over LFA messages on HDA2.
values |= {
"LKA_OptUsmSta": 0, # TODO: not used by the stock system
"StrTqReqVal": 0, # we don't use torque
"ActToiSta": 0, # we don't use torque
"LKA_RcgSta": 3 if lat_active else 0,
"ADAS_StrAnglReqVal": apply_angle,
"LKAS_ANGLE_ACTIVE": 2 if lat_active else 1,
"ADAS_ACIAnglTqRedcGainVal": apply_torque if lat_active else 0,
}

ret = []
if CP.flags & HyundaiFlags.CANFD_LKA_STEERING:
lkas_msg = "LKAS_ALT" if CP.flags & HyundaiFlags.CANFD_LKA_STEERING_ALT else "LKAS"
Expand Down
10 changes: 9 additions & 1 deletion opendbc/car/hyundai/interface.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_lo

ret.enableBsm = 0x1ba in fingerprint[CAN.ECAN]

# no longitudinal for all lka_steering angle steering
if lka_steering and ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
ret.alphaLongitudinalAvailable = False

# Check if the car is hybrid. Only HEV/PHEV cars have 0xFA on E-CAN.
if 0xFA in fingerprint[CAN.ECAN]:
ret.flags |= HyundaiFlags.HYBRID.value
Expand Down Expand Up @@ -80,6 +84,9 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_lo
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ALT_BUTTONS.value
if ret.flags & HyundaiFlags.CANFD_CAMERA_SCC:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CAMERA_SCC.value
if ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING:
ret.steerControlType = structs.CarParams.SteerControlType.angle
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.CANFD_ANGLE_STEERING.value

else:
# Shared configuration for non CAN-FD cars
Expand Down Expand Up @@ -112,7 +119,8 @@ def _get_params(ret: structs.CarParams, candidate, fingerprint, car_fw, alpha_lo
ret.centerToFront = ret.wheelbase * 0.4
ret.steerActuatorDelay = 0.1
ret.steerLimitTimer = 0.4
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)
if not (ret.flags & HyundaiFlags.CANFD_ANGLE_STEERING):
CarInterfaceBase.configure_torque_tune(candidate, ret.lateralTuning)

if ret.flags & HyundaiFlags.ALT_LIMITS:
ret.safetyConfigs[-1].safetyParam |= HyundaiSafetyFlags.ALT_LIMITS.value
Expand Down
50 changes: 50 additions & 0 deletions opendbc/car/hyundai/torque_reduction_gain.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import numpy as np
from opendbc.car.common.conversions import Conversions as CV


class TorqueReductionGainController:
"""
Controls the ADAS_ACIAnglTqRedcGainVal signal for HKG CAN-FD angle steering.

The gain controls how hard the EPS tries to track the commanded angle:
- Speed-dependent ceiling: higher at highway speed for precision,
lower at low speed to reduce EPS internal PID oscillation.
- Override: drops gain when steeringPressed for easy driver takeover.
- Smooth ramp: prevents sudden gain changes that jerk the steering.
"""

SPEED_BP = [0., 10., 30., 50., 80.] # km/h
SPEED_CEILING = [0.55, 0.55, 0.75, 0.90, 1.0]

OVERRIDE_FACTOR = 0.1

RAMP_RATE = 0.008
RECOVERY_RATE = 0.02
OVERRIDE_DROP_RATE = 0.05
Comment on lines +21 to +23
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
RAMP_RATE = 0.008
RECOVERY_RATE = 0.02
OVERRIDE_DROP_RATE = 0.05
RAMP_RATE = 0.008
RECOVERY_RATE = 0.02
OVERRIDE_DROP_RATE = 0.05

store in reduction per seconds, or just divide by steer step


def __init__(self):
self.gain = 0.0
self._was_overriding = False

def update(self, steering_pressed: bool, lat_active: bool, v_ego: float) -> float:
if not lat_active:
target = 0.0
self._was_overriding = False
else:
speed_kmh = v_ego * CV.MS_TO_KPH
ceiling = float(np.interp(speed_kmh, self.SPEED_BP, self.SPEED_CEILING))
target = ceiling * self.OVERRIDE_FACTOR if steering_pressed else ceiling

if steering_pressed:
self._was_overriding = True
elif self._was_overriding and lat_active and self.gain >= target - 0.001:
self._was_overriding = False

if target < self.gain:
rate = self.OVERRIDE_DROP_RATE if steering_pressed else self.RAMP_RATE
self.gain = max(self.gain - rate, target)
else:
rate = self.RECOVERY_RATE if self._was_overriding else self.RAMP_RATE
self.gain = min(self.gain + rate, target)

return self.gain
Loading
Loading