3.4.3 LTI CT – Respuesta a estado cero ZSR con Sympy-Python

Se desarrolla el integral de convolución con Sympy con los criterios indicados en el desarrollo analítico. Para determinar los límites del integral se requiere revisar la Causalidad de h(t) descrita con la función es_causal(ft). Los pasos para los resultados se completan con la función desarrollada en la sección anterior para Integral de convolución.
..


Ejemplo 1. Convolución con x(t) causal y h(t) causal

Referencia Lathi ejemplo 2.9 p175, Lathi ejemplo 2.6 p166

En la entrada de sistema se aplica:

x(t) = 10 e^{-3t} \mu (t)

El sistema tiene respuesta a impulso:

h(t) = \big( 2e^{-2t} -e^{-t}\big)\mu (t)

El ejemplo es la continuación de lo realizado en respuesta a entrada cero, que tiene la ecuación:

(D^2 + 3D +2)y(t) = Dx(t)

La respuesta del sistema y(t) para un LTIC se determina como:

y(t) = x(t) \circledast h(t) = \int_{-\infty}^{+\infty} x(\tau)h(t-\tau) \delta \tau

Si la entrada x(t) y el sistema h(t) son causales, la respuesta también será causal. Teniendo como límites del integral τa = 0 y τb = t

y(t)=\begin{cases}\int_{0^{-}}^{t} x(\tau)h(t-\tau) \delta \tau , & t\ge 0\\ 0, & t<0 \end{cases}

El límite inferior del integral se usa como 0, implica aunque se escriba solo 0 se pretende evitar la dificultad cuando x(t) tiene un impulso en el origen.

Para iniciar el algoritmo se definen las variables t y tau, simplificando la expresión del escalón unitario o Heaviside con u.

# INGRESO
t = sym.Symbol('t',real=True)
tau = sym.Symbol('tau',real=True)
u = sym.Heaviside(t)

Se definen las señales de entrada x(t) y respuesta al impulso h(t) usando las expresiones en Sympy. Para seleccionar los límites del integral de convolución se indica si x(t) y h(t) son causales.

# entrada x(t), respuesta impulso h(t)
x = 10*sym.exp(-3*t)*u
h = (2*sym.exp(-2*t)-sym.exp(-t))*u

Se realiza la comprobación de causalidad revisando cada término de la función, que contenga un escalón o un impulso, tomando como referencia la forma en que se construye h(t) con el impulso y los modos caraterísticos.

xcausal = fcnm.es_causal(x)
hcausal = fcnm.es_causal(h)

En el procedimiento se definen los límites del integral de convolución, la expresión dentro del integral xh(t) y con el resultado se aplica la instrucción expand() para obtener términos suma mas sencillos.

En el caso que la respuesta al impulso h(t) no sea causal y la entrada x(t) es causal, se intercambian las funciones para mantener la simplicidad del integral con límite superior t en lugar de infinito. Se aplica la propiedad conmutativa de la convolución.

    # intercambia si h(t) no es_causal
    # con x(t) es_causal por propiedad conmutativa
    intercambia = False
    if hcausal==False and xcausal==True:
        temporal = h
        h = x
        x = temporal
        xcausal = False
        hcausal = True
        intercambia = True

    # limites de integral de convolución
    tau_a = -sym.oo ; tau_b = sym.oo
    if hcausal==True:
        tau_b = t
    if (xcausal and hcausal)==True:
        tau_a = 0

Se añaden las instrucciones al algoritmo del ejercicio para la convolución de la sección anterior y convierte a una función respuesta_ZSR(x,h) .

Con los resultados del algoritmo, queda añadir las instrucciones para mostrar las ecuaciones y las gráficas como los siguientes:

Resultados con Python

xh :
      -t  -2*tau                                     
- 10*e  *e      *Heaviside(tau)*Heaviside(t - tau) + 

    -2*t  -tau                                  
+ 20*e    *e    *Heaviside(tau)*Heaviside(t - tau)
xcausal : True
hcausal : True
[tau_a,tau_b] : [0, t]
intercambia : False
cond_graf : True
ZSR :
/     -t       -2*t       -3*t\             
\- 5*e   + 20*e     - 15*e    /*Heaviside(t)

respuesta Estado Cero 01 Sympy

Grafica animada de la convolución

LTIC ZSR Ej01 animado

Instrucciones en Python

# Respuesta estado cero ZSR con x(t) y h(t)
# Integral de convolucion con Sympy
# https://blog.espol.edu.ec/telg1001/lti-ct-respuesta-a-estado-cero-con-sympy-python/
import numpy as np
import matplotlib.pyplot as plt
import sympy as sym
equivalentes = [{'DiracDelta': lambda x: 1*(x==0)},
                {'Heaviside': lambda x,y: np.heaviside(x, 1)},
                'numpy',]
import telg1001 as fcnm

# INGRESO
t = sym.Symbol('t',real=True)
tau = sym.Symbol('tau',real=True)
u = sym.Heaviside(t)
d = sym.DiracDelta(t)

# entrada x(t), respuesta impulso h(t)
x = 10*sym.exp(-3*t)*u
h = (2*sym.exp(-2*t)-sym.exp(-t))*u

# grafica intervalo [t_a,t_b] plano simétrico
t_b = 5 ; t_a = -t_b
muestras = 101

# PROCEDIMIENTO
def respuesta_ZSR(x,h):
    '''Respuesta a estado cero x(t) y h(t)
    '''
    # revisa causalidad de señales
    xcausal = fcnm.es_causal(x)
    hcausal = fcnm.es_causal(h)

    # intercambia si h(t) no es_causal
    # con x(t) es_causal por propiedad conmutativa
    intercambia = False
    if hcausal==False and xcausal==True:
        temporal = h
        h = x
        x = temporal
        xcausal = False
        hcausal = True
        intercambia = True

    # limites de integral de convolución
    tau_a = -sym.oo ; tau_b = sym.oo
    if hcausal==True:
        tau_b = t
    if (xcausal and hcausal)==True:
        tau_a = 0

    # integral de convolución x(t)*h(t)
    xh = x.subs(t,tau)*h.subs(t,t-tau)
    xh = sym.expand(xh,t)
    ZSR = sym.integrate(xh,(tau,tau_a,tau_b))
    ZSR = sym.expand(ZSR,t)
    if not(ZSR.has(sym.Integral)):
        ZSR = fcnm.simplifica_escalon(ZSR)

    lista_escalon = ZSR.atoms(sym.Heaviside)
    ZSR = sym.expand(ZSR,t) # terminos suma
    ZSR = sym.collect(ZSR,lista_escalon)

    if intercambia == True:
        xcausal = True
        hcausal = False

    # graficar si no tiene Integral o error
    cond_graf = ZSR.has(sym.Integral)
    cond_graf = cond_graf or ZSR.has(sym.oo)
    cond_graf = cond_graf or ZSR.has(sym.nan)
    cond_graf = not(cond_graf)
    
    sol_ZSR = {'xh'      : xh,
               'xcausal' : xcausal,
               'hcausal' : hcausal,
               '[tau_a,tau_b]': [tau_a,tau_b],
               'intercambia'  : intercambia,
               'cond_graf'    : cond_graf,
               'ZSR' : ZSR,}
    return(sol_ZSR)

sol_ZSR = respuesta_ZSR(x,h)
ZSR = sol_ZSR['ZSR']

# SALIDA
fcnm.print_resultado_dict(sol_ZSR)
if sol_ZSR['hcausal']==False:
    print('revisar causalidad de h(t)')
if sol_ZSR['xcausal']==False:
    print('revisar causalidad de x(t)')
if sol_ZSR['intercambia']:
    print('considere intercambiar h(t)con x(t)')
if not(sol_ZSR['cond_graf']):
    print('revisar acortar x(t) o h(t) para BIBO')

# GRAFICA
if sol_ZSR['cond_graf']:
    fig_xh_y = fcnm.graficar_xh_y(x,h,ZSR,t_a,t_b,
                            muestras,y_nombre='ZSR')
#plt.show()

# grafica animada de convolución
n_archivo = '' # sin crear archivo gif animado 
# n_archivo = 'LTIC_ZSR_Ej01' # requiere 'imagemagick'
if sol_ZSR['cond_graf']:
    figura_animada = fcnm.graf_animada_xh_y(x,h,ZSR,t_a,t_b,
                      muestras, reprod_x = 4,y_nombre='ZSR',
                      archivo_nombre = n_archivo)
plt.show()

[ ejemplo 1. x(t) y h(t) causal ]  [ ejemplo 2. h(t) causal ]  [ ejemplo 3. x(t) y h(t) causal]
..


Ejemplo 2. Respuesta entrada cero ZSR entre exponencial y escalón unitario

Referencia: Oppenheim Ej 2.6 p98

Sea la y(t) la respuesta a entrada cero entre las siguientes señales:

x(t) = e^{-2t} \mu (t) h(t) = \mu (t)

Para interpretar el integral de convolución en el ejercicio aa desarrollar se adjunta la animación siguiente:

LTIC ZSR Ej02 animado

Las funciones para el algoritmo se describen como:

# entrada x(t), respuesta impulso h(t)
x = sym.exp(-2*t)*u
h = u

Teniendo como resultado:

xh :
 -2*tau                                  
e      *Heaviside(tau)*Heaviside(t - tau)
xcausal : True
hcausal : True
[tau_a,tau_b] : [0, t]
intercambia : False
cond_graf : True
ZSR :
/     -2*t\             
|1   e    |             
|- - -----|*Heaviside(t)
\2     2  /                

Gráfica de algoritmo

LTIC ZSR Ej02 Sympy

[ ejemplo 1. x(t) y h(t) causal ]  [ ejemplo 2. h(t) causal ]  [ ejemplo 3. x(t) y h(t) causal]
..


Ejemplo 3. Ejercicio con Filtros

Tarea:  Lathi 2.6-4 filtros p207

Para pruebas de algoritmo


[ ejemplo 1. x(t) y h(t) causal ]  [ ejemplo 2. h(t) causal ]  [ ejemplo 3. x(t) y h(t) causal]