Mirrors the live CC autopilot (computer 0) and cockpit (computer 4) from the Modda wii world. install.lua fetches each role's manifest over HTTP so the system installs on any server regardless of computer id. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
47 lines
2.2 KiB
Lua
47 lines
2.2 KiB
Lua
-- pitch.lua (§8) -- PD paa MAALT pitch + TREG INTEGRAL-TRIM (self-learning differanse-trim).
|
|
-- PD-leddet demper/retter transienter; integral-leddet LAERER den varige differanse-trimmen som
|
|
-- holder pitch = 0 paa ETHVERT skip, og re-laerer naar du legger paa vekt. Speiler observerens
|
|
-- bias (som gjor det samme for felles-modus/hover). Ingen skip-spesifikke konstanter her.
|
|
--
|
|
-- VIKTIG: integratoren gjor pitchGain-STORRELSEN nesten irrelevant for steady-state (en integrator
|
|
-- driver utgangen til det som nuller feilen uansett forsterkning). KUN pitchSign maa stemme
|
|
-- (maales av sign test / kalibrering). Med feil fortegn drar baade P og I feil vei.
|
|
|
|
local utils = require("utils")
|
|
|
|
local M = {}
|
|
local Pitch = {}
|
|
Pitch.__index = Pitch
|
|
|
|
-- calib: { pitchSign, pitchGain, pitchTrim? } (pitchTrim = warm-start av laert trim, valgfritt)
|
|
function M.new(cfg, calib)
|
|
return setmetatable({
|
|
cfg = cfg, calib = calib,
|
|
iTrim = calib.pitchTrim or 0, -- laert differanse-trim (D_des-enheter), varmstart fra calib
|
|
}, Pitch)
|
|
end
|
|
|
|
-- pitch/pitchRate: MAALT. dt: faktisk steg (s). saturated: mixeren klemte en utgang (anti-windup
|
|
-- -> frys integralet). Returnerer u_diff (>0 => mer foran) + diag.
|
|
function Pitch:compute(pitch, pitchRate, dt, saturated)
|
|
local cfg, calib = self.cfg, self.calib
|
|
local pitchError = 0 - pitch -- TARGET_PITCH = 0
|
|
local pitchGain = math.max(0.05, calib.pitchGain)
|
|
|
|
-- TREG INTEGRAL-TRIM (self-learning). Frys ved metning (anti-windup) og under raske transienter
|
|
-- (ikke integrer oversving/stoy -- la PD settle foerst). Akkumulerer i D_des-enheter, fortegns-
|
|
-- korrigert slik at den drar i RIKTIG retning for skipets maalte pitchSign.
|
|
if dt > 0 and not saturated and math.abs(pitchRate) < cfg.iPitchRateGate then
|
|
self.iTrim = utils.clamp(
|
|
self.iTrim + cfg.Ki_p * calib.pitchSign * pitchError * dt,
|
|
-cfg.iPitchMax, cfg.iPitchMax)
|
|
end
|
|
|
|
-- PD (transient) + integral-trim (steady). Alt i "onsket differanse-loft"-enheter (D_des).
|
|
local D_des = calib.pitchSign * (cfg.Kp_p * pitchError - cfg.Kd_p * pitchRate) + self.iTrim
|
|
local u_diff = D_des / pitchGain
|
|
return u_diff, { pitchError = pitchError, D_des = D_des, iTrim = self.iTrim }
|
|
end
|
|
|
|
return M
|