ControlSystems.jl
ControlSystems.jl copied to clipboard
bode() returns only phases in interval +/- 180°
If I want to determine the phase at some frequency using bode(G, w) with w as a 1-element vector, bode() only returns values in the interval (-180°, 180°).
This is a problem in case of higher-order systems or delay systems with phases below -180°.
This problem does not occur for vectors w with n>1 elements.
So is it a bug or a feature? :D
G = tf(1, [1, 3, 3, 1])
bode(G, [1.7]) # ϕ = -178°
bode(G, [1.78]) # ϕ = 177° is wrong, should be ϕ=-360° + 177° = -183°
This was discussed in #312, and I think the feeling is that it would be good to fix it, but #312 requires some more further work for MIMO and delay systems. The current behavior is at least consistent.
Have you seen the function unwrap
? I think you just need to unwrap
the entire phase curve
bodeplot(G)
will plot the phase correctly
Right, I was mixing things up. However, unwrap
will not by default give you what you want if there are more than one or two integrators.
Nope, the problem is still there if the phase starts at below -180 degrees (maybe already below -90?).
Yes, the general problem is that it is tricky to compute where the bode plot should start. Thus bode
assumes that the first frequency in the vector is "small enough", and "assumes" that the frequency there is in (-180,180). It will then unwrap from that frequency. That is why you see the problem when you only input one frequency.
Edit: I don't think it is feasible to compute the "correct" phase for arbitrary frequencies without
- starting at a low frequency
- computing based on the zeros and poles what multiple on 360 should be added
- Unwrapping from that frequency, with a fine enough grid, until the frequency you are interested in.
We do not do step 2 in this toolbox (see #312), and step 3 based on the vector you input.
Unwrap also fails if the change in frequency between two grid points is too large
w = exp10.(LinRange(-2, 5, 200))
P = tf(1,[1,1])*delay(1)
bodeplot(P, w)