using DSP
using FFTW
using Gadfly
using LinearAlgebra
using Statistics
using ColorSchemes
using Printf
function plot_signals(X::Matrix{ComplexF64}, n::Int64, fs::Float64)
    t = 1/fs:1/fs:n * fs
    n_elements = size(X)[1]
    p_i = plot(Guide.title("In Phase"), Guide.ylabel("Amplitude"), Guide.xlabel("Time [s]"))
    p_q = plot(Guide.title("Quadrature"), Guide.ylabel("Amplitude"), Guide.xlabel("Time [s]"))
    #colors = [colorant"blue", colorant"red", colorant"green", colorant"cyan", colorant"yellow"]
    colors = ColorSchemes.tab10.colors
    for i in 1:n_elements
        push!(p_i, layer(x=t[1:n], y=real(X[i, 1:n]), Geom.line, color=[colors[i]]))
        push!(p_q, layer(x=t[1:n], y=imag(X[i, 1:n]), Geom.line, color=[colors[i]]))
    end
    stack = vstack(p_i, p_q)
end;

Direction Finding with MUSIC

This post simulates direction finding with a 4 element uniform linear array (ULA) using the MUSIC algorithm.

There are three steps:

  1. Generate a signal for each antenna with the appropriate phase delay for its angle of arrivale (AoA)
  2. Apply the MUSIC algorithm
  3. Evaluate the performance of the MUSIC algorithm

Step 1 - Generate Simulated Signals

For this simulation, there are two parts to generating the signals that are needed.

The first is generating four signals that are identical other than their phase. The phase for each signal gets delayed according to the intended angle of arrival (AoA) and the spacing of the array.

The second step is simply adding additive white Gaussian noise (AWGN).

power(X) = 10 .* log10.(mean(abs.(X) .^ 2, dims=2))
function add_noise!(noise_power::Float64, X::Matrix{ComplexF64})
    noise = sqrt((10 .^ (noise_power./10))) * randn(ComplexF64, size(X))
    X + noise
end;

function add_noise(power::Float64, X::Matrix{ComplexF64})
    noise = sqrt((10 .^ (noise_power./10))) * randn(ComplexF64, size(X))
    X + noise
end;
function gen_vectors(ϕ::Float64, fs::Float64, f::Float64, duration::Float64, n_elements::Int64)::Matrix{ComplexF64}
    t = 1/fs:1/fs:duration
    X = zeros(ComplexF64, n_elements, length(t))
    Φ = ϕ .* collect(0:1:n_elements-1)
    for i in 1:n_elements
        temp = im * sin.(2π * f .* t .+ Φ[i]) +  cos.(2π * f .* t .+ Φ[i]);
        X[i, :] = temp
    end
    X;
end;
# Generate the four signals as if they are coming from an emitter that's at 34° 

θ  = 34.0                  # true angle, degrees
ϕ  = π * cos(deg2rad(θ))   # phase difference, radians

fs = 30e3                  # sampling frquency, Hz
f  = 4e3                   # tone frequency, Hz
duration = 1.0             # signal duration, s

c = 299792458.0            # speed of light, m/s
λ = c / f;                 # wavelength, m
n_elements = 4;            # number of elements

X = gen_vectors(ϕ, fs, f, duration, n_elements);

plot_signals(X, 50, fs)

<?xml version=”1.0” encoding=”UTF-8”?>

Time [s] -0.0025 -0.0020 -0.0015 -0.0010 -0.0005 0.0000 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045 -0.0020 -0.0018 -0.0016 -0.0014 -0.0012 -0.0010 -0.0008 -0.0006 -0.0004 -0.0002 0.0000 0.0002 0.0004 0.0006 0.0008 0.0010 0.0012 0.0014 0.0016 0.0018 0.0020 0.0022 0.0024 0.0026 0.0028 0.0030 0.0032 0.0034 0.0036 0.0038 0.0040 -0.002 0.000 0.002 0.004 -0.0020 -0.0019 -0.0018 -0.0017 -0.0016 -0.0015 -0.0014 -0.0013 -0.0012 -0.0011 -0.0010 -0.0009 -0.0008 -0.0007 -0.0006 -0.0005 -0.0004 -0.0003 -0.0002 -0.0001 0.0000 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007 0.0008 0.0009 0.0010 0.0011 0.0012 0.0013 0.0014 0.0015 0.0016 0.0017 0.0018 0.0019 0.0020 0.0021 0.0022 0.0023 0.0024 0.0025 0.0026 0.0027 0.0028 0.0029 0.0030 0.0031 0.0032 0.0033 0.0034 0.0035 0.0036 0.0037 0.0038 0.0039 0.0040 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 -4 -2 0 2 4 -3.0 -2.9 -2.8 -2.7 -2.6 -2.5 -2.4 -2.3 -2.2 -2.1 -2.0 -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 Amplitude Quadrature Time [s] -0.0025 -0.0020 -0.0015 -0.0010 -0.0005 0.0000 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045 -0.0020 -0.0018 -0.0016 -0.0014 -0.0012 -0.0010 -0.0008 -0.0006 -0.0004 -0.0002 0.0000 0.0002 0.0004 0.0006 0.0008 0.0010 0.0012 0.0014 0.0016 0.0018 0.0020 0.0022 0.0024 0.0026 0.0028 0.0030 0.0032 0.0034 0.0036 0.0038 0.0040 -0.002 0.000 0.002 0.004 -0.0020 -0.0019 -0.0018 -0.0017 -0.0016 -0.0015 -0.0014 -0.0013 -0.0012 -0.0011 -0.0010 -0.0009 -0.0008 -0.0007 -0.0006 -0.0005 -0.0004 -0.0003 -0.0002 -0.0001 0.0000 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007 0.0008 0.0009 0.0010 0.0011 0.0012 0.0013 0.0014 0.0015 0.0016 0.0017 0.0018 0.0019 0.0020 0.0021 0.0022 0.0023 0.0024 0.0025 0.0026 0.0027 0.0028 0.0029 0.0030 0.0031 0.0032 0.0033 0.0034 0.0035 0.0036 0.0037 0.0038 0.0039 0.0040 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 -4 -2 0 2 4 -3.0 -2.9 -2.8 -2.7 -2.6 -2.5 -2.4 -2.3 -2.2 -2.1 -2.0 -1.9 -1.8 -1.7 -1.6 -1.5 -1.4 -1.3 -1.2 -1.1 -1.0 -0.9 -0.8 -0.7 -0.6 -0.5 -0.4 -0.3 -0.2 -0.1 0.0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1.0 1.1 1.2 1.3 1.4 1.5 1.6 1.7 1.8 1.9 2.0 2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9 3.0 Amplitude In Phase
noise_power = -3.0                                # dB, W
noise_power_linear = 10 .^ (noise_power ./ 10)    # W
snr = 3                                           # SNR, log-scale, unitless
snr_linear = 10 .^ (snr ./ 10)                    # SNR, linear-scale, unitless
X_pwr = power(X)                                  # Signal power, dB
X_pwr_linear = 10 .^ (X_pwr ./ 10)                # Signal power, linear
noise = sqrt.(X_pwr_linear ./ snr_linear) .* randn(ComplexF64, size(X))
Xn = X + noise
n_pwr = power(noise)

Xn_pwr = power(Xn)
snr = X_pwr .- n_pwr
@printf "Avg power of X = [%2.2f %2.2f %2.2f %2.2f] dB\n" X_pwr[1] X_pwr[2] X_pwr[3] X_pwr[4]
@printf "Avg power of n = [%2.2f %2.2f %2.2f %2.2f] dB\n" n_pwr[1] n_pwr[2] n_pwr[3] n_pwr[4]
@printf "Avg power of Xn = [%2.2f %2.2f %2.2f %2.2f] dB\n" Xn_pwr[1] Xn_pwr[2] Xn_pwr[3] Xn_pwr[4]
@printf "SNR = [%2.2f %2.2f %2.2f %2.2f] dB\n" snr[1] snr[2] snr[3] snr[4]
plot_signals(Xn, 50, fs)
Avg power of X = [0.00 0.00 0.00 0.00] dB
Avg power of n = [-3.00 -3.03 -3.03 -2.99] dB
Avg power of Xn = [1.75 1.77 1.74 1.77] dB
SNR = [3.00 3.03 3.03 2.99] dB

<?xml version=”1.0” encoding=”UTF-8”?>

Time [s] -0.0025 -0.0020 -0.0015 -0.0010 -0.0005 0.0000 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045 -0.0020 -0.0018 -0.0016 -0.0014 -0.0012 -0.0010 -0.0008 -0.0006 -0.0004 -0.0002 0.0000 0.0002 0.0004 0.0006 0.0008 0.0010 0.0012 0.0014 0.0016 0.0018 0.0020 0.0022 0.0024 0.0026 0.0028 0.0030 0.0032 0.0034 0.0036 0.0038 0.0040 -0.002 0.000 0.002 0.004 -0.0020 -0.0019 -0.0018 -0.0017 -0.0016 -0.0015 -0.0014 -0.0013 -0.0012 -0.0011 -0.0010 -0.0009 -0.0008 -0.0007 -0.0006 -0.0005 -0.0004 -0.0003 -0.0002 -0.0001 0.0000 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007 0.0008 0.0009 0.0010 0.0011 0.0012 0.0013 0.0014 0.0015 0.0016 0.0017 0.0018 0.0019 0.0020 0.0021 0.0022 0.0023 0.0024 0.0025 0.0026 0.0027 0.0028 0.0029 0.0030 0.0031 0.0032 0.0033 0.0034 0.0035 0.0036 0.0037 0.0038 0.0039 0.0040 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 -10 -5 0 5 10 -9.0 -8.8 -8.6 -8.4 -8.2 -8.0 -7.8 -7.6 -7.4 -7.2 -7.0 -6.8 -6.6 -6.4 -6.2 -6.0 -5.8 -5.6 -5.4 -5.2 -5.0 -4.8 -4.6 -4.4 -4.2 -4.0 -3.8 -3.6 -3.4 -3.2 -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0 4.2 4.4 4.6 4.8 5.0 5.2 5.4 5.6 5.8 6.0 6.2 6.4 6.6 6.8 7.0 7.2 7.4 7.6 7.8 8.0 8.2 8.4 8.6 8.8 9.0 Amplitude Quadrature Time [s] -0.0025 -0.0020 -0.0015 -0.0010 -0.0005 0.0000 0.0005 0.0010 0.0015 0.0020 0.0025 0.0030 0.0035 0.0040 0.0045 -0.0020 -0.0018 -0.0016 -0.0014 -0.0012 -0.0010 -0.0008 -0.0006 -0.0004 -0.0002 0.0000 0.0002 0.0004 0.0006 0.0008 0.0010 0.0012 0.0014 0.0016 0.0018 0.0020 0.0022 0.0024 0.0026 0.0028 0.0030 0.0032 0.0034 0.0036 0.0038 0.0040 -0.002 0.000 0.002 0.004 -0.0020 -0.0019 -0.0018 -0.0017 -0.0016 -0.0015 -0.0014 -0.0013 -0.0012 -0.0011 -0.0010 -0.0009 -0.0008 -0.0007 -0.0006 -0.0005 -0.0004 -0.0003 -0.0002 -0.0001 0.0000 0.0001 0.0002 0.0003 0.0004 0.0005 0.0006 0.0007 0.0008 0.0009 0.0010 0.0011 0.0012 0.0013 0.0014 0.0015 0.0016 0.0017 0.0018 0.0019 0.0020 0.0021 0.0022 0.0023 0.0024 0.0025 0.0026 0.0027 0.0028 0.0029 0.0030 0.0031 0.0032 0.0033 0.0034 0.0035 0.0036 0.0037 0.0038 0.0039 0.0040 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 0 1 2 3 4 5 6 7 8 9 10 -9.0 -8.5 -8.0 -7.5 -7.0 -6.5 -6.0 -5.5 -5.0 -4.5 -4.0 -3.5 -3.0 -2.5 -2.0 -1.5 -1.0 -0.5 0.0 0.5 1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0 5.5 6.0 6.5 7.0 7.5 8.0 8.5 9.0 -10 -5 0 5 10 -9.0 -8.8 -8.6 -8.4 -8.2 -8.0 -7.8 -7.6 -7.4 -7.2 -7.0 -6.8 -6.6 -6.4 -6.2 -6.0 -5.8 -5.6 -5.4 -5.2 -5.0 -4.8 -4.6 -4.4 -4.2 -4.0 -3.8 -3.6 -3.4 -3.2 -3.0 -2.8 -2.6 -2.4 -2.2 -2.0 -1.8 -1.6 -1.4 -1.2 -1.0 -0.8 -0.6 -0.4 -0.2 0.0 0.2 0.4 0.6 0.8 1.0 1.2 1.4 1.6 1.8 2.0 2.2 2.4 2.6 2.8 3.0 3.2 3.4 3.6 3.8 4.0 4.2 4.4 4.6 4.8 5.0 5.2 5.4 5.6 5.8 6.0 6.2 6.4 6.6 6.8 7.0 7.2 7.4 7.6 7.8 8.0 8.2 8.4 8.6 8.8 9.0 Amplitude In Phase

Step 2 - Apply the MUSIC Algorithm

There are three main components to the MUSIC algorith: Compute the covariance matrix, obtain the eigenvalues and eigenvectors, apply the eigenvector with the largest eigenvalue to the array manifold.

The first component is computing the covariance matrix. In this example there are four signals of some length, N. When the covariance matrix is computed we are left with a 4x4 symmetric matrix that shows the covariance between each the signal that each antenna receives.

Next, obtain the eigenvalues and eigenvector pairs. The key to MUSIC is separating the signal subspace and the noise subspace by discarding the eigenvector with the smallest eigenvalue (as this eigenvector corresponds to the noise subspace).

Finally, take the remaining eigenvectors and create the MUSIC pseudospectrum by applying the array manifold to the eigenvectors. The array manifold is what the array expects to receive for a given angle of arrival under ideal circumstances.

function array_manifold_vector(array::Vector{Float64}, θ::Float64)::Vector{ComplexF64}
    exp.(-2π * im * cos(θ) .* array)
end;
function MUSIC(X::Matrix{ComplexF64}, n_targets::Int64, normalized_spacing::Float64)::Vector{Float64}
    n_elements = size(X)[1]
    element_locations = normalized_spacing .* 0.5 .* (n_elements .- 1 .- 2 .* collect(0:(n_elements-1)))
    pseudo_spectrum_length = 1024;
    vii = zeros(ComplexF64, n_elements, pseudo_spectrum_length);

    thetas = range(0, stop=π, length=pseudo_spectrum_length)
    for i in 1:pseudo_spectrum_length
        vii[:, i] = array_manifold_vector(element_locations, thetas[i])
    end
    
    # Get the covariance matrix, R
    R = Statistics.cor(X, X, dims=2);

    # Get the eigenvalues and vectors of R
    eigen_values = eigvals(R);
    eigen_vectors = eigvecs(R);
    
    # Sort the eigenvalues
    i = sortperm(abs.(eigen_values));
    eigen_vectors = eigen_vectors[:, i]

    # Use the largest n_elements - 1 eigenvectors to make U_n
    U_N = eigen_vectors[:, 1:n_elements-1];
    U_N_sq = U_N * U_N';

    # Generate the pseudospectrum
    pseudo_spectrum = zeros(Float64, 1, pseudo_spectrum_length)
    q = 0.0
    for i in 1:pseudo_spectrum_length
        q = vii'[[i], :] * U_N_sq * vii[:, [i]]
        pseudo_spectrum[i] = abs(1.0/real(q[1]))
    end

    # Normalize the pseudospectrum to 0dB
    pseudo_spectrum = 10 .* log10.(pseudo_spectrum/maximum(pseudo_spectrum));
    
    # Return the pseudospectrum
    vec(pseudo_spectrum)
end;
pseudo_spectrum = MUSIC(X, 1, 0.5)
(m, i) = findmax(pseudo_spectrum);
θ̂ = rad2deg(i/1024.0 * π);
error = abs(θ-θ̂)
@printf "θ = %2.2f°, θ̂ = %2.2f°, error = %2.4f°\n" θ θ̂ error
θ = 34.00°, θ̂ = 34.10°, error = 0.1016°
plot(x=range(0, stop=180, length=length(pseudo_spectrum)), 
     y=pseudo_spectrum, 
     Geom.line, 
     Coord.cartesian(xmin=0, xmax=180),
     Guide.title("MUSIC Pseudospectrum"),
     Guide.xlabel("Angle of Arrival (°)"),
     Guide.ylabel("MUSIC Response (dB)"))
Angle of Arrival (°) -210 -180 -150 -120 -90 -60 -30 0 30 60 90 120 150 180 210 240 270 300 330 360 390 -180 -160 -140 -120 -100 -80 -60 -40 -20 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 320 340 360 -200 0 200 400 -180 -170 -160 -150 -140 -130 -120 -110 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -130 -120 -110 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 -120 -115 -110 -105 -100 -95 -90 -85 -80 -75 -70 -65 -60 -55 -50 -45 -40 -35 -30 -25 -20 -15 -10 -5 0 5 10 15 20 25 30 35 40 45 50 55 60 -200 -100 0 100 -120 -118 -116 -114 -112 -110 -108 -106 -104 -102 -100 -98 -96 -94 -92 -90 -88 -86 -84 -82 -80 -78 -76 -74 -72 -70 -68 -66 -64 -62 -60 -58 -56 -54 -52 -50 -48 -46 -44 -42 -40 -38 -36 -34 -32 -30 -28 -26 -24 -22 -20 -18 -16 -14 -12 -10 -8 -6 -4 -2 0 2 4 6 8 10 12 14 16 18 20 22 24 26 28 30 32 34 36 38 40 42 44 46 48 50 52 54 56 58 60 MUSIC Response (dB) MUSIC Pseudospectrum

Step 3 - MUSIC Evaluation

The cell below sweeps through every angle in 1 degree increments and records the AoA where the array and MUSIC perform the worst (\Delta max). This will likely be around 1 degree or 179 degrees due to the grating lobes from the ULA.

emitter_angles = 1.0:1.0:179.0
Δ = zeros(size(emitter_angles))
n_elements = 4
for (index, θ) in enumerate(emitter_angles)
    
    ϕ  = π * cos(deg2rad(θ))
    
    X = gen_vectors(ϕ, fs, f, duration, n_elements)
    noise = noise = sqrt((10 .^ (noise_power./10))) * randn(ComplexF64, size(X))

    pseudo_spectrum = MUSIC(X, 1, 0.5)

    (m, i) = findmax(pseudo_spectrum);
    θ̂ = rad2deg(i/1024.0 * π);

    Δ[index] = abs(θ - θ̂)
end

(Δmax, Δmax_ind) = findmax(Δ)
Δmax_angle = emitter_angles[Δmax_ind]

println("Δmax = $Δmax at θ = $Δmax_angle")
Δmax = 0.25 at θ = 11.0
plot(x=emitter_angles, y=Δ,  
     Coord.cartesian(xmin=0, xmax=180),
     Geom.line, 
     Guide.title("MUSIC Error as a function of AoA"),
     Guide.xlabel("Angle of Arrival (°)"),
     Guide.ylabel("Error (°)"))
Angle of Arrival (°) -210 -180 -150 -120 -90 -60 -30 0 30 60 90 120 150 180 210 240 270 300 330 360 390 -180 -160 -140 -120 -100 -80 -60 -40 -20 0 20 40 60 80 100 120 140 160 180 200 220 240 260 280 300 320 340 360 -200 0 200 400 -180 -170 -160 -150 -140 -130 -120 -110 -100 -90 -80 -70 -60 -50 -40 -30 -20 -10 0 10 20 30 40 50 60 70 80 90 100 110 120 130 140 150 160 170 180 190 200 210 220 230 240 250 260 270 280 290 300 310 320 330 340 350 360 h,j,k,l,arrows,drag to pan i,o,+,-,scroll,shift-drag to zoom r,dbl-click to reset c for coordinates ? for help ? -0.30 -0.25 -0.20 -0.15 -0.10 -0.05 0.00 0.05 0.10 0.15 0.20 0.25 0.30 0.35 0.40 0.45 0.50 0.55 -0.26 -0.24 -0.22 -0.20 -0.18 -0.16 -0.14 -0.12 -0.10 -0.08 -0.06 -0.04 -0.02 0.00 0.02 0.04 0.06 0.08 0.10 0.12 0.14 0.16 0.18 0.20 0.22 0.24 0.26 0.28 0.30 0.32 0.34 0.36 0.38 0.40 0.42 0.44 0.46 0.48 0.50 -0.25 0.00 0.25 0.50 -0.25 -0.24 -0.23 -0.22 -0.21 -0.20 -0.19 -0.18 -0.17 -0.16 -0.15 -0.14 -0.13 -0.12 -0.11 -0.10 -0.09 -0.08 -0.07 -0.06 -0.05 -0.04 -0.03 -0.02 -0.01 0.00 0.01 0.02 0.03 0.04 0.05 0.06 0.07 0.08 0.09 0.10 0.11 0.12 0.13 0.14 0.15 0.16 0.17 0.18 0.19 0.20 0.21 0.22 0.23 0.24 0.25 0.26 0.27 0.28 0.29 0.30 0.31 0.32 0.33 0.34 0.35 0.36 0.37 0.38 0.39 0.40 0.41 0.42 0.43 0.44 0.45 0.46 0.47 0.48 0.49 0.50 Error (°) MUSIC Error as a function of AoA