A greenhouse is heated to a target temperature r (°C). Each minute it loses heat to the outside air, whose temperature w a weather sensor measures. One minute of the greenhouse is
T[k+1] = a * T[k] + b * u[k] + (1 - a) * w[k]
with T the inside temperature, u the heater power in kW (between 0 and u_max), a (just below 1) the share of the inside temperature that is kept from one minute to the next, and b the warming per kW per minute.
A plain feedback controller, u = K * (r - T), only reacts once the cold has already cooled the greenhouse. But the outside temperature is measured, and the model says exactly how much power holds the greenhouse at r against a given w: setting T[k+1] = T[k] = r gives
u_ff = (1 - a) * (r - w[k]) / b (the feedforward power)
Feedforward adds this to the feedback: u = u_ff + K * (r - T). If the model is right and the heater has the power, the outside temperature no longer moves the inside one at all.
Simulate both controllers. Start each run at T = T0 and, for every minute k (one per entry of outside), in this order:
u = K * (r - T) (feedback)
u = u + (1 - a) * (r - w[k]) / b (only with feedforward)
u = min(max(u, 0), u_max) (the heater's limits)
T = a * T + b * u + (1 - a) * w[k]
and add (r - T) ** 2 (with the new T) to a sum. The RMS error is sqrt(sum / len(outside)).
Write greenhouse(r, T0, a, b, K, u_max, outside) that returns (rms_feedback_only, rms_with_feedforward). With an empty outside both are 0.0. Press Run with plot on your two temperature lists to see the feedback-only greenhouse sag on a cold night.
Examples
Input: r = 20, T0 = 20, a = 0.9, b = 0.5, K = 2, u_max = 30, outside = [5, 5, 0, 0, -5, -5, 0, 5]
Output: (1.8115517439527178, 0.0)
Explanation: feedback alone first lets the greenhouse cool to 18.5 °C (it heats only once there is
an error) and stays 1.3 to 2.3 °C low. With feedforward the heater supplies the loss before
it happens and the temperature never leaves 20 °C.
Input: r = 20, T0 = 20, a = 0.9, b = 0.5, K = 2, u_max = 4, outside = [5, 5, 0, 0, -5, -5, 0, 5]
Output: (1.9644385467957008, 0.4944890355205057)
Explanation: at -5 °C holding 20 °C takes 5 kW, but the heater gives at most 4: even feedforward
cannot cancel what the heater cannot supply.
Constraints
0 < a < 1,b > 0,K >= 0,u_max > 0- answers are compared with a tolerance of
1e-6; a list is accepted in place of the pair
Goals
- Compute a feedforward term that cancels a measured disturbance using the plant model
- Simulate the same loop with and without feedforward, step by step
- See where feedforward stops helping: when the actuator saturates