docs: update Forecast vs. actual duration for the new server-side simulated estimate
This commit is contained in:
@@ -191,32 +191,37 @@ ever.
|
|||||||
|
|
||||||
### Forecast vs. actual duration
|
### Forecast vs. actual duration
|
||||||
|
|
||||||
The GUI's Automatic tab shows two different time estimates, and they can
|
The GUI's Automatic tab shows up to three time estimates for a schedule:
|
||||||
diverge substantially:
|
|
||||||
|
|
||||||
- Before a run starts, it shows a *static* estimate: walk the schedule
|
- Immediately on load, a quick *naive* preview: walk the schedule assuming
|
||||||
assuming every ramp instantly achieves and holds its declared `rate`
|
every ramp instantly achieves and holds its declared `rate`
|
||||||
(`abs(delta)/rate`) and every hold lasts exactly its declared `duration`.
|
(`abs(delta)/rate`) and every hold lasts exactly its declared `duration`.
|
||||||
- Once running, it switches to a *dynamic* one: the already-elapsed part is
|
Deliberately approximate - it's just a placeholder until the next one
|
||||||
the actual measured trace, and only the remaining steps are re-projected
|
arrives a moment later.
|
||||||
from the live temperature/step/`hold_remaining` each tick.
|
- A *simulated* estimate, computed server-side (`components/sud_forecast.py`'s
|
||||||
|
`SudForecastEstimator`) by actually running the schedule through a
|
||||||
|
throwaway `Sud`/`Pot`/temperature-controller trio built from the same
|
||||||
|
params (`pid_type`, `TempCtrl` gains, plant params, ambient, heater max
|
||||||
|
power) the real server uses - a multi-hour brew simulates in well under a
|
||||||
|
second since it's pure CPU-bound iteration, no real time/IO involved. This
|
||||||
|
replaces the naive preview a moment after a schedule is loaded.
|
||||||
|
- Once running, a *dynamic* one: the already-elapsed part is the actual
|
||||||
|
measured trace, and only the remaining steps are re-projected from the
|
||||||
|
live temperature/step/`hold_remaining` each tick.
|
||||||
|
|
||||||
In practice the dynamic total tends to run well above the static one - a
|
The naive estimate is structurally optimistic - it assumes the plant
|
||||||
schedule estimated at ~160 min commonly finishes closer to ~250-270 min.
|
instantly tracks the declared rate and that "reached" is instant once the
|
||||||
The static model assumes the plant instantly tracks the declared rate and
|
math says so, when the real PID cascade (`theta_err -> pid_hold ->
|
||||||
that "reached" is instant once the math says so; the real PID cascade
|
heatrate_soll -> pid_heat -> heater power -> actual heat rate`) needs real
|
||||||
(`theta_err -> pid_hold -> heatrate_soll -> pid_heat -> heater power ->
|
time to spin up and settle within the tight 0.2°C "reached" tolerance
|
||||||
actual heat rate`) needs real time to spin up (constrained by the plant's
|
(`tasks/sud.py`'s `TEMP_REACHED_TOLERANCE`). The simulated estimate accounts
|
||||||
thermal mass and the Smith predictor's transport-delay compensation) and
|
for that (it's driven by the real controller dynamics), so it's normally
|
||||||
then more time to settle within the tight 0.2°C "reached" tolerance
|
within a few percent of how the dynamic one settles once a run actually
|
||||||
(`tasks/sud.py`'s `TEMP_REACHED_TOLERANCE`) once nominally at target. That
|
finishes - if the two diverge by far more than that, suspect a real control
|
||||||
settling lag is roughly constant per step rather than proportional to the
|
issue rather than a forecasting one (see the `HoldCool` threshold note in
|
||||||
step's nominal duration, so it eats a larger fraction of short ramps and
|
`components/pid/temp_controller_base.py` - too tight a threshold there once
|
||||||
keeps accumulating across every ramp/hold transition in the schedule -
|
caused exactly this kind of large, otherwise-unexplained gap, by making the
|
||||||
many small (~20-90%) per-step overruns compounding into one large gap by
|
controller chatter in and out of `COOL` and never actually converge).
|
||||||
the end, rather than one big error anywhere in particular. The dynamic
|
|
||||||
re-anchoring is what corrects for this as a brew actually progresses; the
|
|
||||||
upfront static number has no settling-time data to work with yet.
|
|
||||||
|
|
||||||
## Logging & analysis
|
## Logging & analysis
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user