FMCW Radar 109- Radar Cube

image0

[1]:
import matplotlib.pyplot as plt
import numpy as np
import matplotlib.colors as mcolors
import matplotlib.pyplot as plt


def explode(data):
    size = np.array(data.shape)*2
    data_e = np.zeros(size - 1, dtype=data.dtype)
    data_e[::2, ::2, ::2] = data
    return data_e

n_adc = 16
n_chirp = 16
n_antenna = 4

sinewave = np.sin(2*np.pi*np.linspace(0,1,n_adc))
cmap = plt.get_cmap('viridis')  # Choose a colormap (e.g., 'viridis')
norm = mcolors.Normalize(vmin=sinewave.min(), vmax=sinewave.max())
sinewave_colored = cmap(norm(sinewave))
print(sinewave_colored.shape)

def rgba_to_hex(rgba_color):
    # Assuming the input is in the range [0, 1]
    r, g, b, a = rgba_color
    # Convert to 0-255 range and cast to integer
    r_int = int(r * 255)
    g_int = int(g * 255)
    b_int = int(b * 255)
    a_int = int(a * 255)
    # Format as a hex string (e.g., #RRGGBBAA)
    hex_string = f"#{r_int:02x}{g_int:02x}{b_int:02x}{a_int:02x}"
    return hex_string



# You can now use sinewave_colored for visualization,
# for example, in a scatter plot:
plt.figure()
plt.scatter(np.arange(len(sinewave)), sinewave, c=sinewave_colored)

sinewave_colored = np.array([rgba_to_hex(color) for color in sinewave_colored])


# build up the numpy logo
n_voxels = np.zeros((16, 4, 16), dtype=bool)
n_voxels[:,:,:] = True
facecolors = np.where(n_voxels, '#FFffff00', '#7A88CCC0')
# facecolors = np.where(n_voxels, '#FF0000FF', '#FFFFFF11')
facecolors[:,0,0] = sinewave_colored

#edgecolors = np.where(n_voxels, '#BFAB6E', '#7D84A6')
edgecolors = np.where(n_voxels, "#ff000000","#ff000000")
filled = np.ones(n_voxels.shape)

# upscale the above voxel image, leaving gaps
filled_2 = explode(filled)
fcolors_2 = explode(facecolors)
ecolors_2 = explode(edgecolors)



# Shrink the gaps
x, y, z = np.indices(np.array(filled_2.shape) + 1).astype(float) // 2
x[0::2, :, :] += 0.05
y[:, 0::2, :] += 0.05
z[:, :, 0::2] += 0.05
x[1::2, :, :] += 0.95
y[:, 1::2, :] += 0.95
z[:, :, 1::2] += 0.95


(16, 4)
_images/FMCW-Radar-109_Radar_Cube_1_1.png
[2]:
ax = plt.figure(figsize=(12, 10)).add_subplot(projection='3d')

ax.voxels(x, y, z, filled_2, facecolors=fcolors_2, edgecolors=ecolors_2)
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.set_aspect('equal')
ax.set_xlabel('ADC Sample')
ax.set_ylabel('Antennas')
ax.set_zlabel('Chirp')
plt.tight_layout()
plt.show()
_images/FMCW-Radar-109_Radar_Cube_2_0.png
[3]:
facecolors[:,1,0] = sinewave_colored
facecolors[:,2,0] = sinewave_colored
facecolors[:,3,0] = sinewave_colored
fcolors_2 = explode(facecolors)

ax = plt.figure(figsize=(12, 10)).add_subplot(projection='3d')

ax.voxels(x, y, z, filled_2, facecolors=fcolors_2, edgecolors=ecolors_2)
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.set_aspect('equal')
ax.set_xlabel('ADC Sample')
ax.set_ylabel('Antennas')
ax.set_zlabel('Chirp')
plt.tight_layout()
plt.show()
_images/FMCW-Radar-109_Radar_Cube_3_0.png
[4]:
for chirp_idx in range(n_chirp):
    for antenna_idx in range(n_antenna):
        facecolors[:,antenna_idx,chirp_idx] = sinewave_colored

fcolors_2 = explode(facecolors)

ax = plt.figure(figsize=(12, 10)).add_subplot(projection='3d')

ax.voxels(x, y, z, filled_2, facecolors=fcolors_2, edgecolors=ecolors_2)
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.set_aspect('equal')
ax.set_xlabel('ADC Sample')
ax.set_ylabel('Antennas')
ax.set_zlabel('Chirp')
plt.tight_layout()
plt.show()
_images/FMCW-Radar-109_Radar_Cube_4_0.png

Range FFT

[5]:
from numpy.fft import fft, fftfreq

range_fft = abs(fft(sinewave))
frequencies = fftfreq(n_adc)

cmap = plt.get_cmap('viridis')  # Choose a colormap (e.g., 'viridis')
norm = mcolors.Normalize(vmin=range_fft.min(), vmax=range_fft.max())
fft_colored = cmap(norm(range_fft))
plt.figure()
plt.scatter(np.arange(len(range_fft)), range_fft, c=fft_colored)
[5]:
<matplotlib.collections.PathCollection at 0x2a4e83d87f0>
_images/FMCW-Radar-109_Radar_Cube_6_1.png
[6]:
range_fft_colored = np.array([rgba_to_hex(color) for color in fft_colored])

for chirp_idx in range(n_chirp):
    for antenna_idx in range(n_antenna):
        facecolors[:,antenna_idx,chirp_idx] = range_fft_colored

fcolors_2 = explode(facecolors)

ax = plt.figure(figsize=(12, 10)).add_subplot(projection='3d')

ax.voxels(x, y, z, filled_2, facecolors=fcolors_2, edgecolors=ecolors_2)
ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.set_aspect('equal')
ax.set_xlabel('Range FFT bins')
ax.set_ylabel('Antennas')
ax.set_zlabel('Chirp')
plt.tight_layout()
plt.show()
_images/FMCW-Radar-109_Radar_Cube_7_0.png

now only keep the first half

[8]:
ax = plt.figure(figsize=(12, 10)).add_subplot(projection='3d')

# Select only the first half of the x indices and the corresponding data
half_x_indices = slice(0, len(x)//2)
half1_x_indices = slice(0, len(x)//2+1)

# we need +1 on voxels (posts and intervals)

x_voxels = x[half1_x_indices, :, :]
y_voxels = y[half1_x_indices, :, :]
z_voxels = z[half1_x_indices, :, :]

filled_sliced = filled_2[half_x_indices, :, :]
fcolors_sliced = fcolors_2[half_x_indices, :, :]
ecolors_sliced = ecolors_2[half_x_indices, :, :]
print(x_voxels.shape)

ax.voxels(x_voxels,y_voxels,z_voxels,
          filled_sliced, facecolors=fcolors_sliced,
          edgecolors=ecolors_sliced)

ax.xaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.yaxis.set_major_locator(plt.MaxNLocator(integer=True))
ax.set_aspect('equal')
ax.set_xlabel('Range FFT bins')
ax.set_ylabel('Antennas')
ax.set_zlabel('Chirp')
plt.tight_layout()
plt.show()

(17, 8, 32)
_images/FMCW-Radar-109_Radar_Cube_9_1.png
[ ]: