Esempio n. 1
0
def test_estimation_with_circuit_simulator():
    eta2 = 1e12

    K1 = 1 << 10
    K2 = 1 << 10
    size = K2 << 2
    window = 1000
    size_2 = size // 2
    window_2 = window // 2
    left_w = size_2 - window_2
    right_w = size_2 + window_2

    analogSystem = AnalogSystem(A, B, CT, Gamma, Gamma_tildeT)
    analogSignals = [Sinusodial(amplitude, frequency, phase)]
    digitalControl1 = DigitalControl(Ts, M)
    digitalControl2 = DigitalControl(Ts, M)
    digitalControl3 = DigitalControl(Ts, M)
    digitalControl4 = DigitalControl(Ts, M)

    tf_abs = np.abs(
        analogSystem.transfer_function_matrix(np.array([2 * np.pi * frequency
                                                        ])))
    print(tf_abs, tf_abs.shape)

    simulator1 = StateSpaceSimulator(analogSystem, digitalControl1,
                                     analogSignals)
    simulator2 = StateSpaceSimulator(analogSystem, digitalControl2,
                                     analogSignals)
    simulator3 = StateSpaceSimulator(analogSystem, digitalControl3,
                                     analogSignals)
    simulator4 = StateSpaceSimulator(analogSystem, digitalControl4,
                                     analogSignals)
    estimator1 = DigitalEstimator(analogSystem, digitalControl1, eta2, K1, K2)
    estimator2 = ParallelEstimator(analogSystem, digitalControl2, eta2, K1, K2)
    estimator3 = FIRFilter(analogSystem, digitalControl3, eta2, K1, K2)
    estimator4 = IIRFilter(analogSystem, digitalControl4, eta2, K2)
    estimator1(simulator1)
    estimator2(simulator2)
    estimator3(simulator3)
    estimator4(simulator4)

    tf_1 = estimator1.signal_transfer_function(
        np.array([2 * np.pi * frequency]))[0]

    e1_array = np.zeros(size)
    e2_array = np.zeros(size)
    e3_array = np.zeros(size)
    e4_array = np.zeros(size)
    e1_error = 0
    e2_error = 0
    e3_error = 0
    e4_error = 0

    for index in range(size):
        e1 = estimator1.__next__()
        e2 = estimator2.__next__()
        e3 = estimator3.__next__()
        e4 = estimator4.__next__()
        e1_array[index] = e1
        e2_array[index] = e2
        e3_array[index] = e3
        e4_array[index] = e4
        t = index * Ts
        u = analogSignals[0].evaluate(t)
        u_lag = analogSignals[0].evaluate(t - estimator4.filter_lag() * Ts)
        if (index > left_w and index < right_w):
            print(
                f"Time: {t: 0.2f}, Input Signal: {u * tf_1}, e1: {e1}, e2: {e2}, e3: {e3}, e4: {e4}"
            )
            e1_error += np.abs(e1 - u * tf_1)**2
            e2_error += np.abs(e2 - u * tf_1)**2
            e3_error += np.abs(e3 - u_lag * tf_1)**2
            e4_error += np.abs(e4 - u_lag * tf_1)**2
    e1_error /= window
    e2_error /= window
    e3_error /= window
    e4_error /= window
    print(f"""Digital estimator error:        {e1_error}, {10 *
        np.log10(e1_error)} dB""")
    print(f"""Parallel estimator error:       {e2_error}, {10 *
        np.log10(e2_error)} dB""")
    print(f"""FIR filter estimator error:     {e3_error}, {10 *
        np.log10(e3_error)} dB""")
    print(f"""IIR filter estimator error:     {e4_error}, {10 *
        np.log10(e4_error)} dB""")

    assert (np.allclose(e1_error, 0, rtol=1e-6, atol=1e-6))
    assert (np.allclose(e2_error, 0, rtol=1e-6, atol=1e-6))
    assert (np.allclose(e3_error, 0, rtol=1e-6, atol=1e-6))
    assert (np.allclose(e4_error, 0, rtol=1e-6, atol=1e-6))
###############################################################################
# Visualize Estimator's Transfer Function (Same for Both)
# -------------------------------------------------------
#

# Logspace frequencies
frequencies = np.logspace(-3, 0, 100)
omega = 4 * np.pi * beta * frequencies

# Compute NTF
ntf = digital_estimator_batch.noise_transfer_function(omega)
ntf_dB = 20 * np.log10(np.abs(ntf))

# Compute STF
stf = digital_estimator_batch.signal_transfer_function(omega)
stf_dB = 20 * np.log10(np.abs(stf.flatten()))

# Signal attenuation at the input signal frequency
stf_at_omega = digital_estimator_batch.signal_transfer_function(
    np.array([2 * np.pi * frequency]))[0]

# Plot
plt.figure()
plt.semilogx(frequencies, stf_dB, label='$STF(\omega)$')
for n in range(N):
    plt.semilogx(frequencies, ntf_dB[0, n, :], label=f"$|NTF_{n+1}(\omega)|$")
plt.semilogx(frequencies, 20 * np.log10(np.linalg.norm(
    ntf[0, :, :], axis=0)), '--', label="$ || NTF(\omega) ||_2 $")

# Add labels and legends to figure
omega_3dB = (4 * np.pi * beta) / 100.
eta2 = np.linalg.norm(
    analog_system.transfer_function_matrix(np.array([omega_3dB])).flatten())**2

# Instantiate estimator.
digital_estimator = DigitalEstimator(analog_system,
                                     digital_control,
                                     eta2,
                                     K1=1)

# Compute NTF
ntf = digital_estimator.noise_transfer_function(omega)
ntf_dB = 20 * np.log10(np.abs(ntf))

# Compute STF
stf = digital_estimator.signal_transfer_function(omega)
stf_dB = 20 * np.log10(np.abs(stf.flatten()))

# Plot
plt.figure()
plt.semilogx(frequencies, stf_dB, label='$STF(\omega)$')
for n in range(N):
    plt.semilogx(frequencies, ntf_dB[0, n, :], label=f"$|NTF_{n+1}(\omega)|$")
plt.semilogx(frequencies,
             20 * np.log10(np.linalg.norm(ntf[0, :, :], axis=0)),
             '--',
             label="$ || NTF(\omega) ||_2 $")

# Add labels and legends to figure
plt.legend()
plt.grid(which='both')