A greenhouse controller models how the air temperature y responds to the heater power x, one sample a minute, with a difference equation in the Level 2 form:
y[k] = c[0] * y[k-1] + c[1] * y[k-2] + ... + d[0] * u[k] + d[1] * u[k-1] + ...
where u[k] = x[k - delay]: the heat reaches the sensor only delay minutes after the heater switches (dead time). The feedback weights are c (c[i] multiplies y[k-1-i]) and the input weights are d.
To get the transfer function, write every delay as a power of z^-1 (y[k-1] becomes z^-1 * Y, x[k-delay-j] becomes z^-(delay+j) * X) and move every y term to the left:
Y * (1 - c[0] * z^-1 - c[1] * z^-2 - ...) = X * z^-delay * (d[0] + d[1] * z^-1 + ...)
so H(z) = Y / X = B(z) / A(z). The usual convention, used in the rest of this level, writes
a[0] * y[k] + a[1] * y[k-1] + a[2] * y[k-2] + ... = b[0] * x[k] + b[1] * x[k-1] + ...
with a[0] = 1: the feedback weights appear in a with the opposite sign.
Write to_transfer(c, d, delay) that returns the pair (b, a): a has len(c) + 1 entries starting with 1, and b has delay + len(d) entries (delay zeros, then the weights d).
Examples
Input: c = [0.9], d = [0.05], delay = 2
Output: ([0, 0, 0.05], [1, -0.9])
Explanation: y[k] = 0.9 y[k-1] + 0.05 x[k-2], so y[k] - 0.9 y[k-1] = 0.05 x[k-2]:
H(z) = 0.05 z^-2 / (1 - 0.9 z^-1).
Input: c = [1.2, -0.5], d = [0.1, 0.2], delay = 0
Output: ([0.1, 0.2], [1, -1.2, 0.5])
Explanation: the ride-height filter of Level 2.
Constraints
- answers are compared with a tolerance of
1e-6; lists may be given as tuples
Goals
- Turn a difference equation into the coefficient lists b and a of its transfer function
- Move the feedback terms to the left-hand side, which flips their signs
- Write a pure delay of d samples as d leading zeros in b