176 lines
6.1 KiB
Lua
176 lines
6.1 KiB
Lua
--------------------------------------------------------------------
|
|
-- lib/ihm.lua : interfaces homme-machine.
|
|
-- Display Link "conduite" : altitudes, vitesse, invites, alertes
|
|
-- Display Link "carburant" : reserve + autonomie estimee (minutes)
|
|
-- Advanced monitor tactile : modes (verrouilles si calibration
|
|
-- manquante), consigne, calibrations, informations
|
|
-- Typewriter : la saisie est geree dans drone.lua (scrutation)
|
|
--------------------------------------------------------------------
|
|
local Ihm = {}
|
|
|
|
function Ihm.nouveau(conf, materiel, journal)
|
|
local ihm = {}
|
|
local moniteur = materiel.moniteur
|
|
moniteur.setTextScale(0.5)
|
|
|
|
local zones = {}
|
|
local messageConduite, messageFin = nil, 0
|
|
|
|
-- message temporaire sur la ligne 1 de la conduite (invites,
|
|
-- alertes); duree en secondes (nil = 5)
|
|
function ihm.message(texte, duree)
|
|
messageConduite = texte
|
|
messageFin = os.clock() + (duree or 5)
|
|
end
|
|
|
|
------------------------------------------------------------------
|
|
-- ECRAN DE CONDUITE
|
|
------------------------------------------------------------------
|
|
-- ctx: { mode, consigneY, saisie }
|
|
function ihm.rafraichirConduite(ctx)
|
|
local e = materiel.ecranConduite
|
|
e.clear()
|
|
e.setCursorPos(1, 1)
|
|
if messageConduite and os.clock() < messageFin then
|
|
e.write(messageConduite:sub(1, 22))
|
|
elseif ctx.saisie and #ctx.saisie > 0 then
|
|
e.write("SAISIE: " .. ctx.saisie)
|
|
elseif ctx.mode == "vol" or ctx.mode == "drone"
|
|
or ctx.mode == "atterrissage" or ctx.mode == "auto"
|
|
or ctx.mode == "position" then
|
|
e.write(("ALT %.1f / %.0f"):format(
|
|
materiel.lireAltitude(), ctx.consigneY or 0))
|
|
else
|
|
e.write("MODE " .. ctx.mode:upper())
|
|
end
|
|
e.setCursorPos(1, 2)
|
|
e.write(("VIT %.2f b/s"):format(materiel.vitesseHorizontale()))
|
|
e.update()
|
|
end
|
|
|
|
------------------------------------------------------------------
|
|
-- ECRAN CARBURANT (peut etre tres etroit: format compact)
|
|
------------------------------------------------------------------
|
|
-- pct 0..1 ou nil ; minutes ou nil
|
|
function ihm.rafraichirCarburant(pct, minutes)
|
|
local e = materiel.ecranCarburant
|
|
local largeur = e.getSize()
|
|
e.clear()
|
|
e.setCursorPos(1, 1)
|
|
if pct == nil then
|
|
e.write(("n/a"):sub(1, largeur))
|
|
else
|
|
e.write(("%d%%"):format(math.floor(pct * 100 + 0.5)):sub(1, largeur))
|
|
e.setCursorPos(1, 2)
|
|
if minutes then
|
|
e.write(("%dm"):format(math.floor(minutes)):sub(1, largeur))
|
|
else
|
|
e.write(("--m"):sub(1, largeur))
|
|
end
|
|
end
|
|
e.update()
|
|
end
|
|
|
|
------------------------------------------------------------------
|
|
-- MONITEUR TACTILE
|
|
------------------------------------------------------------------
|
|
local function bouton(x, y, texte, action, couleur)
|
|
moniteur.setCursorPos(x, y)
|
|
moniteur.setBackgroundColor(couleur or colors.gray)
|
|
moniteur.write(" " .. texte .. " ")
|
|
moniteur.setBackgroundColor(colors.black)
|
|
table.insert(zones, {
|
|
x1 = x, y1 = y, x2 = x + #texte + 1, y2 = y, action = action,
|
|
})
|
|
end
|
|
|
|
local function texte(x, y, contenu, couleur)
|
|
moniteur.setTextColor(couleur or colors.white)
|
|
moniteur.setCursorPos(x, y)
|
|
moniteur.write(contenu)
|
|
moniteur.setTextColor(colors.white)
|
|
end
|
|
|
|
-- ctx: { mode, consigneY, stress, position, carburantPct, minutes,
|
|
-- moteurOk, verrous = { mode -> raison|nil }, points = n }
|
|
function ihm.rafraichirMoniteur(ctx)
|
|
zones = {}
|
|
moniteur.setBackgroundColor(colors.black)
|
|
moniteur.clear()
|
|
|
|
texte(1, 1, "== MODES == actuel: " .. ctx.mode)
|
|
local modes = { "off", "inactif", "stationnement", "vol", "drone",
|
|
"atterrissage", "auto", "position" }
|
|
local x, y = 1, 2
|
|
for _, m in ipairs(modes) do
|
|
local verrou = ctx.verrous[m]
|
|
local couleur = colors.gray
|
|
if m == ctx.mode then couleur = colors.green
|
|
elseif verrou then couleur = colors.red end
|
|
if x + #m + 2 > 50 then x, y = 1, y + 1 end
|
|
bouton(x, y, m, { type = "mode", valeur = m, verrou = verrou },
|
|
couleur)
|
|
x = x + #m + 3
|
|
end
|
|
|
|
texte(1, y + 2, ("== CONSIGNE == %.0f"):format(ctx.consigneY or 0))
|
|
bouton(1, y + 3, "-10", { type = "delta", valeur = -10 })
|
|
bouton(7, y + 3, "-1", { type = "delta", valeur = -1 })
|
|
bouton(12, y + 3, "+1", { type = "delta", valeur = 1 })
|
|
bouton(17, y + 3, "+10", { type = "delta", valeur = 10 })
|
|
|
|
texte(1, y + 5, "== CALIBRATIONS ==")
|
|
local cx = 1
|
|
for _, c in ipairs({ "gimbal", "joystick", "typew", "rsc",
|
|
"capteurs", "pid" }) do
|
|
bouton(cx, y + 6, c, { type = "calib", valeur = c })
|
|
cx = cx + #c + 3
|
|
end
|
|
|
|
local ly = y + 8
|
|
texte(1, ly, "== INFOS ==")
|
|
local t, r = materiel.lireAssiette()
|
|
texte(1, ly + 1, ("assiette T %+.2f R %+.2f%s"):format(t, r,
|
|
ctx.gimbalOk and "" or " (NON CALIBRE)"))
|
|
texte(1, ly + 2, ("sol %.1f (%s%s)"):format(
|
|
materiel.lireDistanceSol(),
|
|
materiel.auSol() and "au sol" or "en vol",
|
|
materiel.solPosable() and "" or ", NON POSABLE"))
|
|
texte(1, ly + 3, ("stress %s moteur %s"):format(
|
|
ctx.stress and ("%.0f%%"):format(ctx.stress * 100) or "n/a",
|
|
ctx.moteurOk and "ok" or "ARRETE"),
|
|
ctx.moteurOk and colors.white or colors.red)
|
|
texte(1, ly + 4, ("carburant %s autonomie %s"):format(
|
|
ctx.carburantPct
|
|
and ("%.0f%%"):format(ctx.carburantPct * 100) or "n/a",
|
|
ctx.minutes and ("%dmin"):format(math.floor(ctx.minutes)) or "--"))
|
|
if ctx.position then
|
|
texte(1, ly + 5, ("gps %.0f %.0f %.0f points: %d")
|
|
:format(ctx.position.x, ctx.position.y, ctx.position.z,
|
|
ctx.points or 0))
|
|
else
|
|
texte(1, ly + 5, "gps n/a", colors.red)
|
|
end
|
|
end
|
|
|
|
function ihm.traiterToucher(tx, ty)
|
|
for _, z in ipairs(zones) do
|
|
if tx >= z.x1 and tx <= z.x2 and ty >= z.y1 and ty <= z.y2 then
|
|
return z.action
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-- attend un toucher du moniteur (utilise par les calibrations)
|
|
function ihm.attendreToucher()
|
|
while true do
|
|
local ev = os.pullEvent("monitor_touch")
|
|
if ev then return end
|
|
end
|
|
end
|
|
|
|
return ihm
|
|
end
|
|
|
|
return Ihm
|