Add interactive "How balancing works" page to the website#516
Conversation
A new homeowner-friendly page (how-balancing-works.html) with a live canvas simulation of the grid-balancing control loop. A synthetic household load wanders and spikes while the battery chases the grid back to zero; three toggles let visitors switch off latency compensation, smooth ramping, and anti-oscillation to see the overshoot/hunting each one prevents. The toy model in ts/balancing.ts is a deliberately simplified cartoon of the real controller (predictor / pacing / oscillation damping in balancer.py), kept pure so balancing.test.ts can assert each mechanism measurably steadies the simulated grid. Wired into the build (new HTML page + esbuild entry point), linked from the nav and the landing "How it works" section. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011iig48zU6fkxczi4SeVwMv
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
🧹 The preview for this PR has been removed now that it is closed. |
Steering evaluation (base vs head)Overall: 0 improved, 0 regressed, 14 unchanged across 14 metrics — mean 0% (unchanged). Priority: priority-weighted 0% (unchanged) — ✅ no do-no-harm guardrail regressions. Lower is better for every metric. See Metrics are the per-scenario mean of 5 seeds. Aggregate — mean across 31 scenarios
📊 Interactive grid-power charts (zoom / hover / toggle series) are in the self-contained What do these metrics mean?
Per-scenario tables (31 scenarios)mixed_cadence/eff — settle 26.1→26.1s, overshoot 232.6→232.6W, RMS 25.6→25.6W
mixed_cadence/fair — settle 24.8→24.8s, overshoot 176.3→176.3W, RMS 13.1→13.1W
mixed_cadence_solar/eff — settle 34.6→34.6s, overshoot 351.2→351.2W, RMS 30.3→30.3W
mixed_cadence_solar/fair — settle 30.8→30.8s, overshoot 169.0→169.0W, RMS 20.3→20.3W
mixed_venus_b2500/eff — settle 56.2→56.2s, overshoot 220.6→220.6W, RMS 14.9→14.9W
mixed_venus_b2500/fair — settle 30.1→30.1s, overshoot 106.9→106.9W, RMS 13.2→13.2W
phase_imbalance — settle 44.9→44.9s, overshoot 166.7→166.7W, RMS 30.2→30.2W
single_venus_d_solar — settle 24.2→24.2s, overshoot 94.4→94.4W, RMS 15.9→15.9W
single_venus_d_steps — settle 26.3→26.3s, overshoot 90.3→90.3W, RMS 15.5→15.5W
single_venus_d_washer — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 61.0→61.0W
single_venus_drain — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 907.3→907.3W
single_venus_fill — settle 360.0→360.0s, overshoot 0.0→0.0W, RMS 953.6→953.6W
single_venus_noisy — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.3→94.3W
single_venus_pv — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 60.8→60.8W
single_venus_solar — settle 26.8→26.8s, overshoot 80.3→80.3W, RMS 17.8→17.8W
single_venus_solar_slow — settle 33.9→33.9s, overshoot 68.3→68.3W, RMS 22.8→22.8W
single_venus_steps — settle 26.0→26.0s, overshoot 88.0→88.0W, RMS 14.7→14.7W
single_venus_steps_slow — settle 40.5→40.5s, overshoot 98.5→98.5W, RMS 14.8→14.8W
single_venus_trace — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 278.9→278.9W
single_venus_washer — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 61.0→61.0W
two_venus/eff — settle 18.9→18.9s, overshoot 150.3→150.3W, RMS 13.9→13.9W
two_venus/fair — settle 18.2→18.2s, overshoot 128.7→128.7W, RMS 13.8→13.8W
two_venus_noisy/eff — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.5→94.5W
two_venus_noisy/fair — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 94.5→94.5W
two_venus_slow/fair — settle 41.3→41.3s, overshoot 181.1→181.1W, RMS 14.0→14.0W
two_venus_solar/eff — settle 25.5→25.5s, overshoot 417.5→417.5W, RMS 19.6→19.6W
two_venus_solar/fair — settle 22.7→22.7s, overshoot 139.8→139.8W, RMS 19.4→19.4W
two_venus_trace/eff — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 283.2→283.2W
two_venus_trace/fair — settle 0.0→0.0s, overshoot 0.0→0.0W, RMS 282.6→282.6W
venus_d_plus_c/eff — settle 17.4→17.4s, overshoot 175.4→175.4W, RMS 14.7→14.7W
venus_d_plus_c/fair — settle 18.6→18.6s, overshoot 118.4→118.4W, RMS 14.6→14.6W
📊 Open the interactive report — |
The previous predictor credited the battery's output change but then re-applied the stale meter error every tick, so during the meter's dead-time window it over-corrected ~7x and hunted — the demo oscillated even at its smooth default. Replace it with a proper dead-time compensator: estimate the current grid as meter - (battOut_now - battOut_when_meter_was_sampled), adding back the corrections the meter has not yet reflected. Add a sub-unity control gain so the approach ramps smoothly, a discharge ceiling so the un-compensated loop stays on-screen, and stronger oscillation-damping params so that toggle has a visible effect. Default now settles with zero sign-flips (RMS ~120 vs ~1500 with compensation off). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011iig48zU6fkxczi4SeVwMv
Analysis showed the three-toggle design was fundamentally flawed: in a dead-time-compensated single loop, ramp pacing moves the aggregate error essentially zero and damping barely registers — only latency compensation matters. Two of the three toggles were effectively dead, so flipping them did nothing, which is what made the demo feel useless. Replace the toggles with a continuous side-by-side race on the *same* household load: a plain meter-follower (textbook dead-time instability, hunts ±~1000 W) versus AstraMeter (latency-compensated, eased, damped — holds the grid at ~10 W RMS). The contrast is self-evident and live, with no dead controls; the only interactive toggle just shows/hides the naive line. A small input deadband and a calm baseline load keep AstraMeter's line genuinely flat between events. The per-trick toggles remain in the model API and are still asserted by the test suite (latency compensation does the heavy lifting; the smart controller converges and holds while the naive one hunts). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011iig48zU6fkxczi4SeVwMv
The side-by-side race showed *that* AstraMeter is better but not *how*. Add an animated meter-lag explainer as the opening section: a scripted "kettle" disturbance plotted against the same signal delayed by the meter's reporting lag, so the delay is visible as a horizontal offset between reality (green) and what the meter reports (grey). Two plain panels explain the consequence (a basic battery chases the late reading and overshoots) and the fix (AstraMeter adds back what it just commanded, so it acts on the real grid now). The page now reads problem -> mechanism -> payoff: the lag explainer, then the live race, then the plain-language recap of all the tricks. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011iig48zU6fkxczi4SeVwMv
A new homeowner-friendly page (how-balancing-works.html) with a live canvas simulation of the grid-balancing control loop. A synthetic household load wanders and spikes while the battery chases the grid back to zero; three toggles let visitors switch off latency compensation, smooth ramping, and anti-oscillation to see the overshoot/hunting each one prevents.
The toy model in ts/balancing.ts is a deliberately simplified cartoon of the real controller (predictor / pacing / oscillation damping in balancer.py), kept pure so balancing.test.ts can assert each mechanism measurably steadies the simulated grid. Wired into the build (new HTML page + esbuild entry point), linked from the nav and the landing "How it works" section.
Claude-Session: https://claude.ai/code/session_011iig48zU6fkxczi4SeVwMv