FCS Assignment
Name: Adhithya Vishwa A
Reg. No.: 127179004
Date: 04.05.2025
Contents:
First Order Sysytem Step Response ---------------------------------- 2
Second Sysytem Order Step Response ------------------------------ 5
Pole-Zero Map ------------------------------------------------------------ 8
Root Locus Plot ----------------------------------------------------------- 11
Bode Plot ------------------------------------------------------------------- 14
Design of State Feedback ----------------------------------------------- 18
Design of State Observer ------------------------------------------------ 22
| First Order System Step
Ex. 1
Response - Python Script
Code:
import matplotlib.pyplot as plt
from control import tf, step_response
import numpy as np
# Define the transfer functions
sys1 = tf([1], [1, 1])
sys2 = tf([1], [5, 1])
sys3 = tf([1], [0.5, 1])
# Generate a time vector
T = np.linspace(0, 10, 1000)
# Get step responses
T1, y1 = step_response(sys1, T)
T2, y2 = step_response(sys2, T)
T3, y3 = step_response(sys3, T)
# Plot the step responses
plt.figure()
plt.plot(T1, y1, label='sys1: 1/(s+1)')
plt.plot(T2, y2, label='sys2: 1/(5s+1)')
plt.plot(T3, y3, label='sys3: 1/(0.5s+1)')
plt.title('Step Response of sys1, sys2, and sys3')
plt.xlabel('Time (seconds)')
plt.ylabel('Amplitude')
plt.grid(True)
plt.legend()
plt.show()
Output:
Result:
Hence the Output was obtained.
| Second Order System Step
Ex. 2
Response - Python Script
Code:
import numpy as np
import matplotlib.pyplot as plt
from control.matlab import tf, step
# Time vector
t = np.arange(0, 20.0001, 0.01)
# Define transfer functions
systems = [
tf([5], [1, 0, 5]),
tf([5], [1, 2, 5]),
tf([5], [1, 5, 5]),
tf([5], [1, 7, 5])
labels = [
'sys1: [1, 0, 5]',
'sys2: [1, 2, 5]',
'sys3: [1, 5, 5]',
'sys4: [1, 7, 5]'
plt.figure(figsize=(10, 6))
# Compute and plot each step response with axes swapped
for sys, label in zip(systems, labels):
t_out, y_out = step(sys, T=t)
plt.plot(y_out, t_out, label=label) # Swapped x and y
plt.title('Step Response of Systems (Axes Swapped)')
plt.xlabel('Amplitude')
plt.ylabel('Time (seconds)')
plt.legend()
plt.grid(True)
plt.show()
Output:
Result:
Hence the Output was obtained.
Ex. 3 | Pole-Zero Map - Python Script
Code:
import matplotlib.pyplot as plt
from control import tf, pzmap
wn = 1
K=1
T1 = 0
T2 = 0.5
T3 = 1
T4 = 5
# Define transfer functions
sys1 = tf([K], [1, 2*T1*wn, wn**2])
sys2 = tf([K], [1, 2*T2*wn, wn**2])
sys3 = tf([K], [1, 2*T3*wn, wn**2])
sys4 = tf([K], [1, 2*T4*wn, wn**2])
# Plot pole-zero maps in subplots
plt.figure(figsize=(8, 12))
plt.subplot(4, 1, 1)
pzmap(sys1, title='Pole-Zero Map: T1=0')
plt.subplot(4, 1, 2)
pzmap(sys2, title='Pole-Zero Map: T2=0.5')
plt.subplot(4, 1, 3)
pzmap(sys3, title='Pole-Zero Map: T3=1')
plt.subplot(4, 1, 4)
pzmap(sys4, title='Pole-Zero Map: T4=5')
plt.tight_layout()
plt.show()
Output:
Result:
Hence the Output was obtained.
| Root Locus Plot - Python
Ex. 4
Script
Code:
import matplotlib.pyplot as plt
from control import tf, rlocus
# Define the transfer functions
sys1 = tf([1], [1, 4]) # 1/(s + 4)
sys2 = tf([1], [1, 4, 0]) # 1/(s^2 + 4s)
sys3 = tf([1], [1, 4, 0, 0]) # 1/(s^3 + 4s^2)
sys4 = tf([1, 9], [1, 4, 0, 0]) # (s + 9)/(s^3 + 4s^2)
# Create subplots with constrained layout for better spacing
fig, axs = plt.subplots(2, 2, figsize=(12, 8), constrained_layout=True)
# Plot root locus for each transfer function
rlocus(sys1, ax=axs[0, 0])
axs[0, 0].set_title('Root Locus of sys1: 1/(s + 4)')
rlocus(sys2, ax=axs[0, 1])
axs[0, 1].set_title('Root Locus of sys2: 1/(s² + 4s)')
rlocus(sys3, ax=axs[1, 0])
axs[1, 0].set_title('Root Locus of sys3: 1/(s³ + 4s²)')
rlocus(sys4, ax=axs[1, 1])
axs[1, 1].set_title('Root Locus of sys4: (s + 9)/(s³ + 4s²)')
# Show the plots
plt.show()
Output:
Result:
Hence the Output was obtained.
Ex. 5 | Bode Plot - Python Script
Code:
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.gridspec as gridspec
from control import tf, margin, bode_plot
from numpy.polynomial import polynomial as P
# Define transfer functions
sys1 = tf([1], [1, 4])
sys2 = tf([1], P.polyfromroots([0, -4]))
sys3 = tf([1], P.polyfromroots([0, 0, -4]))
sys4 = tf([1, 9], P.polyfromroots([0, 0, -4]))
systems = [sys1, sys2, sys3, sys4]
titles = [
'First Order System',
'Second Order System',
'Third Order System',
'Third Order System with Zero'
]
# Create figure with gridspec for nested subplots
fig = plt.figure(figsize=(14, 10))
gs = gridspec.GridSpec(2, 2, figure=fig, hspace=0.5, wspace=0.3)
for idx, (sys, title) in enumerate(zip(systems, titles)):
# Get row/col position in main grid
row = idx // 2
col = idx % 2
# Create a 2x1 subgrid for magnitude/phase in this cell
subgs = gs[row, col].subgridspec(2, 1)
mag_ax = fig.add_subplot(subgs[0])
phase_ax = fig.add_subplot(subgs[1])
# Calculate margins
gm, pm, _, _ = margin(sys)
# Generate Bode plot on the two axes
bode_plot(
sys,
dB=True,
plot_magnitude=True,
plot_phase=True,
omega_limits=(1e-2, 1e3),
display_margins=True,
margins_method='best',
title=title,
ax=[mag_ax, phas""" """e_ax] # Pass BOTH axes as a list
# Annotate margins
if not np.isinf(gm):
gm_db = 20 * np.log10(gm)
mag_ax.axhline(gm_db, color='r', linestyle='--', alpha=0.7)
mag_ax.text(0.5, gm_db + 2, f'GM: {gm_db:.1f} dB',
color='r', ha='center')
if not np.isnan(pm):
phase_ax.axhline(-180 + pm, color='b', linestyle='--', alpha=0.7)
phase_ax.text(0.5, -180 + pm + 5, f'PM: {pm:.1f}°',
color='b', ha='center')
plt.tight_layout()
plt.show()
Output:
Result:
Hence the Output was obtained.
| Design of State Feedback -
Ex. 6
Python Script
Code:
import numpy as np
import matplotlib.pyplot as plt
from control import ss, place, ctrb, step_response
# System matrices
A = np.array([[0, 1, 0],
[0, 0, 1],
[-1, -5, -6]])
B = np.array([[0], [0], [1]]) # Corrected as column vector
C = np.array([[1, 0, 0]]) # Corrected as row vector
D = np.array([[0]]) # Corrected as 2D array
# Check controllability
U = ctrb(A, B)
if np.linalg.matrix_rank(U) != A.shape[0]:
raise ValueError("System is not controllable")
# Desired closed-loop poles
desired_poles = [-2+4j, -2-4j, -10 ]# Complex conjugate poles
# Compute state feedback gain
K = place(A, B, desired_poles)
# Closed-loop system
A_cl = A - B @ K
sys_cl = ss(A_cl, B, C, D)
# Simulate step response
t = np.linspace(0, 10, 1000)
t_step, y_step = step_response(sys_cl, t, X0=[1, 0, 0])
# Plot results
plt.figure(figsize=(10, 6))
plt.plot(t_step, y_step, label='Output', linewidth=2)
plt.xlabel('Time (s)', fontsize=12)
plt.ylabel('System Response', fontsize=12)
plt.title('Closed-Loop Response with Pole Placement', fontsize=14)
plt.grid(True)
plt.legend()
plt.show()
# Display gain matrix
print("\nState feedback gain matrix K:")
print(K)
Output:
Result:
Hence the Output was obtained.
| Design of State Observer -
Ex. 7
Python Script
Code:
import numpy as np
import control as ctrl
import matplotlib.pyplot as plt
Rs = 0.47
Lq = 1.23e-3
B = 0.0002
Kb = 0.42
Kt = 0.73
J = 6.5e-4
A = np.array([[-B/J, Kt/J],
[-Kb/Lq, -Rs/Lq]])
B = np.array([[0],
[1/Lq]])
C = np.array([[1, 0]])
D = np.array([[0]])
open_sys = ctrl.ss(A, B, C, D)
wr = 3 # reference omega, ω
zr = 0.7 # reference zeta, ζ
nr = wr**2
dr = [1, 2*zr*wr, wr**2] # x" + 2·ζ·ω·x' + ω^2·x
Gr = ctrl.tf([nr], dr)
cp = ctrl.poles(Gr)
K = ctrl.acker(A, B, cp)
sys = ctrl.ss(A - B @ K, B, C, D)
Nbar = 1 / ctrl.dcgain(sys)
cls = ctrl.ss(A - B @ K, B * Nbar, C, D)
or_val = 10 * np.real(cp[0])
op = [or_val + 1, or_val - 1]
L = ctrl.place(A.T, C.T, op).T
Aco = np.block([[A - B @ K, B @ K],
[np.zeros_like(A), A - L @ C]])
Bco = np.vstack([B * Nbar, np.zeros_like(B)])
Cco = np.hstack([C, np.zeros_like(C)])
Dco = 0
clco = ctrl.ss(Aco, Bco, Cco, Dco)
plt.figure()
plt.grid(True)
plt.title('Step Response Comparison')
t = np.linspace(0, 2, 500)
t1, y_clco = ctrl.step_response(clco, t)
t2, y_cls = ctrl.step_response(cls, t)
t3, y_open = ctrl.step_response(open_sys, t)
plt.plot(t1, y_clco.T, '-*b', label='Closed-loop observer-based control')
plt.plot(t2, y_cls.T, '-r', label='Closed-loop state feedback')
plt.plot(t3, y_open.T, '--g', label='Open loop')
plt.xlabel('Time (s)')
plt.ylabel('Output')
plt.legend()
plt.show()
Output:
Result:
Hence the Output is obtained.