# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.14.4
#   kernelspec:
#     display_name: Python 3
#     language: python
#     name: python3
# ---

# +
import numpy as np
import matplotlib.pyplot as plt
# %matplotlib inline
import control
from ipywidgets import interact


# -

# # Error de Estado Estacionario
#
# En el bucle de control, el error se calcula como la diferencia entre la referencia y la variable controlada.
#
# ![bucle](figuras/bucle.PNG)
#
# Los cambios en la señal de referencia provocan errores durante los transitorios y pueden generar un error estacionario.
#
# Considerando un sistema de control con realimentación unitaria y función de transferencia de lazo abierto $G(s) = G_c(s)G_a(s)G_p(s)$:
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^N(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)}$$
#
# Este sistema tiene:
# - $c$ ceros definidos por $T_{c1}$, $T_{c2}$, $T_{c3}$, ..., $T_{cc}$
# - $N$ polos en $0$
# - $p$ polos definidos por $T_{p1}$, $T_{p2}$, $T_{p3}$, ..., $T_{pp}$
#
#

# La función de transferencia de lazo cerrado desde la referencia hacia la variable controlada es:
#
# $$\frac{C(s)}{R(s)} = \frac{G(s)}{1 + G_(s)}$$

# La función de transferencia de lazo cerrado desde la referencia hacia el error es:
#
# $$\frac{E(s)}{R(s)} = \frac{R(s)-C(s)}{R(s)} = 1- \frac{C(s)}{R(s)} = 1 - \frac{G(s)}{1 + G(s)} = \frac{1}{1+G(s)}$$

# El **error de estado estacionario** puede calcularse como:
# $$E(s) = \int_0^\infty e(t)e^{-st}dt$$
#
# $$E_{ee} = \lim_{t \rightarrow \infty} e(t) = \lim_{s \rightarrow 0} sE(s) = \lim_{s \rightarrow 0}\frac{sR(s)}{1+G(s)}$$

# ## Error de estado estacionario ante una entrada escalón (posición)
#
# Dada esta señal como referencia:
#
# $$R(s) = \frac{1}{s}$$
#
# y
#
# $$E_{ee} = \lim_{s \rightarrow 0}\frac{s \frac{1}{s} }{1+G(s)} = \frac{1}{1+ \lim_{s \rightarrow 0} G(s) }$$

# **Ejemplo**
#
# Suponga:
#
# $$G(s) = \frac{1}{5s + 1}$$
#
# Entonces:
#
# $$E_{ee} =\frac{1}{1+ \underbrace{\lim_{s \rightarrow 0} \frac{1}{5s + 1}}_{1} }$$
#
# Si se introduce una ganancia $K_p$ (controlador proporcional):
#
# $$E_{ee} =\frac{1}{1+ \underbrace{\lim_{s \rightarrow 0} \frac{K_p}{5s + 1}}_{K_p} }$$
#

# Se define la función de transferencia
G = control.tf(1, [5,1])
G

# Análisis $E_{ee}$
#
#
# $$E_{ee} =\frac{1}{1+ \underbrace{\lim_{s \rightarrow 0} \frac{K_p}{5s + 1}}_{K_p} } = \frac{1}{1+K_p}$$
#

# +
ts = np.linspace(0, 10, 2000)

Kp = [0.5,0.75,1,2,3,5,10,100]
etiq = []#lista para etiquetas
e = []#lista para errores
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(GLC, ts)
    e.append(1/(1+k))
    plt.plot(ts, yLC)
    etiq.append('k = '+str(k))
etiq.append('referencia')
plt.plot([ts[0],ts[-1]], [1,1])
plt.legend(etiq)
plt.grid(True)
print(e)
# -

# ¿Qué pasa si el sistema tiene una dinámica integradora?
#
# $$G(s) = \frac{1}{s(5s + 1)}$$
#

# Se define la función de transferencia
G = control.tf(1, [5,1,0])
G

# Análisis $E_{ee}$
#
#
# $$E_{ee} =\frac{1}{1+ \underbrace{\lim_{s \rightarrow 0} \frac{1}{s(5s + 1)}}_{\infty} } = 0$$

# +
ts = np.linspace(0, 50, 2000)

Kp = [0.5,1,1.5,2.0,3,3.1]
etiq = []
e = []
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(GLC, ts)
    e.append(0)
    plt.plot(ts, yLC)
    etiq.append('k = '+str(k))
etiq.append('referencia')
plt.plot([ts[0],ts[-1]], [1,1])
plt.legend(etiq)
plt.grid(True)
print(e)
# -

# Observe que la presencia de una dinámica integradora hace que el sistema en lazo cerrado tenga error de estado estable nulo. La cantidad de polos integradores determina el **tipo** del sistema:

# ### Sistemas tipo cero
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{c3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \frac{1}{1+ \lim_{s \rightarrow 0} G(s) } \\ 
# & = \frac{1}{1+ \lim_{s \rightarrow 0} K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} } \\
# & = \frac{1}{1+ K }
# \end{align}
#
#
#

# ### Sistemas tipo uno
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \frac{1}{1+ \lim_{s \rightarrow 0} G(s) } \\ 
# & = \frac{1}{1+ \lim_{s \rightarrow 0} K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} } \\
# & = 0
# \end{align}
#
#

# ### Sistemas tipo dos
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \frac{1}{1+ \lim_{s \rightarrow 0} G(s) } \\ 
# & = \frac{1}{1+ \lim_{s \rightarrow 0} K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} } \\
# & = 0
# \end{align}

# ## Error de estado estacionario ante una entrada rampa (velocidad)
# $$R(s) = \frac{1}{s^2} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0}\frac{sR(s)}{1+G(s)} \\ 
# &=  \lim_{s \rightarrow 0}\frac{s\frac{1}{s^2}}{1+G(s)} \\
# &=  \lim_{s \rightarrow 0}\frac{1}{s+sG(s)} \\
# &= \lim_{s \rightarrow 0} \frac{1}{sG(s)}
# \end{align}
#

# ### Sistemas tipo cero
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{sG(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{sK\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & = \infty
# \end{align}
#
#

# **Ejemplo**
#
# Suponga:
#
# $$G(s) = \frac{1}{5s + 1}$$
#
#
#

# Se define la función de transferencia
G = control.tf(1, [5,1])
G

# +
ts = np.linspace(0, 100, 2000)

Kp = [0.5,5,10]
etiq = []
e = []
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(control.tf(1,[1,0])*GLC, ts)
    plt.plot(ts, yLC)
    etiq.append('k = '+str(k))
etiq.append('referencia')
plt.plot([ts[0],ts[-1]], [0,ts[-1]])
plt.legend(etiq)
plt.grid(True)
print(e)
# -

#
# ### Sistemas tipo uno
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{p3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{c3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{sG(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{sK\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & = \frac{1}{K}
# \end{align}
#
#

# Se define la función de transferencia
G = control.tf(1, [5,1,0])
G

# +
ts = np.linspace(0, 50, 2000)

Kp = [0.1,1,10]
etiq = []
e = []
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(control.tf(1,[1,0])*GLC, ts)
    e.append(1/(k))
    plt.plot(ts, ts-yLC)
    etiq.append('k = '+str(k))
# etiq.append('referencia')
# plt.plot([ts[0],ts[-1]], [0,ts[-1]])
plt.legend(etiq)
plt.grid(True)
print(e)
# -

# ### Sistemas tipo dos
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{c3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{sG(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{sK\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & = \frac{s}{K} = 0
# \end{align}

## Desarrolle su propio ejemplo
G = control.tf([10,1], [5,1,0,0])
G


rlist,klist = control.root_locus(G,plot = True)

# +
ts = np.linspace(0, 50, 2000)

Kp = [0.1,1,10]
etiq = []
e = []
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(control.tf(1,[1,0])*GLC, ts)
    plt.plot(ts,yLC)
    etiq.append('k = '+str(k))
# etiq.append('referencia')
# plt.plot([ts[0],ts[-1]], [0,ts[-1]])
plt.legend(etiq)
plt.grid(True)
print(e)
# -

# ## Error de estado estacionario ante una entrada parábola (aceleración)
#
# $$R(s) = \frac{1}{s^3} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0}\frac{sR(s)}{1+G(s)} \\ 
# &=  \lim_{s \rightarrow 0}\frac{s\frac{1}{s^3}}{1+G(s)} \\
# &=  \lim_{s \rightarrow 0}\frac{1}{s^2+s^2G(s)} \\
# &= \lim_{s \rightarrow 0} \frac{1}{s^2G(s)}
# \end{align}
#

# ### Sistemas tipo cero
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{s^2G(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{s^2K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & = \infty
# \end{align}

## Desarrolle su propio ejemplo
# Se define la función de transferencia
G = control.tf(1, [5,1])
G

# +
ts = np.linspace(0, 100, 2000)

Kp = [0.1,1,5,10]
etiq = []
e = []
for k in Kp:
    
    GLC = control.feedback(k*G,1)
    _, yLC = control.step_response(control.tf(1,[1,0,0])*GLC, ts)
    plt.plot(ts, yLC)
    etiq.append('k = '+str(k))
etiq.append('referencia')
plt.plot(ts, ts*ts/2,'k')
plt.legend(etiq)
plt.grid(True)
print(e)
# -

#
#
#
# ### Sistemas tipo uno
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{p3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{c3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{s^2G(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{s^2K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & =  \infty
# \end{align}
#
#

## Desarrolle su propio ejemplo


# ### Sistemas tipo dos
#
# $$G(s) = K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{c3}s+1)...(T_{pp}s+1)} $$
#
# \begin{align}
# E_{ee} &= \lim_{s \rightarrow 0} \frac{1}{sG(s)} \\ 
# & = \lim_{s \rightarrow 0} \frac{1}{s^2K\frac{(T_{c1}s+1)(T_{c2}s+1)(T_{c3}s+1)...(T_{cc}s+1)}{s^2(T_{p1}s+1)(T_{p2}s+1)(T_{p3}s+1)...(T_{pp}s+1)} }\\
# & = \frac{1}{K}
# \end{align}

## Desarrolle su propio ejemplo


# ## Tabla
#
# |error   | $$\frac{1}{s}$$|$$\frac{1}{s^2}$$|$$\frac{1}{s^3}$$|
# |--------|----------------|-----------------|-----------------|
# | tipo 0 |$$\frac{1}{1+K}$$ |$$\infty$$     | $$\infty$$      | 
# | tipo 1 |$$0$$           |$$ \frac{1}{K}$$ | $$\infty$$      |
# | tipo 2 |$$0$$           |$$ 0 $$          | $$ \frac{1}{K}$$|
#

# ## Ejemplo
#
# Suponga un proceso con el siguiente modelo:
#
# $$G_p(s) = \frac{2.5}{s^2+6s+5}$$
#
# Analice el comportamiento del sistema

Gp = control.tf(2.5,[1,6,5])
Gp

Gp.pole()

Gp.zero()

rlist,klist = control.root_locus(Gp,plot = True)

np.exp(-5)

# +
ts = np.linspace(0, 10, 2000)
e = 0.05

_, y = control.step_response(Gp, ts)
plt.plot(ts, y)
plt.plot([ts[0],ts[-1]], [y[-1],y[-1]],':k',
         [ts[0],ts[-1]], [y[-1]*(1-e),y[-1]*(1-e)],':k',
         [ts[0],ts[-1]], [y[-1]*(1+e),y[-1]*(1+e)],':k')
# etiq.append('referencia')
# plt.plot([ts[0],ts[-1]], [0,ts[-1]])
plt.grid(True)

# -

# Observaciones:
# - Sistema estable (polos con parte real negativa).
# - El polo más lento está en $s=-1$, su constante de tiempo asociada es $\tau = -1/\sigma = 1s$, por lo que el tiempo de estabilización es aproximadamente $3\tau=3s$.
# - El error de estado estable ante una entrada escalón es $0.5$.
#

# A partir de las observaciones en lazo abierto, se plantean los requerimientos para el sistema controlado:
#
# - Que el sistema en lazo cerrado reduzca el error de estado estable a $0.1$
# - Que el sistema en lazo cerrado reduzca el tiempo de estabilización.

# Se plantea una forma para el controlador $G_c(s)$ de manera que sea capaz de eliminar a la dinámica más lenta del proceso.
# $$G_c(s) = k_c\frac{s+a}{s+b}$$
#
# El diseño de este controlador consiste en encontrar los valores apropiados para $k_c,a$ y $b$.

# Teniendo en cuenta el bucle de control
#
# ![Simple feedback loop](figuras/feedback.png)
#
# se obtiene la función de transferencia de lazo directo:
#
# \begin{align}
# G(s) &= G_c(s)G_p(s)\\
# G(s) &= k_c\frac{s+a}{s+b} \frac{2.5}{s^2+6s+5}\\
# G(s) &= k_c\frac{s+a}{s+b} \frac{2.5}{(s+1)(s+5)}
# \end{align}
#
#

#
# Como la dinámica más lenta del proceso es el polo en $s=-1$, puede definirse que $a=1$.
#
# \begin{align}
# G(s) &= k_c\frac{s+1}{s+b} \frac{2.5}{(s+1)(s+5)}\\
# G(s) &= k_c\frac{1}{s+b} \frac{2.5}{s+5}\\
# G(s) &= k_c\frac{2.5}{(s+b)(s+5)}
# \end{align}

# Suponga que $b=8$ para introducir una dinámica más rápida en el comportamiento.
#
# $$G_p(s) = \frac{2.5}{(s+1)(s+5)}$$
# $$G_c(s) = k_c\frac{s+1}{s+8}$$
# $$G(s) = \frac{2.5k_c}{(s+8)(s+5)}$$

Gc = control.tf([1,1],[1,8])
Gc

_,_ = control.root_locus(Gp,plot = True)

_,_ = control.root_locus(Gc*Gp,plot = True)

# El sistema es tipo 0 por no tener polos integradores, el error de estado estacionario ante una señal escalón es:
#
# \begin{align}
# E_{ee} &= \frac{1}{1+\lim_{s \rightarrow 0}G(s)}\\
# E_{ee} &= \frac{1}{1+\lim_{s \rightarrow 0}k_c\frac{5}{2(s+8)(s+5)}}\\
# E_{ee} &= \frac{1}{1+k_c\frac{5}{80}}\\
# E_{ee} &= \frac{80}{80+5k_c}\\
# \end{align}
#
# Se desea $E_{ee} = 0.1$
#
#
# $$E_{ee} =0.1= \frac{80}{80+5k_c}$$
# $$k_c= \frac{720}{5}=144$$
#
# El controlador es:
#
# $$G_c(s) = 144 \frac{s+1}{s+8}$$

Gc = 144*control.tf([1,1],[1,8])
Gc

G = Gc*Gp
G

GLC = control.feedback(G,1)
GLC

# +
ts = np.linspace(0, 4, 2000)
e = 0.05

_, y = control.step_response(Gp, ts)
_, yLC = control.step_response(GLC, ts)

plt.plot(ts, y,ts,yLC)
plt.plot([ts[0],ts[-1]], [y[-1],y[-1]],':k',
         [ts[0],ts[-1]], [y[-1]*(1-e),y[-1]*(1-e)],':k',
         [ts[0],ts[-1]], [y[-1]*(1+e),y[-1]*(1+e)],':k')
plt.plot([ts[0],ts[-1]], [yLC[-1],yLC[-1]],':k',
         [ts[0],ts[-1]], [yLC[-1]*(1-e),yLC[-1]*(1-e)],':k',
         [ts[0],ts[-1]], [yLC[-1]*(1+e),yLC[-1]*(1+e)],':k')
plt.grid(True)
# -

# - ¿Es satisfactorio el comportamiento obtenido para el sistema en lazo cerrado?
# - ¿Qué propone hacer para mejorar el comportamiento?
# - ¿Qué propone hacer para eliminar el error de estado estable?
#



StarcoderdataJupyterScriptsDedupFiltered