Fix oscillation drone

This commit is contained in:
Ploush 2026-07-19 14:08:36 +02:00
parent 700d60ca27
commit 9137a98af3
4 changed files with 66 additions and 12 deletions

View file

@ -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)",

View file

@ -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)
------------------------------------------------------------------

View file

@ -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

View file

@ -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