Finding impulse response of the block diagram

Viewed 116

I have the following block diagram and each subsystem, I need to find the overall impulse response for 0<=n<=99.

The individual impulse response for each subsystem was found as shown.

import numpy as np
import matplotlib.pyplot as plt

n1 = np.arange(0, 6, 1) # set upper limit = 5 and lower limit = 0 in steps of 1.
h1 = [1, 1/2, 1/4, 1/8, 1/16, 1/32] #impulse response h1
plt.stem(n1, h1)
n2 = np.arange(0, 6, 1) # set upper limit = 5 and lower limit = 0 in steps of 1.
h2 = [1, 1, 1, 1, 1, 0] #impulse response h2
plt.stem(n2, h2)
n3 = np.arange(0, 6, 1) # set upper limit = 5 and lower limit = 0 in steps of 1.
h3 = [1/4, 1/2, 1/3, 0, 0, 0] #impulse response h3
plt.stem(n3, h3)

Then I performed the following convolution and addition to find overall impulse response:

h_t = np.convolve(h1,h2, 'full') + h3

but I got the following error.

ValueError: operands could not be broadcast together with shapes (11,) (6,) 

Not certain how I should incorporate the range of n values considered.

1 Answers

You need to pad the various impulse responses so that they match in shape. In effect, the impulse responses you show are just the non-zero values. After that, you can pad to infinity time with zero.

def pad(y, t):
    return np.pad(y, (0, len(t) - len(y)), constant_values=0)

t = np.arange(20)  # or change to 100 for 0<=n<=99, but that's lots of zeros...
h1 = [1, 1/2, 1/4, 1/8, 1/16, 1/32]  # impulse response h1
h2 = [1, 1, 1, 1, 1]  # impulse response h2
h3 = [1/4, 1/2, 1/3]  # impulse response h3
h_t = pad(np.convolve(h1, h2, 'full'), t) + pad(h3, t)


# or, equivalently:

t = np.arange(20)
h1 = pad([1, 1/2, 1/4, 1/8, 1/16, 1/32], t)  # impulse response h1
h2 = pad([1, 1, 1, 1, 1], t)  # impulse response h2
h3 = pad([1/4, 1/2, 1/3], t)  # impulse response h3
h_t = np.convolve(h1, h2, 'full')[:len(t)] + h3


plt.stem(t, pad(h1, t), markerfmt='C0o')
plt.stem(t, pad(h2, t), markerfmt='C1o')
plt.stem(t, pad(h3, t), markerfmt='C2o')
plt.stem(t, h_t, markerfmt='C3-')

Addendum

To address the case where y is longer than what we need, a modified function can clip or pad depending on the need:

def take(y, n):
    y = y[:n]
    return np.pad(y, (0, n - len(y)), constant_values=0)

Examples:

n = 20
t = np.arange(n)
h1 = take([1, 1/2, 1/4, 1/8, 1/16, 1/32], n)  # impulse response h1
h2 = take([1, 1, 1, 1, 1], n)  # impulse response h2
h3 = take([1/4, 1/2, 1/3], n)  # impulse response h3
h_t = take(np.convolve(h1, h2, 'full'), n) + h3

And also:

X = take(np.exp(-t/10), n)
h_t = take(np.convolve(h1, X, 'full'), n) + h3
Related