#173 FINAL: port cadence defect FIXED -- the velocity ring now samples at the pod's 28Hz by default (BT_MYO_RING_HZ overrides). Measured [T2, six curves m173v2]: at ~59fps the |a| operand carried 64-66% gait-aliasing noise = drive heat 2x the machine's; at 28Hz + the authored loop-5 boost (detent 50 receipt-proven, flow 0.909) a vulture holds FULL supercharge 54-57 u/s indefinitely at stable Tm~1500 -- the machine's valve lever worked, the manual's Super Charged print was honest, witnesses 7-0 (Draco/Oracle/Elengil + the user's eyes beat the solver AND the first bench). Balanced seek-4 still cooks authentically (~18s); wrap trap stands; display pixel-verified in sync. BT_VALVE5 bench hook added (receipted detent presses). Post-promotion smoke: boosted vulture stable ~1500 dipping under. Gotcha 32 (sampled-history operands at render cadence; a validated model EXTRAPOLATES, only the bench INTERPOLATES); cadence census -> BTSimClock migration checklist in open-questions (gyro bounce timescale next, footstep smoothers, doppler; heatLoad was already pod-clocked #119 = the reference pattern). Guide 2B rewritten with the confession + the measured fix
This commit is contained in:
@@ -1233,7 +1233,18 @@ consistent with internals-only, see #103). Logs: `scratchpad/night16/` + Oracle
|
||||
(x2 spawns, AFC50/Zanin Neko); once ABSENT for an entire fatal leak (5-6 voice repetitions,
|
||||
no flash on any MFD, died ~9:38PM CT -- the match's only death, receipt findable in night16).
|
||||
Distinct from the closed #135: this is the SET-edge / first-flash arming path.
|
||||
- **#173 -- chicken-walker seek-4 myomer overheat** (see [[subsystems]] night-16 note).
|
||||
- **#173 -- chicken-walker seek-4 myomer overheat: ⚑ SETTLED AUTHENTIC (2026-08-13, three
|
||||
lanes, see [[subsystems]] #173 blocks).** Bench matrix reproduced Elengil exactly (vulture
|
||||
seek-4: degT in 13.9 s, governor-pinned eq ~1801, loop-5 bar full-scale ~15-20 s, sheds
|
||||
−10/s only at standstill); the equilibrium is a chassis-blind governor thermostat — the
|
||||
port's avatar (same 143-kph speed class) cooks identically, and the manual prints the big
|
||||
walkers even FASTER (MadCat 175/220) than the port runs them. Counter-play measured: one
|
||||
loop-5 valve press sustains drive 0.68 vs 0.54. TWO residuals stay open: (1) [T3] the
|
||||
accel-term |a| ring is frame-cadence-sensitive (|a|≈14-20 at 59 fps on a straight flat
|
||||
cruise = gait surge; pod 28 Hz would read ~2-3x smaller → pod eq likely ~1200-1500, softer
|
||||
governor — if calibration is wanted, fix the |a| feed cadence, never the byte-exact
|
||||
constants); (2) locomotion-lane: port per-chassis top speeds undershoot the manual prints
|
||||
(thor 87 vs 143 N print) — correcting them raises heat further.
|
||||
- **#165 ROOT-CAUSED + FIXED + BENCHED (2026-08-13, the 4-agent hunt):** gotcha SS30 -- the
|
||||
binary's ONE destroyed cell was split into four port stores and the crit-lottery kill path
|
||||
(MechWeapon::TakeDamage) wrote none the gate reads. Fixed (chain to MechSubsystem::TakeDamage,
|
||||
@@ -1253,3 +1264,26 @@ consistent with internals-only, see #103). Logs: `scratchpad/night16/` + Oracle
|
||||
wanted for the pair-leak confirmation.
|
||||
- Nanook lost the coolant MFD glass window, recovered only by config edit -> #76 comment
|
||||
(in-game layout-reset recovery path).
|
||||
|
||||
|
||||
## Cadence census -- the shared 28Hz sim-clock migration checklist (2026-08-13) [T1/T2]
|
||||
Census of sampled-history-at-render-cadence sites (gotcha 32; full table in the census
|
||||
workflow journal wf_d875938f + classifier verdicts). DONE: velocity ring default-28Hz
|
||||
(mech4.cpp, HIGH, the #173 fix -- myomer heat + instability/sway inherit); heatLoad already
|
||||
pod-clocked (#119, the reference pattern). REMAINING for the BTSimClock migration (one
|
||||
shared 28Hz tick source; tick-native sites subscribe; dt-native physics -- Mover/missile ODE
|
||||
-- stays on real dt):
|
||||
- MED gyro eye/body spring-damper integrators (gyro.cpp:503-575): per-tick position step, NO
|
||||
dt, damping carries last-frame state -- cockpit bounce timescale runs 2.14x the machine's.
|
||||
Needs an impulse-response bench (28 vs 60) before/after.
|
||||
- LOW footstep AudioControlSmoother windows (AUDCMP.cpp:952-977): authored N=30/15 sized for
|
||||
28Hz; halved at 60fps + noisy operand. Clock the watcher-poll intake.
|
||||
- LOW doppler operand (AUDLOC.cpp:439-505 reads UNSMOOTHED worldLinearVelocity frame
|
||||
derivative): per-stride pitch warble on nearby movers. A/B-able by ear.
|
||||
- LOW published localVelocity 0.25s exponential smoothing (mech4.cpp:5578-5613): re-base to
|
||||
the binary's own 15-sample@28Hz filter once the shared clock exists.
|
||||
- DEFERRED dead-reckon divergence (@_DAT_004be050) -- only matters if the Missile entity
|
||||
revives. ANNOTATE-ONLY: Simulate telemetry FilteredScalars (dormant).
|
||||
- Productionize the ring's 16-slot dt-accumulator registry (mech4.cpp) to the heat.cpp map
|
||||
pattern (degrades gracefully to per-frame push on overflow today; fine for one mission's
|
||||
mech count, sloppy long-term).
|
||||
|
||||
@@ -1064,3 +1064,26 @@ passes every reader-side bench. **Bench rule (the #165 lesson, second applicatio
|
||||
week):** prove the bench detects the bug BEFORE trusting its pass -- the negative control
|
||||
here (fix stashed) scored 147 cascades where the fixed build scores 1.
|
||||
Bench: BT_ZONE_HAMMER=<zone>[,<amt>] (mech4.cpp) + scratchpad/night16/cascade_bench.sh.
|
||||
|
||||
|
||||
## 32. SAMPLED-HISTORY OPERANDS AT RENDER CADENCE: rate-scaling amounts cannot un-noise a signal (#173 flip, 2026-08-13)
|
||||
The port's #137 pattern (term x dt x 28) correctly rate-normalizes per-tick heat AMOUNTS -- but
|
||||
OPERANDS COMPUTED FROM SAMPLED HISTORY (rings, last-frame deltas, moving averages, per-tick
|
||||
integrators carrying state) still sampled at RENDER cadence where the pod's board sampled at
|
||||
28 Hz. The killer case: the AccelerationLastFrame velocity ring pushed per render frame read
|
||||
|a| 17-26 of pure gait-aliasing noise on a flat straight cruise -- 64-66% of myomer drive-heat
|
||||
generation was PHANTOM; at 28 Hz sampling the noise drops to 24-32% and generation HALVES at
|
||||
equal speed. Consequence: every fast-heavy chassis was over-punished ~2x; the authored loop-5
|
||||
valve boost genuinely sustains FULL supercharge seek-4 at 28 Hz (bench m173v2 leg G: 54-57 u/s
|
||||
held, Tm stable ~1500) -- the machine's lever worked and the manual's Super Charged print was
|
||||
honest. Witnesses (Draco/Oracle/Elengil + the user's own eyes) beat the validated-solver
|
||||
extrapolation AND the first bench: 7-0 this week.
|
||||
**Rules:** (1) any binary value derived from per-tick sampled history must be sampled on the
|
||||
BINARY'S clock -- accumulate render dt, take one sample per 1/28 s measuring over the full
|
||||
elapsed window (the heat.cpp #119 heatLoad clock is the reference implementation; the ring
|
||||
default-28Hz in mech4.cpp is the second). (2) Rate-scaling the consuming term is NOT
|
||||
sufficient -- it scales amounts, not signal quality. (3) A validated model EXTRAPOLATES; only
|
||||
the bench INTERPOLATES -- never print "sustains indefinitely" from a solver row the bench
|
||||
never flew (the #173 verdict flipped twice on exactly this). Census of the whole class (11
|
||||
rows, 2 HIGH fixed, migration checklist for the shared 28 Hz sim-clock): open-questions.md
|
||||
SSCadence-census + the wf_d875938f journal.
|
||||
|
||||
@@ -475,3 +475,45 @@ edge — this is the gap that would reconcile Oracle's "ran 182 kph sustained" p
|
||||
If field calibration is ever wanted, the knob is the |a| feed's cadence (sample the ring at
|
||||
28 Hz), NOT the formula constants (byte-exact, #137). Also note the CLIMB term is inert in
|
||||
the port (g=0, EnvironmentZone unwired) — the pod added heat on slopes that we do not.
|
||||
|
||||
**#173 DECISIVE VALVE-BOOST + CADENCE EXPERIMENT (2026-08-13 night17;
|
||||
`scratchpad/night17/m173v_bench.sh`/`m173v2_bench.sh`/`m173v_check.py`, logs
|
||||
`content/m173_vul_[ABCEFG]*.log`, captures `content/vlv_*.png`) — the residual above is now
|
||||
MEASURED and the verdict sharpens:**
|
||||
- **Valve delivery PORT-FAITHFUL, receipt-PROVEN [T2 live / T1 operands]**: the `BT_VALVE5=N`
|
||||
hook (mech4.cpp, env-gated) presses Condenser5's MoveValve N times; every landed detent is
|
||||
receipted (`[valve] Condenser5 valve -> detent 5/50/0` + the zero-sum redistribute lines:
|
||||
share 0.5 → 0.909091 → 0, others 0.1 → 0.0182 → 0.2, exactly @0049f788's flow=valve/total).
|
||||
C5 responds as flow dictates (cruise Tc5: balanced 1396 → detent-50 712 → CLOSED 1902 pegged).
|
||||
- **The bottleneck SHIFTS to the valve-independent stage [T1+T2]**: myomer→Condenser5
|
||||
conduction measures 4.1–5.0e4 heat-units/K of dT in EVERY run (balanced/boosted/closed,
|
||||
both cadences) — constant because @004ad9ec's exponent reads the CALLER's own
|
||||
flowScale@+0x15C (the myomer's, pinned 1.0), never the condenser's valve share [T1 raw
|
||||
pseudocode]. The solver's 2.7x boosted whole-chain throughput is CONFIRMED live (4.8e7/s
|
||||
through the chain at 60fps detent 50) but its "sustains under degT 1000" corollary is
|
||||
WRONG at any cadence: sub-1000 Tm caps stage-1 flux at ~3e7/s < supercharge generation, so
|
||||
the governor always engages; the boost buys SPEED at a lower pinned Tm, never sub-1000 Tm.
|
||||
- **The cadence residual is REAL and ~2x [T2 measured]** (BT_MYO_RING_HZ=28 knob landed in
|
||||
mech4.cpp — cadence only, constants untouched): at ~59fps the |a| gait-surge noise carries
|
||||
64–66% of steady seek-4 generation (|a|≈17–26 flat grass); at 28Hz it drops to 24–32%
|
||||
(|a|≈6–7) and generation at equal speed HALVES. The six curves (solo vulture seek-4, t1000 /
|
||||
equilibrium / held v): 60fps bal 12.3s/1800/28 · 60fps d50 12.3s/1675/44 · 60fps CLOSED
|
||||
13.9s/NO-EQ-1936-still-climbing/11.7 (drive 0.21, C5 pegged 1902 — the wrap-trap signature)
|
||||
· 28Hz bal 18.3s/~1710/39–41 · **28Hz d50 22.5s/~1500 STABLE/54–57 = FULL supercharge speed
|
||||
sustained indefinitely** (equilibrium sits on the soft governor shoulder, zero speed cost;
|
||||
500 under failT). **The machine's loop-5 boost genuinely sustained unrestricted seek-4 — the
|
||||
manual's Super Charged print is vindicated at pod cadence; the port at ~59fps over-punishes
|
||||
by ~2x. Severity verdict flips to PORT CADENCE DEFECT (fix = 28Hz ring sampling; default
|
||||
promotion = owners' decision).** Balance verdict unchanged: balanced-valve seek-4 cooks at
|
||||
BOTH cadences (authentic, manual-warned).
|
||||
- **Field "3–4s to governor" ≠ spawn preheat [T2]**: field-shaped run (autofire at scenery
|
||||
from frame 0, no pre-settle) still takes 15.9s to degT from cold; GenD/loop-5 preheat is
|
||||
real but slow (GenD 666 by 29s). The 3–4s feel is a WARM-START baseline (T≥800 → <3s) plus
|
||||
the deep 59fps governor making the derate obvious.
|
||||
- **Heat-MFD valve slider IN SYNC [T2 pixel-verified]**: the vertNormalSlider renders
|
||||
coolantFlowScale@0x15C — the SAME cell the flow model consumes (single-cell design, no
|
||||
split possible); measured bar fractions 0.20/0.51/0.90/0.04 for receipt shares
|
||||
0.167/0.5/0.909/0.0 (perfectly linear; `vlv_*.png`). Detent 50 (≈90% up) and detent 0
|
||||
(bottom) are clearly distinguishable; the residual legibility trap is CLOSED-vs-STARVED
|
||||
(share 0 vs 0.018–0.1 ≈ 1–2px apart) and the silent 4th-press wrap — "maxed and couldn't
|
||||
shed" field reports match the run-C wrap signature, not a display desync.
|
||||
|
||||
@@ -121,9 +121,9 @@ THE ORIGINAL'S BEHAVIOR (audited to the byte this week)
|
||||
in this machine. The fast-heavy Clan walkers pay the most.
|
||||
- Gears 1 through 3 make IDENTICAL heat: seek-3 is free speed.
|
||||
Seek-4 roughly doubles drive heat AND raises your top speed --
|
||||
a sprint gear. Cruising it on a heavy walker crosses myomer
|
||||
degradation in about 14 seconds and the governor drags you to a
|
||||
crawl. A same-weight humanoid at the same speed cooks the same:
|
||||
a sprint gear. Cruising it on a heavy walker without the boost
|
||||
crosses myomer degradation in under twenty seconds and the
|
||||
governor bites. A same-weight humanoid at the same speed cooks the same:
|
||||
it is physics, not a chicken-walker curse.
|
||||
- The machine gave you the tool: BOOST COOLANT LOOP 5 (Generator D /
|
||||
Myomers). One press visibly buys your speed back; a full boost
|
||||
@@ -133,20 +133,28 @@ THE ORIGINAL'S BEHAVIOR (audited to the byte this week)
|
||||
wrap. Two presses, never three.
|
||||
- Standing still sheds heat fast (~10 degrees a second).
|
||||
|
||||
OUR PORT TODAY
|
||||
All of the above, byte-faithful -- and our walkers actually run a
|
||||
little SLOWER than the machine's printed speeds, so if anything the
|
||||
pods cooked slightly faster than we do. One open sliver: our
|
||||
governor may bite a touch harder than you remember (a frame-timing
|
||||
nuance under study), which the question below settles.
|
||||
OUR PORT TODAY -- AND A CONFESSION YOUR REPORTS FORCED
|
||||
You were right that something was off. Our build measured your
|
||||
mech's acceleration at modern frame rates, and at those rates the
|
||||
measurement picks up walking-gait jitter as phantom acceleration --
|
||||
nearly TWO-THIRDS of your drive heat on a flat cruise was noise
|
||||
that the original's electronics (sampling at their own slower
|
||||
clock) never saw. The port was punishing heavy walkers roughly
|
||||
TWICE as hard as the machine did.
|
||||
|
||||
CHANGING IN THE NEXT BUILD
|
||||
Nothing mechanical.
|
||||
CHANGING IN THE NEXT BUILD (the fix, measured)
|
||||
Heat sensing now samples on the original's clock. Result on the
|
||||
bench: a Vulture at seek-4 WITH the loop-5 boost holds FULL
|
||||
supercharge speed indefinitely, running hot but stable -- the
|
||||
valve trick works exactly as the machine intended, and the
|
||||
manual's printed Super Charged speed is real. WITHOUT the boost,
|
||||
seek-4 still cooks you (that part is the machine's own balance,
|
||||
and it stays). The wrap trap also stays: two presses, never three.
|
||||
|
||||
WE NEED YOUR MEMORY
|
||||
- At seek-4 on a Vulture or MadCat -- balanced valves, flat ground
|
||||
-- did your speed sag within ~15 seconds, or could you hold
|
||||
supercharge speed sustained?
|
||||
- Next build: boost loop 5, hold seek-4 on a big walker. Does the
|
||||
sustained supercharge match how the machine felt? Your yes
|
||||
closes the oldest heat complaint on the books.
|
||||
- Did the loop-5 valve boost trick live in era pilot lore, or are
|
||||
we rediscovering it?
|
||||
|
||||
|
||||
@@ -7835,6 +7835,57 @@ void
|
||||
gBTValveKey = (s_vtFrame >= 600 && s_vtFrame < 610) ? 1 : 0;
|
||||
}
|
||||
|
||||
// #173 decisive experiment (BT_VALVE5=N): press Condenser5's MoveValve
|
||||
// exactly N times, spaced BT_VALVE5_SPACING frames (default 30) apart,
|
||||
// starting at frame BT_VALVE5_AT (default 300) -- walks the detent
|
||||
// cycle 1->5->50->0 (@4ae464) a CONTROLLED number of steps on the
|
||||
// MYOMER loop. Dispatches the same ReceiverDataMessageOf<ControlsButton>
|
||||
// press payload the pod's engineering-screen aux button delivers; the
|
||||
// handler's unconditional [valve] receipt proves each landed detent.
|
||||
// Self-contained (does NOT ride gBTValveKey, so it cannot collide with
|
||||
// the BT_VALVE_TEST edge detector). Env-gated, off by default.
|
||||
if ((Entity *)this == application->GetViewpointEntity()
|
||||
&& getenv("BT_VALVE5"))
|
||||
{
|
||||
static int s_v5Frame = 0;
|
||||
static int s_v5Sent = 0;
|
||||
++s_v5Frame;
|
||||
int want = atoi(getenv("BT_VALVE5"));
|
||||
const char *atEnv = getenv("BT_VALVE5_AT");
|
||||
const char *spEnv = getenv("BT_VALVE5_SPACING");
|
||||
int startAt = (atEnv != 0) ? atoi(atEnv) : 300;
|
||||
int spacing = (spEnv != 0) ? atoi(spEnv) : 30;
|
||||
if (spacing < 2) spacing = 2; // edge needs a gap
|
||||
if (s_v5Sent < want
|
||||
&& s_v5Frame >= startAt + s_v5Sent * spacing)
|
||||
{
|
||||
Subsystem *condenser = 0;
|
||||
for (int s = 1; s < GetSubsystemCount(); ++s)
|
||||
{
|
||||
Subsystem *sub = GetSubsystem(s);
|
||||
if (sub != 0 && (int)sub->GetClassID() == 0xBBD // Condenser
|
||||
&& sub->GetName() != 0
|
||||
&& stricmp(sub->GetName(), "Condenser5") == 0)
|
||||
{
|
||||
condenser = sub;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (condenser != 0)
|
||||
{
|
||||
++s_v5Sent;
|
||||
DEBUG_STREAM << "[valve-tx] BT_VALVE5 press " << s_v5Sent
|
||||
<< "/" << want << " -> " << condenser->GetName()
|
||||
<< " (frame " << s_v5Frame << ")\n" << std::flush;
|
||||
ReceiverDataMessageOf<ControlsButton> msg(
|
||||
4 /*Condenser::MoveValveMessageID*/,
|
||||
sizeof(ReceiverDataMessageOf<ControlsButton>),
|
||||
(ControlsButton)1 /*press*/);
|
||||
condenser->Dispatch(&msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Gitea #6 scripted verify (BT_VIEWCYCLE_TEST=<frame>): pulse one
|
||||
// secondary-schematic cycle (Damage -> Critical -> Heat -> Damage) at
|
||||
// the given frame and every 300 frames after -- with
|
||||
@@ -8695,15 +8746,72 @@ void
|
||||
// footstep smoother fed (fed per-stride only, it took 10-20 s to warm
|
||||
// from fill=0: the late-footsteps bug).
|
||||
{
|
||||
// #173 RING CADENCE -- DEFAULT 28 Hz (promoted 2026-08-13, user call,
|
||||
// six-curve bench m173v2): push velocity-ring samples at the pod's
|
||||
// BOARD cadence (28 Hz nominal [T1]) instead of once per render
|
||||
// frame. The ring / mean-derivative STRUCTURE is untouched
|
||||
// (byte-faithful); the only change is the sampling clock, which on
|
||||
// the pod WAS the frame clock (28 Hz) and here is ~60. MEASURED
|
||||
// [T2]: at ~59fps the |a| operand carries 64-66% ALIASING NOISE
|
||||
// (|a| 17-26 on flat straight grass); at 28 Hz it drops to 24-32%
|
||||
// and drive-heat generation HALVES at equal speed -- the port was
|
||||
// over-punishing every fast-heavy chassis ~2x. With the authored
|
||||
// loop-5 boost, 28 Hz sustains FULL supercharge speed indefinitely
|
||||
// at a stable Tm ~1500 (leg G: 54-57 u/s held) -- the machine's
|
||||
// valve lever worked, and the manual's printed Super Charged stat
|
||||
// was honest. BT_MYO_RING_HZ=<hz> overrides for bracketing
|
||||
// (=0 or negative restores raw render-cadence sampling).
|
||||
int ringPush = 1;
|
||||
Scalar ringDt = dt;
|
||||
{
|
||||
static Scalar s_ringHz = -2.0f;
|
||||
if (s_ringHz < -1.0f)
|
||||
{
|
||||
const char *rh = getenv("BT_MYO_RING_HZ");
|
||||
s_ringHz = (rh != 0 && *rh != '\0') ? (Scalar)atof(rh) : 28.0f;
|
||||
}
|
||||
if (s_ringHz > 0.0f)
|
||||
{
|
||||
// per-instance dt accumulator (tiny fixed registry -- bench
|
||||
// scaffolding; a solo bench has one mech, MP a handful)
|
||||
static const void *s_raKey[16];
|
||||
static Scalar s_raAcc[16];
|
||||
int slot = -1, freeSlot = -1;
|
||||
for (int k = 0; k < 16; ++k)
|
||||
{
|
||||
if (s_raKey[k] == (const void *)this) { slot = k; break; }
|
||||
if (s_raKey[k] == 0 && freeSlot < 0) freeSlot = k;
|
||||
}
|
||||
if (slot < 0 && freeSlot >= 0)
|
||||
{
|
||||
slot = freeSlot;
|
||||
s_raKey[slot] = (const void *)this;
|
||||
s_raAcc[slot] = 0.0f;
|
||||
}
|
||||
if (slot >= 0)
|
||||
{
|
||||
s_raAcc[slot] += dt;
|
||||
if (s_raAcc[slot] < 1.0f / s_ringHz)
|
||||
ringPush = 0;
|
||||
else
|
||||
{
|
||||
ringDt = s_raAcc[slot];
|
||||
s_raAcc[slot] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ringPush)
|
||||
{
|
||||
Scalar rdx = localOrigin.linearPosition.x - accelPrevPos.x;
|
||||
Scalar rdy = localOrigin.linearPosition.y - accelPrevPos.y;
|
||||
Scalar rdz = localOrigin.linearPosition.z - accelPrevPos.z;
|
||||
accelPrevPos = localOrigin.linearPosition;
|
||||
if (dt > 1.0e-4f)
|
||||
if (ringDt > 1.0e-4f)
|
||||
{
|
||||
velRingFwd[velRingCursor] = (Scalar)sqrtf(rdx * rdx + rdz * rdz) / dt;
|
||||
velRingVert[velRingCursor] = rdy / dt;
|
||||
velRingDt[velRingCursor] = dt;
|
||||
velRingFwd[velRingCursor] = (Scalar)sqrtf(rdx * rdx + rdz * rdz) / ringDt;
|
||||
velRingVert[velRingCursor] = rdy / ringDt;
|
||||
velRingDt[velRingCursor] = ringDt;
|
||||
velRingCursor = (velRingCursor + 1) % 15;
|
||||
}
|
||||
Scalar fwdMean = 0.0f, vertMean = 0.0f, dtMean = 0.0f;
|
||||
@@ -8723,6 +8831,7 @@ void
|
||||
-((fwdMean - accelPrevFwdMean) / dtMean));
|
||||
accelPrevFwdMean = fwdMean;
|
||||
accelPrevVertMean = vertMean;
|
||||
}
|
||||
}
|
||||
|
||||
// (AUDIO_FIDELITY F7) latch the incoming-missile report accumulated by
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env bash
|
||||
# =========================================================================
|
||||
# #173 wave 2 -- the field-feel gap (3-4s to governor vs bench 12-13s) and
|
||||
# the 28Hz cadence residual, decisive runs:
|
||||
# E) FIELD-SHAPED spawn: no pre-settle, weapons charging + THROTTLED
|
||||
# autofire at scenery from the first frame, sprint at seek-4 --
|
||||
# time-to-degradation + Condenser5/GeneratorD preheat at motion start.
|
||||
# F) 28Hz ring cadence (BT_MYO_RING_HZ=28), balanced valves -- does the
|
||||
# |a| gait-surge term collapse and t1000 stretch?
|
||||
# G) 28Hz ring cadence + PROVEN detent 50 on Condenser5 (BT_VALVE5=2) --
|
||||
# THE FLIP TEST: does boosted seek-4 land UNDER degradation 1000?
|
||||
# Same rig as m173v_bench.sh (solo expert vulture, grass/day, seek-4 forced,
|
||||
# full autodrive, 0.12 turn), 165s each.
|
||||
# =========================================================================
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
||||
sleep 2
|
||||
|
||||
run_one () { # run_one <tag> <secs> [extra env pairs...]
|
||||
local TAG=$1 SECS=$2; shift 2
|
||||
bt_expert_egg MP.EGG M173V.EGG
|
||||
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=vulture/" M173V.EGG
|
||||
local LOG=m173_${TAG}.log
|
||||
rm -f "$LOG"
|
||||
( export BT_MYO_LOG=1 BT_HEAT_LOG=1 BT_SPEC_LOG=1 BT_MYOMERS_LOG=1 BT_VALVE_LOG=1
|
||||
export BT_FORCE_SEEK=3 BT_AUTODRIVE=1.0 BT_FORCE_TURN=0.12
|
||||
for kv in "$@"; do export "$kv"; done
|
||||
bt_launch "$LOG" M173V.EGG 0x03 )
|
||||
sleep "$SECS"
|
||||
bt_kill_ours
|
||||
sleep 3
|
||||
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
||||
sleep 2
|
||||
}
|
||||
|
||||
run_one vul_E_field 165 BT_AUTOFIRE=1 BT_FIRE_AT_ICON=1 BT_AF_PERIOD=4 BT_FIRE_LOG=1
|
||||
run_one vul_F_28bal 165 BT_MYO_RING_HZ=28
|
||||
run_one vul_G_28d50 165 BT_MYO_RING_HZ=28 BT_VALVE5=2
|
||||
|
||||
echo "=================== m173v wave-2 RUNS DONE ==================="
|
||||
for f in m173_vul_E_field.log m173_vul_F_28bal.log m173_vul_G_28d50.log; do
|
||||
echo "--- $f"
|
||||
grep -ac "myotemp" "$f" 2>/dev/null
|
||||
grep -a "valve-tx\|valve -> detent" "$f" 2>/dev/null
|
||||
done
|
||||
@@ -0,0 +1,65 @@
|
||||
#!/usr/bin/env bash
|
||||
# =========================================================================
|
||||
# #173 DECISIVE EXPERIMENT -- does boosting coolant loop 5's valve sustain
|
||||
# seek-4 on a Vulture, as the equilibrium solver claims, or does it still
|
||||
# cook as the field reported ("loop 5 maxed and couldn't shed")?
|
||||
#
|
||||
# Rig: the m173 measurement pattern (night16 myo173.sh) -- solo expert
|
||||
# vulture, grass/day, BT_FORCE_SEEK=3 (seek-4) + BT_AUTODRIVE=1.0 +
|
||||
# BT_FORCE_TURN=0.12 (stays on-map near top speed), myomer/condenser temp
|
||||
# receipts under the heat-log envs.
|
||||
#
|
||||
# Valve control: the NEW BT_VALVE5=N hook (mech4.cpp) presses Condenser5's
|
||||
# MoveValve N times, spaced 30 frames, starting frame 300. Every press is
|
||||
# receipted by the handler's unconditional "[valve] Condenser5 valve ->
|
||||
# detent D" line, and BT_VALVE_LOG receipts the zero-sum share redistribute
|
||||
# ("[valve] condenser#5 valveState=V flow=F (total=T)") -- the landed
|
||||
# detent is PROVEN, not assumed.
|
||||
#
|
||||
# Three measurement runs, ~150s sustained seek-4 cruise each, identical
|
||||
# otherwise:
|
||||
# A) balanced (no presses) -- expected: degradation ~14s, eq ~1800
|
||||
# B) BT_VALVE5=2 (detent 1->5->50) -- THE QUESTION: stays under 1000?
|
||||
# C) BT_VALVE5=3 (wrap to detent 0) -- expected WORSE than A (share 0)
|
||||
# Plus one visual run:
|
||||
# D) idle mech, 3 presses spaced 600 frames, BT_SHOT_EVERY=90 -- captures
|
||||
# the Heat MFD valve slider at each detent 1/5/50/0 (indicator audit).
|
||||
# =========================================================================
|
||||
set -x
|
||||
. /c/git/bt411/scratchpad/night6/bench_common.sh
|
||||
cd /c/git/bt411/content || exit 1
|
||||
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
||||
sleep 2
|
||||
rm -f vlv_*.png
|
||||
|
||||
run_one () { # run_one <tag> <secs> [extra env pairs...]
|
||||
local TAG=$1 SECS=$2; shift 2
|
||||
bt_expert_egg MP.EGG M173V.EGG
|
||||
sed -i "s/^map=.*/map=grass/; s/^time=.*/time=day/; 0,/^vehicle=.*/s//vehicle=vulture/" M173V.EGG
|
||||
local LOG=m173_${TAG}.log
|
||||
rm -f "$LOG"
|
||||
( export BT_MYO_LOG=1 BT_HEAT_LOG=1 BT_SPEC_LOG=1 BT_MYOMERS_LOG=1 BT_VALVE_LOG=1
|
||||
for kv in "$@"; do export "$kv"; done
|
||||
bt_launch "$LOG" M173V.EGG 0x03 )
|
||||
sleep "$SECS"
|
||||
bt_kill_ours
|
||||
sleep 3
|
||||
taskkill //F //IM btl4.exe > /dev/null 2>&1
|
||||
sleep 2
|
||||
}
|
||||
|
||||
DRIVE="BT_FORCE_SEEK=3 BT_AUTODRIVE=1.0 BT_FORCE_TURN=0.12"
|
||||
|
||||
run_one vul_A_bal 165 $DRIVE
|
||||
run_one vul_B_d50 165 $DRIVE BT_VALVE5=2
|
||||
run_one vul_C_d0 165 $DRIVE BT_VALVE5=3
|
||||
run_one vul_D_shot 100 BT_VALVE5=3 BT_VALVE5_AT=900 BT_VALVE5_SPACING=600 \
|
||||
BT_SHOT_EVERY=90 BT_SHOT_PREFIX=vlv
|
||||
|
||||
echo "=================== m173v RUNS DONE ==================="
|
||||
for f in m173_vul_A_bal.log m173_vul_B_d50.log m173_vul_C_d0.log m173_vul_D_shot.log; do
|
||||
echo "--- $f"
|
||||
grep -ac "myotemp" "$f" 2>/dev/null
|
||||
grep -a "\[valve" "$f" 2>/dev/null | head -40
|
||||
done
|
||||
ls vlv_*.png 2>/dev/null | head
|
||||
@@ -0,0 +1,68 @@
|
||||
# #173 valve experiment digest -- per run: valve receipts (PROOF of detent),
|
||||
# time-to-degradation-1000, equilibrium T, held speed, C5/bank finals.
|
||||
import re, sys, statistics as st
|
||||
|
||||
def digest(path):
|
||||
myotemp = [] # (t, T)
|
||||
myoheat = [] # (v, a, dt)
|
||||
myo = [] # speedEffect samples in file order
|
||||
c5 = []; bank = []
|
||||
presses = [] # ([valve-tx] BT_VALVE5 press lines)
|
||||
detents = [] # ([valve] CondenserN valve -> detent D lines)
|
||||
redist = [] # ([valve] condenser#N valveState=V flow=F (total=T))
|
||||
for ln in open(path, encoding='latin-1', errors='replace'):
|
||||
m = re.search(r"\[myotemp\] t=([\d.eE+-]+) T=([\d.eE+-]+)", ln)
|
||||
if m: myotemp.append((float(m.group(1)), float(m.group(2)))); continue
|
||||
m = re.search(r"\[myoheat\] v=([\d.eE+-]+) a=([\d.eE+-]+) m=[\d.eE+-]+ g=[\d.eE+-]+ ratio=[\d.eE+-]+ dmgGain=[\d.eE+-]+ dt=([\d.eE+-]+)", ln)
|
||||
if m: myoheat.append(tuple(map(float, m.groups()))); continue
|
||||
m = re.search(r"\[myo\] Myomers.* speed=([\d.eE+-]+).* gear=(\d+)", ln)
|
||||
if m: myo.append((float(m.group(1)), int(m.group(2)))); continue
|
||||
m = re.search(r"\[heat-t\] (\S+)( \(bank\))? T=([\d.eE+-]+)", ln)
|
||||
if m:
|
||||
name, isbank, T = m.group(1), m.group(2), float(m.group(3))
|
||||
if name == 'Condenser5': c5.append(T)
|
||||
elif isbank or name == 'HeatSink': bank.append(T)
|
||||
continue
|
||||
if '[valve-tx] BT_VALVE5' in ln: presses.append(ln.strip()); continue
|
||||
m = re.search(r"\[valve\] (Condenser\d+) valve -> detent (\d+)", ln)
|
||||
if m: detents.append((m.group(1), int(m.group(2)))); continue
|
||||
m = re.search(r"\[valve\] condenser#(\d) valveState=(\d+) flow=([\d.eE+-]+) \(total=(\d+)\)", ln)
|
||||
if m: redist.append(tuple(int(x) if i != 2 else float(x) for i, x in enumerate(m.groups()))); continue
|
||||
|
||||
name = path.split('m173_')[-1].replace('.log', '')
|
||||
print("=" * 78)
|
||||
print("RUN %s" % name)
|
||||
if presses:
|
||||
for p in presses: print(" " + p)
|
||||
if detents:
|
||||
print(" detent walk: " + " -> ".join("%s:%d" % d for d in detents))
|
||||
# final redistribute state (last 6 lines)
|
||||
if redist:
|
||||
last6 = redist[-6:]
|
||||
print(" final shares: " + " ".join("#%d v=%d f=%.4f" % (n, v, f) for (n, v, f, t) in last6)
|
||||
+ " (total=%d)" % last6[-1][3])
|
||||
if not myotemp:
|
||||
print(" NO MYOTEMP DATA"); return
|
||||
t_end = myotemp[-1][0]
|
||||
t1000 = next((t for t, T in myotemp if T >= 1000), None)
|
||||
t2000 = next((t for t, T in myotemp if T >= 2000), None)
|
||||
Tpk = max(T for _, T in myotemp)
|
||||
late = [T for t, T in myotemp if t > t_end - 40.0]
|
||||
k = max(2, len(myotemp) // 5)
|
||||
dT = (myotemp[-1][1] - myotemp[-k][1]) / max(1e-6, (myotemp[-1][0] - myotemp[-k][0]))
|
||||
# pair myoheat with myotemp by index (printed in lockstep)
|
||||
n = min(len(myoheat), len(myotemp))
|
||||
vlate = [myoheat[i][0] for i in range(n) if myotemp[i][0] > t_end - 40.0]
|
||||
vpk = max(x[0] for x in myoheat) if myoheat else 0.0
|
||||
selate = [s for s, g in myo[-20:]]
|
||||
gears = set(g for s, g in myo)
|
||||
print(" t1000=%s t2000=%s Tpeak=%.0f eqT(last40s)=%.0f endSlope=%+.2f/s (window %.1fs)"
|
||||
% ("%.1fs" % t1000 if t1000 else "NEVER", "%.1fs" % t2000 if t2000 else "never",
|
||||
Tpk, st.mean(late), dT, t_end))
|
||||
print(" vPeak=%.1f vHeld(last40s)=%.1f u/s speedEffect(last~20 samples)=%.2f gear(s)=%s"
|
||||
% (vpk, st.mean(vlate) if vlate else 0.0, st.mean(selate) if selate else 0.0, sorted(gears)))
|
||||
print(" Condenser5 end T=%.0f bank end T=%.0f" % (c5[-1] if c5 else 0, bank[-1] if bank else 0))
|
||||
|
||||
if __name__ == '__main__':
|
||||
for f in sys.argv[1:]:
|
||||
digest(f)
|
||||
Reference in New Issue
Block a user