diff --git a/MyGamepadFX/assist.lua b/MyGamepadFX/assist.lua index 6f644a4..c07503d 100644 --- a/MyGamepadFX/assist.lua +++ b/MyGamepadFX/assist.lua @@ -1,6 +1,6 @@ -- assist.lua — pipeline assembly and CSP entry points -- Pipeline (execution order): --- raw input → deadzone/gamma → speed scale → slip limit (driver only) → + self-steer → smooth → clamp → output +-- raw input → calibrate → deadzone/gamma → speed scale → slip limit (driver only) → + self-steer → smooth → clamp → output local CFG = require('config') local lib = require('lib') @@ -18,6 +18,12 @@ local liveCfgTimer = 0.5 -- start first check after 0.5s to avoid startup nois local function applyLiveCfg() local ok, ini = pcall(ac.INIConfig.load, LIVE_CFG_PATH) if not ok or not ini then return end + CFG.STEER_CENTER = ini:get('PARAMS', 'STEER_CENTER', CFG.STEER_CENTER) + CFG.STEER_RANGE = ini:get('PARAMS', 'STEER_RANGE', CFG.STEER_RANGE) + CFG.GAS_REST = ini:get('PARAMS', 'GAS_REST', CFG.GAS_REST) + CFG.GAS_MAX = ini:get('PARAMS', 'GAS_MAX', CFG.GAS_MAX) + CFG.BRAKE_REST = ini:get('PARAMS', 'BRAKE_REST', CFG.BRAKE_REST) + CFG.BRAKE_MAX = ini:get('PARAMS', 'BRAKE_MAX', CFG.BRAKE_MAX) CFG.DEADZONE = ini:get('PARAMS', 'DEADZONE', CFG.DEADZONE) CFG.GAMMA = ini:get('PARAMS', 'GAMMA', CFG.GAMMA) CFG.STEER_SMOOTH = ini:get('PARAMS', 'STEER_SMOOTH', CFG.STEER_SMOOTH) @@ -83,9 +89,10 @@ function script.update(dt) firstFrameDiagnostics = true end - -- 1. Raw input → deadzone → gamma → speed scale - local raw = gamepad.axes[1] or 0.0 -- left stick X (steering) - local steer = lib.applyGamma(lib.applyDeadzone(raw, CFG.DEADZONE), CFG.GAMMA) + -- 1. Raw input → calibrate → deadzone → gamma → speed scale + local raw = gamepad.axes[1] or 0.0 -- left stick X (steering) + local calibrated = lib.normalizeAxis(raw, CFG.STEER_CENTER, CFG.STEER_RANGE) + local steer = lib.applyGamma(lib.applyDeadzone(calibrated, CFG.DEADZONE), CFG.GAMMA) steer = steer * lib.speedScale(car.speedKmh, CFG) -- 2. Slip limit — clamps driver input only; self-steer is added after @@ -129,9 +136,11 @@ function script.update(dt) end -- 5. Write to physics + local rawGas = lib.normalizeTrigger(gamepad.axes[3] or 0.0, CFG.GAS_REST, CFG.GAS_MAX) + local rawBrake = lib.normalizeTrigger(gamepad.axes[4] or 0.0, CFG.BRAKE_REST, CFG.BRAKE_MAX) ac.setSteer(math.clamp(steerOut, -1.0, 1.0)) - ac.setGas( math.clamp(lib.applyGamma(lib.applyDeadzone(gamepad.axes[3] or 0.0, CFG.GAS_DEADZONE), CFG.GAS_GAMMA), 0.0, 1.0)) - ac.setBrake(math.clamp(lib.applyGamma(lib.applyDeadzone(gamepad.axes[4] or 0.0, CFG.BRAKE_DEADZONE), CFG.BRAKE_GAMMA), 0.0, 1.0)) + ac.setGas( math.clamp(lib.applyGamma(lib.applyDeadzone(rawGas, CFG.GAS_DEADZONE), CFG.GAS_GAMMA), 0.0, 1.0)) + ac.setBrake(math.clamp(lib.applyGamma(lib.applyDeadzone(rawBrake, CFG.BRAKE_DEADZONE), CFG.BRAKE_GAMMA), 0.0, 1.0)) end function script.reset() diff --git a/MyGamepadFX/config.lua b/MyGamepadFX/config.lua index 05baaca..c11dcfd 100644 --- a/MyGamepadFX/config.lua +++ b/MyGamepadFX/config.lua @@ -1,5 +1,14 @@ -- config.lua — all tunable constants; no logic lives here local CFG = { + -- Axis calibration (Hall Effect controllers) + -- Defaults produce no change from v1.0 behaviour. + STEER_CENTER = 0.0, -- raw stick value at rest; subtracted before deadzone + STEER_RANGE = 1.0, -- max raw deflection from center (scale to ±1.0) + GAS_REST = 0.0, -- raw trigger value when fully released + GAS_MAX = 1.0, -- raw trigger value when fully pressed + BRAKE_REST = 0.0, -- raw trigger value when fully released + BRAKE_MAX = 1.0, -- raw trigger value when fully pressed + -- Deadzone & curve DEADZONE = 0.08, -- stick deadzone radius GAMMA = 1.6, -- steering curve exponent (>1 = more center precision) diff --git a/MyGamepadFX/lib.lua b/MyGamepadFX/lib.lua index 8c9a019..89e8f23 100644 --- a/MyGamepadFX/lib.lua +++ b/MyGamepadFX/lib.lua @@ -11,6 +11,21 @@ function M.logOnce(key, message) end end +-- Normalise a symmetric axis (stick) given its rest offset and physical range. +-- Output is clamped to [-1, 1]. With center=0, range=1 this is an identity. +function M.normalizeAxis(raw, center, range) + if range == 0 then return 0.0 end + return math.clamp((raw - center) / range, -1.0, 1.0) +end + +-- Normalise a unipolar axis (trigger) given rest and max raw values. +-- Output is clamped to [0, 1]. With rest=0, maxVal=1 this is an identity. +function M.normalizeTrigger(raw, rest, maxVal) + local span = maxVal - rest + if span <= 0 then return 0.0 end + return math.clamp((raw - rest) / span, 0.0, 1.0) +end + -- Deadzone with rescale: removes drift and maps the remaining range to [0,1] -- with no discontinuity at the deadzone edge. function M.applyDeadzone(v, dz) diff --git a/MyGamepadFX_Config/app.lua b/MyGamepadFX_Config/app.lua index 93ff38c..1afdf1d 100644 --- a/MyGamepadFX_Config/app.lua +++ b/MyGamepadFX_Config/app.lua @@ -12,6 +12,12 @@ local LIVE_CFG_PATH = ac.getFolder(ac.FolderID.ExtLua) .. '/joypad-assist/MyGame -- Defaults mirror config.lua — used when no saved file exists yet local cfg = { + STEER_CENTER = 0.0, + STEER_RANGE = 1.0, + GAS_REST = 0.0, + GAS_MAX = 1.0, + BRAKE_REST = 0.0, + BRAKE_MAX = 1.0, DEADZONE = 0.08, GAMMA = 1.6, STEER_SMOOTH = 0.12, @@ -40,6 +46,12 @@ local saveTimer = 0 local function saveLiveCfg() local ok, err = pcall(function() local ini = ac.INIConfig.load(LIVE_CFG_PATH) + ini:set('PARAMS', 'STEER_CENTER', cfg.STEER_CENTER) + ini:set('PARAMS', 'STEER_RANGE', cfg.STEER_RANGE) + ini:set('PARAMS', 'GAS_REST', cfg.GAS_REST) + ini:set('PARAMS', 'GAS_MAX', cfg.GAS_MAX) + ini:set('PARAMS', 'BRAKE_REST', cfg.BRAKE_REST) + ini:set('PARAMS', 'BRAKE_MAX', cfg.BRAKE_MAX) ini:set('PARAMS', 'DEADZONE', cfg.DEADZONE) ini:set('PARAMS', 'GAMMA', cfg.GAMMA) ini:set('PARAMS', 'STEER_SMOOTH', cfg.STEER_SMOOTH) @@ -70,6 +82,12 @@ end local function loadSaved() local ok, ini = pcall(ac.INIConfig.load, LIVE_CFG_PATH) if not ok or not ini then return end + cfg.STEER_CENTER = ini:get('PARAMS', 'STEER_CENTER', cfg.STEER_CENTER) + cfg.STEER_RANGE = ini:get('PARAMS', 'STEER_RANGE', cfg.STEER_RANGE) + cfg.GAS_REST = ini:get('PARAMS', 'GAS_REST', cfg.GAS_REST) + cfg.GAS_MAX = ini:get('PARAMS', 'GAS_MAX', cfg.GAS_MAX) + cfg.BRAKE_REST = ini:get('PARAMS', 'BRAKE_REST', cfg.BRAKE_REST) + cfg.BRAKE_MAX = ini:get('PARAMS', 'BRAKE_MAX', cfg.BRAKE_MAX) cfg.DEADZONE = ini:get('PARAMS', 'DEADZONE', cfg.DEADZONE) cfg.GAMMA = ini:get('PARAMS', 'GAMMA', cfg.GAMMA) cfg.STEER_SMOOTH = ini:get('PARAMS', 'STEER_SMOOTH', cfg.STEER_SMOOTH) @@ -112,6 +130,16 @@ function windowMain(dt) end saveTimer = saveTimer - dt + ui.text('Calibration') + ui.separator() + sliderRow('Stick center', 'STEER_CENTER', -0.10, 0.10, '%.3f') + sliderRow('Stick range', 'STEER_RANGE', 0.80, 1.00, '%.3f') + sliderRow('Gas rest', 'GAS_REST', 0.00, 0.10, '%.3f') + sliderRow('Gas max', 'GAS_MAX', 0.90, 1.00, '%.3f') + sliderRow('Brake rest', 'BRAKE_REST', 0.00, 0.10, '%.3f') + sliderRow('Brake max', 'BRAKE_MAX', 0.90, 1.00, '%.3f') + + ui.offsetCursorY(8) ui.text('Steering') ui.separator() sliderRow('Deadzone', 'DEADZONE', 0.0, 0.30, '%.2f') diff --git a/MyGamepadFX_Config/manifest.ini b/MyGamepadFX_Config/manifest.ini index 66bcd90..7f453ad 100644 --- a/MyGamepadFX_Config/manifest.ini +++ b/MyGamepadFX_Config/manifest.ini @@ -1,12 +1,10 @@ [ABOUT] NAME = MyGamepadFX Config AUTHOR = rolling-codes -VERSION = 1.0 - +VERSION = 1.1 [CORE] LAZY = FULL - [WINDOW_MAIN] ID = main FUNCTION_MAIN = windowMain -SIZE = 380, 680 +SIZE = 380, 800