[1]:
import sympy
sympy.init_printing()
%matplotlib inline

3. Sinusoidal response

In this notebook we will look at the response of first and second order systems to sinusoidal inputs. Recall that we always assume inputs were zero for times less than zero, so in fact the input looks like this:

\[\begin{split}u_{sin}(t) = \begin{cases}0 & t<0\\A\sin(\omega t) & t \geq 0 \end{cases}\end{split}\]

We will define our symbols in such a way that the positive \(t\) is assumed and Sympy will do the math correctly.

[24]:
A, t, omega = sympy.symbols('A, t, omega', positive=True)
s = sympy.Symbol('s')

So we can define our input like this and get the same Laplace transform as in our table of standard transforms:

[25]:
usin = A*sympy.sin(t*omega)
[26]:
usin_s = sympy.laplace_transform(usin, t, s, noconds=True)
usin_s
[26]:
$$\frac{A \omega}{\omega^{2} + s^{2}}$$

3.1. First order

Let’s explore how first order systems respond to this kind of input:

[27]:
K, tau = sympy.symbols('K, tau', positive=True)
[28]:
G = K/(tau*s + 1)
[29]:
y = G*usin_s
[35]:
yt = sympy.inverse_laplace_transform(y, s, t)
yt
[35]:
$$\frac{A K e^{- \frac{t}{\tau}}}{\left(i \omega \tau - 1\right)^{2} \left(i \omega \tau + 1\right)^{2}} \left(\omega^{2} \tau^{2} + 1\right) \left(- \omega \tau e^{\frac{t}{\tau}} \cos{\left (\omega t \right )} + \omega \tau + e^{\frac{t}{\tau}} \sin{\left (\omega t \right )}\right)$$
[37]:
yt = yt.simplify().expand()
yt
[37]:
$$- \frac{A K \omega \tau e^{\frac{t}{\tau}} \cos{\left (\omega t \right )}}{\omega^{2} \tau^{2} e^{\frac{t}{\tau}} + e^{\frac{t}{\tau}}} + \frac{A K \omega \tau}{\omega^{2} \tau^{2} e^{\frac{t}{\tau}} + e^{\frac{t}{\tau}}} + \frac{A K e^{\frac{t}{\tau}} \sin{\left (\omega t \right )}}{\omega^{2} \tau^{2} e^{\frac{t}{\tau}} + e^{\frac{t}{\tau}}}$$
[38]:
def response(omega_, A_, tau_, K_):
    sympy.plot(usin.subs({omega: omega_, A: A_}),
               yt.subs({A: A_, tau: tau_, K: K_, omega: omega_}),
               (t, 0, 30), ylim=(-2, 2))
[39]:
from ipywidgets import interact
[40]:
interact(response,
         omega_=(0.1, 10.),
         A_=(0.1, 2.),
         tau_=(0.1, 10.),
         K_=(-0.1, 2.))
[40]:
<function __main__.response(omega_, A_, tau_, K_)>

We see the response is eventually sinusoidal.

3.2. Second order sinusoidal response

[41]:
zeta = sympy.Symbol('zeta', positive=True)
[42]:
G2 = K/(tau**2*s**2 + 2*tau*zeta*s + 1)
G2
[42]:
$$\frac{K}{s^{2} \tau^{2} + 2 s \tau \zeta + 1}$$

Sympy can calculate this response analytically.

Warning: This next cell takes quite a long time.

[43]:
yt = sympy.inverse_laplace_transform(G2*usin_s, s, t)
[44]:
def response(omega_, A_, K_, tau_, zeta_):
    sympy.plot(usin.subs({omega: omega_, A: A_}),
               yt.subs({A: A_, tau: tau_, K: K_, zeta: zeta_, omega: omega_}),
               (t, 0, 20), ylim=(-2, 2))
[45]:
interact(response,
         omega_=(0.1, 10.),
         A_=(0.1, 2.),
         tau_=(0.1, 10.),
         K_=(-0.1, 2.),
         zeta_=(0.1, 1.2))
[45]:
<function __main__.response(omega_, A_, K_, tau_, zeta_)>

Again we see that the response is eventually sinusoidal, with a longer transient. Unlike the first order system, there are frequencies where the output is larger than the input when the system is underdamped. This is known as a harmonic response:

[18]:
response(0.5, 1, 1, 1.1, 0.4)
../../_images/1_Dynamics_4_First_and_second_order_system_dynamics_Sinusoidal_response_25_0.png

3.3. Amplitude over frequency

It can be shown (unfortunately SymPy is not quite up to the task) that for first order processes, the eventual magnitude of the sinusoidal responses are as follows:

It is useful to plot the normalised amplitude ratio (the above amplitudes divided by \(KA\)) of the two systems as a function of frequency:

[19]:
firstorder = 1/sympy.sqrt(omega**2*tau**2 + 1)
secondorder = 1/sympy.sqrt((1 - omega**2*tau**2)**2 + (2*zeta*omega*tau)**2)
[20]:
def frequencyplot(tau_, zeta_):
    sympy.plot(firstorder.subs({tau: tau_}),
               secondorder.subs({tau: tau_, zeta: zeta_}),
               (omega, 0.1, 10),
               xscale='log',
              )
[21]:
interact(frequencyplot, tau_=(0.01, 4), zeta_=(0.1, 1.2))
[21]:
<function __main__.frequencyplot(tau_, zeta_)>

It is clear that the value of \(\tau\) determines the frequency of the peak in the second order plot. This peak is known as the “harmonic nose” and is only larger than 1 when \(0<\zeta<0.7\).

[22]:
frequencyplot(1, 0.7)
../../_images/1_Dynamics_4_First_and_second_order_system_dynamics_Sinusoidal_response_33_0.png
[23]:
frequencyplot(1, 0.6)
../../_images/1_Dynamics_4_First_and_second_order_system_dynamics_Sinusoidal_response_34_0.png
[ ]:

[ ]:

Read the Docs v: latest
Versions
latest
stable
Downloads
pdf
epub
On Read the Docs
Project Home
Builds

First order processes

\[\frac{KA}{\sqrt{\omega^2 \tau^2 + 1}}\]

Second order processes

\[\frac{KA}{\sqrt{(1 - \omega^2 \tau^2)^2 + (2\zeta\omega\tau)^2}}\]