Never reference the ground attitude -- a flight-built hull lies on its side
The attitude reference was captured at the first sensor read, on the ground, where a ship built to fly typically lies over. That made every tilt reading relative to a meaningless datum, and worse: the hull's natural righting swing after liftoff was read both as tilt and as rate response, contaminating the very measurement the test exists to make. - Attitude reference is now taken in the air, after an explicit righting phase that waits for every axis rate to steady (5 s calm, 120 s cap). Until then maxTilt() reads 0, so nothing can trip on ground attitude. - The settled airborne attitude is recorded and reported per axis, with a warning if the hull settles far from level even under balanced lift. - Wizard now says outright that a ship lying over on the ground is fine. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -154,8 +154,12 @@ end
|
||||
-- mellom de to dyttene kansellerer enhver konstant skjev-drift eksakt. Og fordi vi VEKSLER mellom
|
||||
-- dyttene gynger skipet rundt utgangspunktet i stedet for aa akkumulere tilt -- selvbegrensende.
|
||||
--
|
||||
-- BAKKE-ATTITYDEN BRUKES ALDRI: skipet er bygget for aa FLY, ikke for aa staa, saa paa bakken
|
||||
-- ligger det gjerne paa siden. Vi venter til oppdriften har reist det opp OG ratene har roet seg
|
||||
-- foer attityde-referansen settes -- ellers ville skipets egen oppretting blitt lest som respons.
|
||||
--
|
||||
-- 1/5 trapper seg luftbaaren fra bunnen (laerer ~hover paa kjoepet, ingen fast liftLevel)
|
||||
-- 2/5 klatrer kontrollert til trygg maalehoyde (fart-P-hold rundt laert hover)
|
||||
-- 2/5 klatrer til maalehoyde, lar skipet RETTE SEG OPP, setter attityde-referanse i lufta
|
||||
-- 3/5 GYNGE-PROBE: front-dytt <-> bak-dytt, 2 sykluser; aksen som svarer blir pitchIndex.
|
||||
-- Svak respons -> auto sterkere dytt. Maaler ALLE gimbal-akser (byggeretning likegyldig)
|
||||
-- 4/5 BALANSE: med fortegnet kjent laeres differanse-trimmen som holder skipet vannrett
|
||||
@@ -196,12 +200,21 @@ local function runSigntest()
|
||||
if type(a) ~= "table" or type(a[1]) ~= "number" then return nil end
|
||||
if NAX == 0 then
|
||||
NAX = math.min(3, #a)
|
||||
a0 = {}
|
||||
for i = 1, NAX do axRings[i] = utils.newRing(1.0); a0[i] = a[i] end
|
||||
for i = 1, NAX do axRings[i] = utils.newRing(1.0) end
|
||||
end
|
||||
return a
|
||||
end
|
||||
|
||||
-- Attityde-referansen settes AaLDRI paa bakken: et skip bygget for aa FLY staar ikke stoett,
|
||||
-- det ligger gjerne paa siden. Den attityden er meningsloes -- og oppdriftens egen oppretting
|
||||
-- etter avgang ville blitt lest som baade "tilt" og "rate-respons". Vi setter referansen
|
||||
-- FOERST naar skipet har rettet seg opp i lufta og ratene har roet seg.
|
||||
local function setAttitudeRef()
|
||||
if not lastAx then return end
|
||||
a0 = {}
|
||||
for i = 1, NAX do a0[i] = lastAx[i] end
|
||||
end
|
||||
|
||||
local function axRates()
|
||||
local r = {}
|
||||
for i = 1, NAX do r[i] = axRings[i]:slope() end
|
||||
@@ -338,13 +351,32 @@ local function runSigntest()
|
||||
|
||||
local okC, cErr = recenter("2/5", "initial climb")
|
||||
if not okC then return bail(abortMsg(cErr)) end
|
||||
local tSettle = now()
|
||||
while now() - tSettle < 8 do
|
||||
velTick(0, 0, "settle0")
|
||||
hud("2/5", "Settling (learning true hover)...", {
|
||||
string.format("hover ~%.2f %.0fs left", hover, math.max(0, 8 - (now() - tSettle))),
|
||||
|
||||
-- La skipet RETTE SEG OPP i lufta foer vi maaler noe som helst. Et flybygget skrog ligger
|
||||
-- gjerne paa siden paa bakken; oppdriften reiser det opp av seg selv naar det kommer i lufta.
|
||||
-- Vi venter til ALLE akse-ratene har roet seg -- og setter FOERST DA attityde-referansen.
|
||||
local tR, calmR, worst = now(), 0, 0
|
||||
while now() - tR < 120 and now() < deadline do
|
||||
velTick(0, 0, "righting")
|
||||
worst = 0
|
||||
for i = 1, NAX do worst = math.max(worst, math.abs(axRings[i]:slope())) end
|
||||
if worst < 0.5 then calmR = calmR + cfg.dt else calmR = 0 end
|
||||
hud("2/5", "Letting the ship right itself...", {
|
||||
"(a flight-built hull lies over on the ground;",
|
||||
" buoyancy levels it once airborne)",
|
||||
string.format("worst rate %.2f deg/s steady %.1f/5.0 s", worst, calmR),
|
||||
string.format("hover ~%.2f", hover),
|
||||
})
|
||||
if calmR >= 5.0 then break end
|
||||
local rel = est.altitude - h0
|
||||
if rel < BAND_LO or rel > BAND_HI then
|
||||
local okD, dErr = recenter("2/5", "altitude drift")
|
||||
if not okD then return bail(abortMsg(dErr)) end
|
||||
end
|
||||
end
|
||||
setAttitudeRef() -- NAA er referansen meningsfull: skipets faktiske flyattityde
|
||||
local settled = {}
|
||||
for i = 1, NAX do settled[i] = (lastAx and lastAx[i]) or 0 end
|
||||
|
||||
-- rate-stabil maaling PER AKSE: hold hoyden (vDes=0) med gitt differanse til ratene roer
|
||||
-- seg. Returnerer tabell {avgRate per akse}. Lag-bevisst: minHold >= loft-etterslepet.
|
||||
@@ -476,6 +508,9 @@ local function runSigntest()
|
||||
term.clear(); term.setCursorPos(1, 1)
|
||||
print("==== SIGN TEST: SUCCESS ====")
|
||||
print(string.format("pitch = gimbal axis a%d, sign %+d", axis, sign))
|
||||
local sline = ""
|
||||
for i = 1, NAX do sline = sline .. string.format(" a%d %+.0f", i, settled[i]) end
|
||||
print("airborne attitude:" .. sline)
|
||||
print(string.format("balance trim %+.2f (saved warm-start)", 2 * levelTrim))
|
||||
if balanced then
|
||||
print("Ship levelled out under this trim.")
|
||||
@@ -483,6 +518,12 @@ local function runSigntest()
|
||||
print(string.format("NOTE: still %+.0f deg off level -- limited", pitchNow))
|
||||
print("pitch authority. FLY keeps learning it.")
|
||||
end
|
||||
if math.abs(settled[axis]) > 30 then
|
||||
print("")
|
||||
print("WARNING: it settled far from level even")
|
||||
print("with balanced lift -- the hull may not be")
|
||||
print("righting fully. Check balloon spacing.")
|
||||
end
|
||||
print(string.format("hover ~%.1f (saved as baseline)", hover))
|
||||
print("")
|
||||
print("Ship is holding hover. Ready to FLY.")
|
||||
@@ -797,9 +838,12 @@ local function runSetup()
|
||||
print("Two steps, fully guided:")
|
||||
print(" 1) Wiring -- map front/aft burner sides")
|
||||
print(" 2) Sign test -- short auto-flight that")
|
||||
print(" measures pitch response + hover")
|
||||
print(" measures pitch response + balance")
|
||||
print("")
|
||||
print("Ship must be ON THE GROUND, open sky above.")
|
||||
print("Just needs open sky above. It's FINE if the")
|
||||
print("ship lies over on the ground -- it rights")
|
||||
print("itself airborne, and nothing is measured")
|
||||
print("until it has.")
|
||||
print("")
|
||||
write("[Enter] = start, q = cancel: ")
|
||||
if read():lower() == "q" then return end
|
||||
@@ -811,10 +855,11 @@ local function runSetup()
|
||||
term.clear(); term.setCursorPos(1, 1)
|
||||
print("==== STEP 2: SIGN TEST ====")
|
||||
print("")
|
||||
print("The ship now lifts off BY ITSELF, gives")
|
||||
print("the front balloon a small push, verifies")
|
||||
print("the response both ways, and comes back")
|
||||
print("down to hover. Takes 1-3 minutes.")
|
||||
print("The ship lifts off BY ITSELF, waits until")
|
||||
print("it has righted and steadied in the air,")
|
||||
print("rocks front/aft to find the pitch axis,")
|
||||
print("learns the trim that levels it, then comes")
|
||||
print("back down to hover. Takes 2-4 minutes.")
|
||||
print("")
|
||||
write("[Enter] = lift off, q = cancel: ")
|
||||
if read():lower() == "q" then return end
|
||||
|
||||
Reference in New Issue
Block a user