freqresp gives wrong output for purely real inputs
11 visualizaciones (últimos 30 días)
Mostrar comentarios más antiguos
Will Robertson
el 17 de Mayo de 2020
I am stumped by the behaviour of evalfr vs freqresp in the control systems toolbox. They claim to give the same results, but when their arguments are purely real there is a (large!) discrepancy. I am inclined to believe the results from evalfr; for all sane transfer functions a real value of s should result in a real value of the transfer function.
With the following code:
G = tf([1],[1 1]);
wc = 3+1e-10*1i;
[evalfr(G,wc);freqresp(G,wc)]
Both give the answer 0.2500-0.0000i.
When the input is purely real, however:
G = tf([1],[1 1]);
wc = 3;
[evalfr(G,wc);freqresp(G,wc)]
ans =
0.2500 + 0.0000i
0.1000 - 0.3000i
I'm using Matlab 2020a and I believe this behaviour has been around for a while; I came across an old code comment that said something like "don't use freqresp -- evalfr gives proper results here". Fine for me, but harder to advise when teaching students...
2 comentarios
Devineni Aslesha
el 22 de Mayo de 2020
Could you share the link for where you saw the comment "don't use freqresp -- evalfr gives proper results here"?
Respuesta aceptada
Devineni Aslesha
el 26 de Mayo de 2020
Hi Will,
I have brought the issue of 'freqresp accepting frequency input with non-zero imaginary part' to the notice of our developers. They will investigate the matter further.
5 comentarios
Paul
el 3 de Jun. de 2020
Editada: Paul
el 4 de Jun. de 2020
- I agree with Will on point 1. The documenation is crystal clear. The input w must be real and the output is defined using the standard definition of freuqency response for either a continous or discrete system. I'm not sure why there's any reason for freqresp to accept an input with non-zero imaginary part. One might think that it should for backwards compatibility with the old version of freqresp (which is still usable, see my example below). But IMO that argument doesn't work because freqresp as currently implemented already has a different behavior than the old version for a real input. So that backwards compatibilty was lost anyway. At the very least, if freqresp is going to continue to accept complex inputs, it should generate a warning that that's unodocumented behavior, and it should be deprecated. And the same goes for the old version of freqresp.
- Zhao, I can't comment on Will's point. But freqresp does return inconsistent results. Please check my example below that shows freqresp (the current version) returns different outputs for the same input. Surely that can't be acceptable.
- As to Will's point 3, I agree that the documentation for evalfr is misleading. In fact, I think the name of the function is misleading. It should be evaltf. The very description says: "evaluates the transfer function ..." (emphasis added).
- As has been well established we have for continuous time systems: evalfr(G,1j*w) == freqresp(G,w) with w real. I'd like to add that if G is a model for a discrete time system then we have: evalfr(G,exp(1j*w*G.Ts) == freqresp(G,w) if G.Ts is defined and w is real, and evalfr(G,exp(1j*w) == freqresp(G,w) if G.Ts is undefined.
- The doc pages for evalfr and freqresp are pretty weak at explaining how these functions relate to each other, and the "More About" and "Algorithm" sections of doc freqresp are weak at explaining the discrete time case.
Más respuestas (1)
Paul
el 24 de Mayo de 2020
evalfr evalutes the transfer function at the value of the input argument, which can be an arbitrary complex number. For your example, evalfr(G,wc) = G(wc).
freqresp evaluates the frequency response at the value of the input argument, which must be real (doc freqresp). Because it's the frequency response, freqresp(G,wc) = G(1j*wc) (as long as wc is real).
So if you want to compute the frequency response of G using evalfr, you have to multiply the (real) input by 1j:
>> wc = 3; [evalfr(G,1j*wc); freqresp(G,wc)]
ans =
0.1000 - 0.3000i
0.1000 - 0.3000i
If you want to evaluate the transfer function of G at a complex number with non-zero real part, then your only choice is evalfr(G,s).
Check the doc pages for both functions.
Having said that, in 2019a the doc page for evalfr is missing the sections for the details on the input and output arguments. But it's all pretty clear from what is shown on that doc page.
3 comentarios
Paul
el 25 de Mayo de 2020
Editada: Paul
el 25 de Mayo de 2020
Will,
My statement that you quoted was intendended to be general in that I was thinking that 3, as in your example, is a complex number. I'm also suprised that freqresp (for a tf object like G, and probaby for its superclasses) accepts a frequency input with a non-zero imaginary part. And the situation is even worse than I thought. Consider:
>> G=tf(1,[1 1]);h1=freqresp(G,3);h2=freqresp(G,[3; 1+3*1i]);[h1 h2(1)]
ans =
0.1000 - 0.3000i 0.2500 + 0.0000i
freqresp computed a different output for the same input. Which is troubling. Though I can't say it's a bug because that second call to compute h2 is invalid anyway.
Then on top of this, the old-style use of freqresp is still usable, though I'm not sure if it's still supported functionality:
>> freqresp(1,[1 1],3)
ans =
0.2500
Apprarently freqresp used to work like evalfr works now.
Ver también
Productos
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!