A 3D printer's firmware wants a model of its heated print bed, so that its controller can be tuned for it. It runs one test: from sample 0 the heater gets a constant power (in watts), and the bed's temperature rise above the room is logged once a second in temps (°C). The bed is a first-order system:
y[k] = a * y[k-1] + b * power for k = 1, 2, ...
but a (the share of the rise kept from one second to the next) and b (°C per second gained per watt) are unknown. Finding them from measurements is called system identification.
Look at the pairs of consecutive samples (p, q) = (temps[k-1], temps[k]). The model says that every pair lies on the straight line q = a * p + c with c = b * power. Real readings are slightly noisy, so the points scatter around that line, and the best line is the least-squares line (the one that makes the sum of squared vertical misses as small as possible). With pm and qm the means of all the p and all the q values:
a = sum((p - pm) * (q - qm)) / sum((p - pm) ** 2)
c = qm - a * pm
Write identify_bed(temps, power) that returns a tuple of three numbers: a, b = c / power, and the final rise the model predicts, c / (1 - a) (where y[k] = y[k-1]).
Examples
Input: temps = [0, 10, 19, 27.1, 34.39], power = 20
Output: (0.9, 0.5, 100.0)
Explanation: the pairs (0, 10), (10, 19), (19, 27.1), (27.1, 34.39) lie exactly on q = 0.9 * p + 10,
so a = 0.9, b = 10 / 20 = 0.5, and the bed would settle 100 °C above the room.
Input: temps = [0, 9.8, 19.3, 27.0, 34.6], power = 20
Output: (0.9066169175426531, 0.4979848865732146, 106.65419762742806)
Explanation: the same bed with sensor noise: the fit is close to, but not exactly, the true model.
Constraints
len(temps) >= 3, andtemps[:-1]are not all equal- answers are compared with a tolerance of
1e-6; do not round
Goals
- Recover the coefficients of a first-order model from a recorded step response
- Fit a straight line through pairs of consecutive samples
- Turn the fitted coefficients into a prediction of the final value