<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Control of a harddisk drive
Step1:  Model
$$G(s) = \frac{k_d}{Js^2} = \frac{b}{s^2} $$ 
2DOF controller with
\begin{align}
F_f &= K \frac{b_1}{a_1}\
F_b &= K \frac{s+b_1}{s+a_1}
\end{align}
Characteristic equation
\begin{align}
A_c(s) = 1 + G(s)F_b(s) &= 0\
1 + K\frac{b(s+b_1)}{s^2(s+a_1)} &= 0\
s^3 + a_1s^2 + Kbs + Kbb_1 &= 0
\end{align}
Desired closed-loop poles
$$ p_1 = -\omega_0, \quad p_2 = \omega_0(-0.5 + i\frac{\sqrt{3}}{2}) \quad p_2 = \omega_0(-0.5 - i\frac{\sqrt{3}}{2}) $$
Step2:  Finding the controller parameters
Setting the coefficients equal gives
\begin{align}
a_1 &= 2\omega_0\
K &= \frac{2J\omega_0^2}{k_d}\
b_1 &= \frac{\omega_0^3}{2\omega_0^2} = \frac{\omega_0}{2}
\end{align}
So, the feedback part of the controller is given by the filter with transfer function
$$ F_b(s) = \frac{2J\omega_0}{k_d} \cdot \frac{s + \frac{\omega_0}{2}}{s + 2\omega_0}$$
and the feedforward part is
$$ F_f(s) = \frac{2J\omega_0}{k_d} \cdot \frac{\frac{\omega_0}{2}}{2\omega_0} = \frac{J\omega_0}{2k_d}.$$
Bode plot of the feedback filter
Step3:  Bodeplot of the loop gain
<ASSISTANT_TASK:>
Python Code:
%%tikz --scale 2 --size 800,300 -f svg
\tikzset{node distance=2cm, 
    block/.style={rectangle, draw, minimum height=15mm, minimum width=20mm},
    sumnode/.style={circle, draw, inner sep=2pt}        
}
  \node[coordinate] (input) {};
  \node[block, right of=input] (TR) {$F_f(s)=K\frac{b_1}{a_1}$};
  \node[sumnode, right of=TR] (sum) {$\sum$};
  \node[block,right of=sum, node distance=30mm] (plant) {$G(s)=\frac{k_d}{Js^2}$};
  \node[sumnode, right of=plant] (sumdist) {$\sum$};
  \node[coordinate, above of=sumdist, node distance=15mm] (dist) {};
  \node[coordinate, right of=sumdist, node distance=15mm] (measure) {};
  \node[coordinate, right of=measure, node distance=10mm] (output) {};
  \node[sumnode,below of=measure, node distance=25mm] (sumnoise) {$\sum$};
  \node[coordinate, right of=sumnoise, node distance=15mm] (noise) {};
  \node[block,left of=sumnoise, node distance=30mm] (SR) {$F_b(s) = K\frac{s+b_1}{s+b_1}$};
  \draw[->] (input) -- node[above, pos=0.2] {$\theta_{ref}(t)$} (TR);
  \draw[->] (TR) -- node[above] {} (sum);
  \draw[->] (sum) -- node[above] {$u(t)$} (plant);
  \draw[->] (plant) -- (sumdist);
  \draw[->] (dist) -- node[at start, right] {$v(t)$} (sumdist);
  \draw[->] (sumdist) -- node[at end, above] {$\theta(t)$} (output);
  \draw[->] (measure) -- (sumnoise);
  \draw[->] (noise) -- node[at start, above] {$n$} (sumnoise);
  \draw[->] (sumnoise) -- (SR);
  \draw[->] (SR) -| (sum) node[left, pos=0.96] {$-$};
Explanation: Control of a harddisk drive
End of explanation
s = sy.symbols('s')
a1,b1,kd,K,J = sy.symbols('a_1,b_1,k_d,K,J')
w0 = sy.symbols('omega0')
p1 = -w0
p2 = w0*(-0.5 + sy.I*sy.sqrt(3)/2)
p3 = w0*(-0.5 - sy.I*sy.sqrt(3)/2)
Ac = sy.collect(sy.expand((s-p1)*(s-p2)*(s-p3)), s)
Ac
A = s**2
B = kd/J
R = s+a1
S = K*(s+b1)
lhs = A*R + B*S
lhs
dioph = sy.collect(sy.expand(lhs-Ac), s)
dioph
Explanation: Model
$$G(s) = \frac{k_d}{Js^2} = \frac{b}{s^2} $$ 
2DOF controller with
\begin{align}
F_f &= K \frac{b_1}{a_1}\
F_b &= K \frac{s+b_1}{s+a_1}
\end{align}
Characteristic equation
\begin{align}
A_c(s) = 1 + G(s)F_b(s) &= 0\
1 + K\frac{b(s+b_1)}{s^2(s+a_1)} &= 0\
s^3 + a_1s^2 + Kbs + Kbb_1 &= 0
\end{align}
Desired closed-loop poles
$$ p_1 = -\omega_0, \quad p_2 = \omega_0(-0.5 + i\frac{\sqrt{3}}{2}) \quad p_2 = \omega_0(-0.5 - i\frac{\sqrt{3}}{2}) $$
End of explanation
w0_n=1.0
J_n = 1.0
kd_n = 1.0
a1_n = 2*w0_n
b1_n = w0_n/2.0
K_n = 2*J_n*w0_n**2/kd_n
Fb = K_n*cm.tf([1, b1_n], [1, a1_n])
mag, phase, omega = cm.bode(Fb)
#plt.figure()
#mag, phase, omega = cm.bode(Fb)
#plt.figure()
#plt.loglog(mag, omega)
Explanation: Finding the controller parameters
Setting the coefficients equal gives
\begin{align}
a_1 &= 2\omega_0\
K &= \frac{2J\omega_0^2}{k_d}\
b_1 &= \frac{\omega_0^3}{2\omega_0^2} = \frac{\omega_0}{2}
\end{align}
So, the feedback part of the controller is given by the filter with transfer function
$$ F_b(s) = \frac{2J\omega_0}{k_d} \cdot \frac{s + \frac{\omega_0}{2}}{s + 2\omega_0}$$
and the feedforward part is
$$ F_f(s) = \frac{2J\omega_0}{k_d} \cdot \frac{\frac{\omega_0}{2}}{2\omega_0} = \frac{J\omega_0}{2k_d}.$$
Bode plot of the feedback filter
End of explanation
K = 2*J*w0**2/kd
a1 = 2*w0
b1 = w0/2
Fb = K*(s + b1)/(s+a1)
G = kd/J / s**2
Go = G*Fb
sy.simplify(sy.expand(Go))
Go_at_w0 = Go.subs(s, sy.I*w0)
sy.simplify(Go_at_w0)
sy.Abs(sy.simplify(Go_at_w0))
sy.arg(sy.simplify(Go_at_w0)).evalf()*180/np.pi
w0_n=1.0
J_n = 1.0
kd_n = 1.0
a1_n = 2*w0_n
b1_n = w0_n/2.0
K_n = 2*J_n*w0_n/kd_n
Fb = K_n*cm.tf([1, b1_n], [1, a1_n])
G = kd_n/J_n * cm.tf([1],[1, 0, 0])
plt.figure()
mag, phase, omega = cm.bode(Fb*G)
yout, tt = cm.step(Fb/K_n)
plt.figure()
plt.plot(tt, yout)
Explanation: Bodeplot of the loop gain
End of explanation
<END_TASK>