From 868c35f4e8ab66c09e91c9eabd28b075ffa423a0 Mon Sep 17 00:00:00 2001 From: Jens Ahrensfeld Date: Mon, 22 Jun 2026 19:01:28 +0200 Subject: [PATCH] SudForecastEstimator no longer needs plant_params - the doc supplies it sud.start() synchronously fires the first step's on_step_changed callback before it even returns (assigning Sud.step triggers callbacks immediately), which sets M/C/L/Td from this doc's own derive_plant_params() before any pot.process()/tc.process() tick ever runs - so the constructor's plant_params was being set, then immediately discarded, unused. theta_amb stays, since it's not part of the Sud doc at all. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01DkkuG48uHFCGKe6dPSERFk --- components/sud_forecast.py | 12 +++++++----- server/brewpi.py | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/components/sud_forecast.py b/components/sud_forecast.py index 0798123..3434f27 100644 --- a/components/sud_forecast.py +++ b/components/sud_forecast.py @@ -22,10 +22,9 @@ class SudForecastEstimator: spin-up/settling lag, which is exactly why its estimate drifted so far from reality (see README.md's "Forecast vs. actual duration").""" - def __init__(self, dt, theta_amb, plant_params, pid_type, tempctrl_params, heater_max_power): + def __init__(self, dt, theta_amb, pid_type, tempctrl_params, heater_max_power): self.dt = dt self.theta_amb = theta_amb - self.plant_params = plant_params self.pid_type = pid_type self.tempctrl_params = tempctrl_params self.heater_max_power = heater_max_power @@ -61,14 +60,17 @@ class SudForecastEstimator: if not sud.load(doc) or not sud.schedule: return [0.0], [start_theta], SudState.DONE, [] + # Plant params (M/C/L/Td) are deliberately *not* seeded here from + # any default - sud.start() below synchronously fires the first + # step's on_step_changed callback (assigning Sud.step triggers + # its callbacks immediately, before sud.start() even returns), + # which sets them from this doc's own derive_plant_params() - see + # there - before any pot.process()/tc.process() tick ever runs. pot = Pot(self.dt) - pot.set_plant_params(self.plant_params) pot.set_ambient_temperature(self.theta_amb) pot.initial(start_theta) tc = PidFactory.create(self.pid_type, self.dt) tc.set_params(self.tempctrl_params) - if hasattr(tc, 'set_model_plant_params'): - tc.set_model_plant_params(self.plant_params) if hasattr(tc, 'set_ambient_temperature'): tc.set_ambient_temperature(self.theta_amb) tc.set_enabled(True) diff --git a/server/brewpi.py b/server/brewpi.py index 0f72e93..5d4b9ab 100755 --- a/server/brewpi.py +++ b/server/brewpi.py @@ -111,7 +111,7 @@ if __name__ == '__main__': # it with the same kind of plant/controller (and params) as above - # see components/sud_forecast.py. forecast_estimator = SudForecastEstimator( - DT, theta_amb, DEFAULT_PLANT_PARAMS, config['Controller']['pid_type'], config['TempCtrl'], heater.get_power_max()) + DT, theta_amb, config['Controller']['pid_type'], config['TempCtrl'], heater.get_power_max()) sud_task = SudTask(sud, tc, stirrer, pot, DT, DT_TASK, dispatcher.msgio_get("Sud"), forecast_estimator) taskmgr.add(sud_task) # Records every Sud run's measured data and forecast to their own