diff --git a/drone.lua b/drone.lua index d745bd7..19fb81d 100644 --- a/drone.lua +++ b/drone.lua @@ -130,6 +130,20 @@ local PARAMS = { pas = 0.5, mini = 0, maxi = 10 }, { chemin = "CALIB.ATTENTE_NIVEAU", label = "attente calib mot. (s)", pas = 0.5, mini = 0.5, maxi = 5 }, + { chemin = "ASSIETTE_PLAFOND", label = "autorite assiette", + pas = 0.05, mini = 0.05, maxi = 1 }, + { chemin = "PID.tangage.kp", label = "assiette T kp", pas = 0.25, + mini = 0 }, + { chemin = "PID.tangage.ki", label = "assiette T ki", pas = 0.05, + mini = 0 }, + { chemin = "PID.tangage.kd", label = "assiette T kd", pas = 0.25, + mini = 0 }, + { chemin = "PID.roulis.kp", label = "assiette R kp", pas = 0.25, + mini = 0 }, + { chemin = "PID.roulis.ki", label = "assiette R ki", pas = 0.05, + mini = 0 }, + { chemin = "PID.roulis.kd", label = "assiette R kd", pas = 0.25, + mini = 0 }, { chemin = "V_MONTEE_MAX", label = "v montee max (b/s)", pas = 0.5, mini = 0.5 }, { chemin = "V_DESCENTE_MAX", label = "v descente max (b/s)", diff --git a/lib/conf.lua b/lib/conf.lua index 533ccc4..86f5188 100644 --- a/lib/conf.lua +++ b/lib/conf.lua @@ -82,10 +82,18 @@ return { alt = { kp = 1.2 }, -- erreur alt -> v cible (1/s) montee = { kp = 40, ki = 60, kd = 5 }, -- v -> delta rpm descente = { kp = 40, ki = 60, kd = 5 }, - tangage = { kp = 4, ki = 0.5, kd = 8 }, - roulis = { kp = 4, ki = 0.5, kd = 8 }, + -- gains d'ASSIETTE: toujours lus ici (editables en direct page + -- PARAM), JAMAIS remplaces par les calibrations pid/pidmath + tangage = { kp = 2, ki = 0.2, kd = 3 }, + roulis = { kp = 2, ki = 0.2, kd = 3 }, }, + -- Autorite maximale de la correction d'assiette (et du trim), en + -- FRACTION du rpm de sustentation courant: l'autorite suit le + -- point de fonctionnement du drone (20 rpm comme 200 rpm) au lieu + -- d'etre figee a VMAX/2. + ASSIETTE_PLAFOND = 0.5, + ------------------------------------------------------------------ -- Ecrans (faces des deux Create_DisplayLink sur le PC) ------------------------------------------------------------------ diff --git a/lib/ihm.lua b/lib/ihm.lua index bdf0b27..8611440 100644 --- a/lib/ihm.lua +++ b/lib/ihm.lua @@ -333,16 +333,25 @@ function Ihm.nouveau(conf, materiel, journal) ------------------------------------------------------------------ -- PAGE PARAMS (edition tactile; surcharges dans drone.etat) ------------------------------------------------------------------ + local defilParams = 0 local function dessinerPageParams(ctx) - texte(1, 2, "surcharges sauvees dans drone.etat", colors.lightGray) + local params = ctx.params or {} + local parPage = H - 3 + local maxDefil = math.max(0, #params - parPage) + if defilParams > maxDefil then defilParams = maxDefil end + texte(1, 2, ("surcharges dans drone.etat (%d-%d/%d)"):format( + defilParams + 1, math.min(defilParams + parPage, #params), + #params), colors.lightGray) + bouton(L - 9, 2, "^", { type = "defilparam", sens = -1 }) + bouton(L - 4, 2, "v", { type = "defilparam", sens = 1 }) local y = 3 - for i2, p in ipairs(ctx.params or {}) do + for i2 = defilParams + 1, math.min(defilParams + parPage, #params) do + local p = params[i2] texte(1, y, ("%-24s"):format(p.label)) texte(26, y, tostring(p.valeur), colors.yellow) bouton(L - 9, y, "-", { type = "param", idx = i2, sens = -1 }) bouton(L - 4, y, "+", { type = "param", idx = i2, sens = 1 }) y = y + 1 - if y > H then break end end end @@ -389,6 +398,9 @@ function Ihm.nouveau(conf, materiel, journal) if z.action.type == "page" then page = z.action.valeur return { type = "redessiner" } + elseif z.action.type == "defilparam" then + defilParams = math.max(0, defilParams + z.action.sens * 4) + return { type = "redessiner" } end return z.action end diff --git a/lib/pilotage.lua b/lib/pilotage.lua index d5af687..b499cbf 100644 --- a/lib/pilotage.lua +++ b/lib/pilotage.lua @@ -39,7 +39,17 @@ function Pilotage.nouveau(conf, etat, materiel, Pid, journal) if v < mini then return mini elseif v > maxi then return maxi end return v end - local gains = etat.pid or conf.PID + + -- Gains: montee/descente viennent des calibrations (etat.pid), + -- l'assiette vient TOUJOURS de la conf (reference vive: la page + -- PARAM agit immediatement) + local gains = { + alt = conf.PID.alt, + montee = (etat.pid and etat.pid.montee) or conf.PID.montee, + descente = (etat.pid and etat.pid.descente) or conf.PID.descente, + tangage = conf.PID.tangage, + roulis = conf.PID.roulis, + } local pidMontee = Pid.nouveau(gains.montee, -VMAX, VMAX, 20) local pidDescente = Pid.nouveau(gains.descente, -VMAX, VMAX, 20) @@ -168,12 +178,14 @@ function Pilotage.nouveau(conf, etat, materiel, Pid, journal) end function p.reglerGains(nouveaux) - gains = nouveaux - etat.pid = nouveaux + gains.alt = nouveaux.alt or gains.alt + gains.montee = nouveaux.montee or gains.montee + gains.descente = nouveaux.descente or gains.descente + -- seuls les gains verticaux sont persistes: l'assiette reste + -- pilotee par la conf / page PARAM + etat.pid = { montee = gains.montee, descente = gains.descente } pidMontee:reglerGains(gains.montee) pidDescente:reglerGains(gains.descente) - pidTangage:reglerGains(gains.tangage) - pidRoulis:reglerGains(gains.roulis) end function p.reglerFacteurProp(f) @@ -196,14 +208,22 @@ function Pilotage.nouveau(conf, etat, materiel, Pid, journal) -- la cargaison); le PID reste centre sur la dynamique. local function appliquerHelices(base, tangage, roulis, dt, anglesCibles, adapter) + -- autorite d'assiette proportionnelle au point de fonctionnement + local plafond = math.max(2, + conf.ASSIETTE_PLAFOND * (p.rpmSustentation() + rpmAdapt)) + pidTangage.borneMin, pidTangage.borneMax = -plafond, plafond + pidRoulis.borneMin, pidRoulis.borneMax = -plafond, plafond + local corrTangage = SIGNE_TANGAGE * pidTangage:calculer(anglesCibles.tangage or 0, tangage, dt) local corrRoulis = SIGNE_ROULIS * pidRoulis:calculer(anglesCibles.roulis or 0, roulis, dt) if adapter then local taux = conf.ADAPTATION.TAUX_TRIM * dt - trimTangage = trimTangage + taux * corrTangage - trimRoulis = trimRoulis + taux * corrRoulis + trimTangage = borner(trimTangage + taux * corrTangage, + -plafond, plafond) + trimRoulis = borner(trimRoulis + taux * corrRoulis, + -plafond, plafond) end for role, s in pairs(SIGNES) do materiel.reglerRsc(role, borner(base