Solved Various Problem Sets#

from IPython.display import display, Markdown

from sympy import *
from sympy.interactive.printing import init_printing
from sympy.abc import s, K, k, t

from mathprint import *

Problem 1#

Topics: block diagram, second-order system

Determine the values of \(K\) and \(k\) such that the system has a damping ratio \(\zeta\) of 0.7 and an undamped natural frequency \(\omega_n\) of \(4 \mathrm{rad} / \mathrm{sec}\).

Solution#

First, simplify the blockdiagram:

G = K / (s+2)
S1 = (G / (1+G*k)) * (1/s) # negative feedback and serial connection
S2 = S1 / (1+S1) # another negative feedback
S2 = collect(expand(simplify(S2)), [s**2, s]) # make it nice

mprint("\\frac{C(s)}{R(s)}=", latex(S2))
\[\displaystyle \frac{C(s)}{R(s)}=\frac{K}{K + s^{2} + s \left(K k + 2\right)}\]

Next, the coeficient of \(s\) is \(2 \zeta \omega_n\) and \(K=\omega_n^2\).

zeta = 0.7
omegan = 4

# Take the denom, find the coefficient of s,
# set it equals to 2 * zeta 8 omega_n
eq = Eq(denom(S2).coeff(s), 2*zeta*omegan)
display(eq)

# Set K = omega_n^2
eq = eq.subs(K, omegan**2)
display(eq)
\[\displaystyle K k + 2 = 5.6\]
\[\displaystyle 16 k + 2 = 5.6\]

Solve for \(k\):

k_ = solveset(eq, k)
mprint("k=", latex(k_))
\[\displaystyle k=\left\{0.225\right\}\]

So, the final answer is \(k=0.225\).

Problem 2#

Topics: block diagram, second-order system

Determine the value of \(k\) such that the damping ratio \(\zeta\) is 0.5 . Then obtain the rise time \(t_r\), peak time \(t_p\), maximum overshoot \(M_p\), and settling time \(t_s\) in the unit-step response.

Solution#

First, simplify the blockdiagram:

G = 16 / (s+0.8) 

S1 = (G / (1+G*k)) * (1/s) # negative feedback and serial connection
S2 = S1 / (1+S1) # another negative feedback
S2 = collect(expand(simplify(S2)), [s**2, s]) # make it nice

mprint("\\frac{C(s)}{R(s)}=", latex(S2))
\[\displaystyle \frac{C(s)}{R(s)}=\frac{16}{s^{2} + s \left(16 k + 0.8\right) + 16}\]

Finding \(k\) for \(\zeta = 0,5\) and \(\omega_n = 4\). Note that the coeficient of \(s\) is \(2 \zeta \omega_n\).

zeta = 0.5
omegan = 4 #sqrt(16)

# Take the demom, find the coefficient of s,
# set it equals to 2 * zeta 8 omega_n
eq = Eq(denom(S2).coeff(s), 2*zeta*omegan)

kval = solve(eq, k)

mprint("k=", latex(kval[0]))
\[\displaystyle k=0.2\]

Thus, \(k=0.2\).

Finally, conclude the system, convert it to a transfer function.

To push things a bit further, we will apply inverse Laplace to bring the response back to time-domain and allow us to plot the result.

Please note that SymPy does have a generic function for plotting a step response out of an s-domanin transfer function. However, we are not going to use it here.

G = S2.subs(k, 0.2)
mprint("G(s)=", latex(G))
\[\displaystyle G(s)=\frac{16}{s^{2} + 4.0 s + 16}\]
from sympy.plotting import plot

C = 1/s * G
c = inverse_laplace_transform(C, s, t)

plot(c, (t, 0, 5), size=(4, 3), ylabel="$c(t)$", show=True);
_images/fab474b78ec598a95f6e4fa72ac2c5efd079cd2a4599a1e6b009a8108fba928b.png
# Rise time
tr = 2*atan(sqrt(zeta+1) / sqrt(1-zeta)) / (omegan * sqrt(1-zeta**2))                     

# Peak time
tp = pi / (omegan * sqrt(1 - zeta**2))

# Maximum overshoot
Mp = exp(-pi * zeta / sqrt(1 - zeta**2))   

# 2-percent settling time
ts = (3.912023 - 0.5 * log(1 - zeta**2)) / (omegan * zeta) 

print('rise time =', tr.evalf())
print('peak time =', tp.evalf())
print('maximum overshoot =', Mp.evalf())
print('2-percent-settling time =', ts)
rise time = 0.604599788078073
peak time = 0.906899682117109
maximum overshoot = 0.163033534821580
2-percent-settling time = 2.02793201811295

Comparison to the Python Control Library#

The results are slightly different from the Python Control Library. This is beacase Python Control Library does the calculations numerically.

import control as ct

s = ct.TransferFunction.s
tf = ct.TransferFunction(16 / (s**2+4*s+16))
ct.step_info(tf, RiseTimeLimits=(0, 1))
{'RiseTime': np.float64(0.6279777526347396),
 'SettlingTime': np.float64(2.023483869600828),
 'SettlingMin': np.float64(0.9734200938528016),
 'SettlingMax': np.float64(1.1630334929041963),
 'Overshoot': np.float64(16.303349290419632),
 'Undershoot': 0,
 'Peak': np.float64(1.1630334929041963),
 'PeakTime': np.float64(0.9070789760279573),
 'SteadyStateValue': np.float64(1.0)}