45. Asymptotic Bode diagrams¶
One of the big advantages of Bode diagrams is that they are very easy to sketch out by hand (or, equivalently, to visualise mentally).
[1]:
import numpy
import matplotlib.pyplot as plt
%matplotlib inline
[2]:
omega = numpy.logspace(-2, 2, 1000)
s = 1j*omega
46. Systems with real poles¶
Let’s study the bode diagrams of systems of the form
\[\frac{K}{(\tau s + 1)^n}\]
[3]:
def annotated_bode(ax_gain, ax_phase, G, K, tau, order):
high_freq_asymptote = K/(tau*omega)**order
# Gain part
ax_gain.loglog(omega, numpy.abs(G))
ax_gain.axhline(K, color='grey') # Rule 1
ax_gain.loglog(omega, high_freq_asymptote, color='grey') # Rule 2
ax_gain.axvline(1/tau, color='grey') # Rule 2
ax_gain.set_ylim([1e-2, 1e+1])
ax_gain.set_ylabel('|G|')
# Phase part
ax_phase.axhline(0, color='grey') # Rule 3
ax_phase.semilogx(omega, numpy.unwrap(numpy.angle(G)))
ax_phase.axhline(-numpy.pi/2*order, color='grey') # Rule 4
ax_phase.axvline(1/tau, color='grey') # Rule 5
ax_phase.set_ylim([-3*numpy.pi/2, 2*numpy.pi/2])
ax_phase.set_ylabel(r'$\angle G$')
[4]:
def plotresponse(order=1, tau=1, K=1):
G = K/(tau*s + 1)**order
fig, [ax_gain, ax_phase] = plt.subplots(2, 1)
annotated_bode(ax_gain, ax_phase, G, K, tau, order)
[5]:
from ipywidgets import interact
[6]:
interact(plotresponse, order=(-2, 3), tau=(0.1, 10), K=(-1., 2));
We see that we can construct a reasonable approximation by knowing a couple of things
- The gain (\(K\)) of the system defines the low frequency asymptote of the gain graph
- The high frequency asymptote of the gain is \(\frac{K}{(\omega\tau)^n}\). Effectively, on a loglog scale, this means we have -n/decade slope above frequencies of around \(1/\tau\)
- The low frequency phase asymptote is 0
- The high frequency phase asymptote is \(-n\pi/2\)
- The phase curve has an inflection at \(1/\tau\)
47. Systems with complex poles¶
Systems with complex poles show uniique frequency response behaviour. We will focus on the second order system shown below:
\[G = \frac{K}{\tau^2 s^2 + 2\tau\zeta s + 1}\]
[7]:
def plotresponse(K=1, tau=1, zeta=1):
plt.figure(figsize=(15, 5))
order = 2
G = K/(tau**2*s**2 + 2*tau*zeta*s + 1)
ax_gain = plt.subplot2grid((2, 2), (0, 0))
ax_phase = plt.subplot2grid((2, 2), (1, 0))
ax_complex = plt.subplot2grid((2, 2), (0, 1), rowspan=2)
annotated_bode(ax_gain, ax_phase, G, K, tau, order)
# poles
poles = numpy.roots([tau**2, 2*tau*zeta, 1])
ax_complex.scatter(poles.real, poles.imag)
ax_complex.axhline(0)
ax_complex.axvline(0)
ax_complex.axis([-2, 2, -2, 2])
[8]:
interact(plotresponse, K=(0.1, 2), tau=(0.1, 2), zeta=(0., 1.1))
[8]:
<function __main__.plotresponse(K=1, tau=1, zeta=1)>
We see that the rules from before still hold, except that we start seeing the so-called “harmonic nose” emerge when \(\zeta<\sqrt{2}/2\approx{0.7}\). The maximum of the nose occurs at the resonant frequency of
\[\omega_r = \frac{\sqrt{1 - 2\zeta^2}}{\tau}\]
48. Dead time¶
The effect of dead time is to increase the phase lag indefinitely as a function of frequency. Delay has no effect on the gain of a system.
[9]:
D = 1
G = numpy.exp(-D*s)
[10]:
plt.semilogx(omega, numpy.unwrap(numpy.angle(G)))
[10]:
[<matplotlib.lines.Line2D at 0x117a944e0>]
