z transfer function evaluates to inaccurate value near z=1
14 views (last 30 days)
Show older comments
Ashish Panpalia
on 3 Nov 2022
Commented: Ashish Panpalia
on 14 Nov 2022
I have a simple 6th order CIC (sinc2) filter made by follwoing commands:
z = tf('z',1);
tf = ((1-z^(-2))/(1-z^(-1)))^6;
This Transfer Function is known to have a magnitude = 64 at z=1.
I am trying to evaluate the magnitude of this transfer function using evalfr command as follows:
abs(evalfr(tf,exp(-2i*pi*1/10000)))
It evaluates to 8.0001 which is completely wrong.
However if I evaluate this function at a value slightly away from z=1, then it gives accurate answer:
abs(evalfr(tf,exp(-2i*pi*1/100))) >>> 63.8108
I also tried to plot the magnitude response of this filter using Filter Visualization Tool (fvtool). Even here I see the magnitude response very inaccurate when f is close to 0 (which corresponds to the case when z is close to 1).
regards,
Ashish
0 Comments
Accepted Answer
David Goodmanson
on 4 Nov 2022
Edited: David Goodmanson
on 4 Nov 2022
Hi Ashish,
This function,
((1-1/z^2)/(1-1/z))^6
is identically equal to
((z+1)/z)^6
so you can just use that. And it does equal 64 at z = 1.
More Answers (2)
Paul
on 13 Nov 2022
Edited: Paul
on 13 Nov 2022
Hi Ashish,
This problem illustrates a couple of things to keep in mind when using the Control System Toolbox
Here is the original code
format long e
z = tf('z',1);
However, we shouldn't use tf as a variable name because tf is a very important CST function that we don't want to shadow with a variable name
h = ((1-z^(-2))/(1-z^(-1)))^6
When using tf as above, we get very high order polynomials. The denominator polynmial has at least one root exactly at z = 1
polyval(h.den{:},1)
So bad things will happen when evaluating h at z = 1
evalfr(h,1)
However, we also know that the poles at z = 1 should cancel with zeros at z = 1. So we can try minreal
h = minreal(h)
However, minreal doesn't work very well because root finding of high-order polynomials with multiple, repeated roots is hard (or so I've been led to believe).
evalfr(h,1)
Alternatively, we could have used minreal from the start
h = (minreal((1-z^(-2))/(1-z^(-1))))^6
And then we get the expected result
evalfr(h,1)
Genereally speaking, the zpk form is preferred over the tf form (becuase of numerlcal robustess concerns when dealing with polynomials)
z = zpk('z',1);
h = ((1-z^(-2))/(1-z^(-1)))^6
This actually looks pretty good. Unfortunately, the display is misleading, as the poles (and zeros) are not exactly at z = 1.
h.p{:}.'
I'm a little bit surprised by this result, but I'm sure it's a result of how the CST has to do the algebraic manipulations in z
Consequently, evalfr still fails (and maybe this result is worse than the tf case because it's not obviously wrong)
evalfr((h),1)
However, the poles and zeros of h are close enough to unity that minreal works as desired
h = minreal(h)
evalfr(h,1)
Of course, we could have used minreal from the outset
h = (minreal((1-z^(-2))/(1-z^(-1))))^6
evalfr(h,1)
Also, it's worth pointing out that even this approach is not without issue. To wit:
h = minreal((1-z^-2)/(1-z^-1))
h.P{:}
h.Z{:}
So, even with this simple case, the numerical zero isn't exactly at -1. Continuing
h = h^6;
h.P{:}.'
h.Z{:}.'
isequal(evalfr(h,1),64)
I guess the rounding works in our favor and we get the exact, expected result.
The best approach would be to start with
h = zpk(-1,0,1,1)
h.Z{:}
Then
h = h^6
h.Z{:} % zeros exactly at z = -1
isequal(evalfr(h,1),64)
Summary: avoid the tf form if possible (the doc talks about this), simplify earlier rather than later, avoid or minimize "transfer function algebra" if possible.
2 Comments
William Rose
on 4 Nov 2022
The function is tricky, as z approaches 1, since the numerator and denominator both tend toward zero.
Why do you think G(z=1)=64?
which goes toward as z tends toward +1.
L'Hopital's rule predicts something similar: d(numerator)/dz is finite and positive, d(denominator)/dz goes to zero, so G(z) goes to infinity as z goes toward +1.
You tried approaching the point z=1 from below on the unit circle, with values such as z=exp(-i*(2*pi/100)), z=exp(-i*(2*pi/1e3)), etc. The strange results you observed are due to round off error as the numerator and denominator both approach zero. If you approach z along the real axis, from more positive values, or along the real axis from less positive values, you also get wrong answers, but they are quite different wrong answers. It just shows that the function G(z) is not nice near z=1.
See Also
Categories
Find more on Digital Filter Analysis in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!