FMCW Intro
You can open this workbook in Google Colab to experiment with mmWrt
Below is an intro to mmWrt for simple targets position estimation
For a generic introduction to mmWave sensors: Watch Here
linear chirps and IF frequencies
Signal model According to (Barriok 1973; Stove 1992; Komarov and Smolskiy 2003; Winkler 2007) the transmitted signal of an FMCW radar system can be modeled as where
Given for a linear chirp that
We derive the phase, given
which can be written as:
Where:
\(f_{0min}\) is the start frequency at the begining of the raising frequency of the chirp.
s is the slope at which the frequency is ramped ( \(S = \frac{B}{T}\))
B is the total bandwdith of the chirp
T is the total time of the chirp
Considering a reflected signal with a time delay \(\delta = 2 · \frac{R0+ v\cdot t}{c}\) and Doppler shift \(f_D = −2 · \frac{f_c \cdot v}{c}\)
Where:
c is the speed of light
\(f_D\) is the doppler shift
R0 is the nominal distance to the target
\(\Delta\) is the time of flight (to and from the target)
v is the velocity of the target
The receive signal \(y_R(t)\) can be written as :
\(y_{IF}(t)\) is the IF signal (after mixer) which is obtained by multiplication in the time domain, and passed to a low-pass filter (LPF)
This can be done easily when remembering the trigonometric relation:
Noticing that the element which sums the elements will be higher frequency and will be filtered by the LPF, it remains that:
Where:
\(f_{0min}\) the starting frequency of the chirp
s is the slope of the chirp
\(\Delta\) is the total time of flight between antennas and target
At, Ar: Amplitude of the RX and TX waves
[1]:
# Install a pip package in the current Jupyter kernel
import sys
from os.path import abspath, basename, join, pardir
import datetime
# hack to handle if running from git cloned folder or stand alone (like Google Colab)
cw = basename(abspath(join(".")))
dp = abspath(join(".",pardir))
if cw=="docs" and basename(dp) == "mmWrt":
# running from cloned folder
print("running from git folder, using local path (latest) mmWrt code", dp)
sys.path.insert(0, dp)
else:
print("running standalone, need to ensure mmWrt is installed")
!{sys.executable} -m pip install mmWrt
print(datetime.datetime.now())
running from git folder, using local path (latest) mmWrt code c:\git\mmWrt
2024-05-23 14:22:24.667261
[2]:
from os.path import abspath, join, pardir
import sys
import matplotlib.pyplot as plt
import matplotlib.cm as cm
from matplotlib import colors
from numpy import where, expand_dims
# uncomment below if the notebook is launched from project's root folder
# dp = abspath(join(".",pardir))
# sys.path.insert(0, dp)
from mmWrt.Raytracing import rt_points # noqa: E402
from mmWrt.Scene import Radar, Transmitter, Receiver, Target # noqa: E402
from mmWrt import RadarSignalProcessing as rsp # noqa: E402
[3]:
c = 3e8
debug_ON = False
test = 0
radar = Radar(transmitter=Transmitter(bw=1e9, slope=70e8),
receiver=Receiver(fs=1e3, max_adc_buffer_size=256,
debug=debug_ON), debug=debug_ON)
target1 = Target(2.11)
target2 = Target(4.53, 0, 0, xt=lambda t: 2*t+4.53)
# below is also an equivalent definition of target2
# as at t=0 the position will be x0=2+3=5
# target2 = Target(2, 0, 0, vx=lambda t: 2*t+3)
targets = [target1, target2]
bb = rt_points(radar, targets, debug=debug_ON)
Distances, range_profile = rsp.range_fft(bb)
ca_cfar = rsp.cfar_ca_1d(range_profile)
mag_r = abs(range_profile)
mag_c = abs(ca_cfar)
# little hack to remove small FFT ripples : mag_r> 5
target_filter = ((mag_r > mag_c) & (mag_r > 5))
index_peaks = where(target_filter)[0]
# grouped_peaks = rsp.peak_grouping_1d(index_peaks)
found_targets = [Target(Distances[i]) for i in index_peaks]
error = rsp.error([target1, target2], found_targets)
print("synthetic targets", [t.distance() for t in targets])
print("found targets", [t.distance() for t in found_targets])
print("error is", error)
# 2D representation of the FFT and CFAR
# plot on X,Y axis the FFT and CFAR
plt.plot(Distances, mag_r)
plt.plot(Distances, mag_c)
plt.title("2D plots FFT w/ CFAR")
plt.show()
synthetic targets [2.11, 4.53]
found targets [2.112676056338028, 4.527162977867203]
error is 0.005513078470825494
[4]:
# 1D representation of the FFT
# useful later on to show the link between 1D FFT and 2D FFTs
# Select the color map named CMRmap_r
cmap = cm.get_cmap(name='CMRmap_r')
# convert the 1D array in 2D array to plot using imshow
mag_r = expand_dims(mag_r, axis=0)
# set aspect ratio to auto to have high enough pixels to see them in the y_axis
# change the norm to have a log color scale
# to better see the peaks in correlation with 2D FFT plot
plt.imshow(mag_r, cmap,
aspect='auto',
norm=colors.LogNorm(vmin=min(mag_r[0][:]), vmax=max(mag_r[0][:])))
plt.title("1D FFT")
# plt.savefig(fp_fft_1D)
plt.show()
C:\Users\matth\AppData\Local\Temp\ipykernel_20492\95121931.py:5: MatplotlibDeprecationWarning: The get_cmap function was deprecated in Matplotlib 3.7 and will be removed two minor releases later. Use ``matplotlib.colormaps[name]`` or ``matplotlib.colormaps.get_cmap(obj)`` instead.
cmap = cm.get_cmap(name='CMRmap_r')
NON REGRESSION
[6]:
assert index_peaks[0]==14
[ ]: