In [1]:
import radarsimpy
radarsimpy.__version__
Out[1]:
'10.0.1'

FMCW Radar with a Corner Reflector¶



This is an example of using RadarSimPy to simulate an FMCW radar with a corner reflector model (not an ideal point target).


Setup FMCW radar¶

Transmitter¶

Setup the basic transmitter parameters through Transmitter module.

The following table lists the parameters in this example.

Parameter Variable in Transmitter Value
Frequency ($f$) f [77e9-50e6, 77e9+50e6] GHz
Time ($T$) t 80e-6 s
Transmitted power ($P_t$) tx_power 15 dBm
Pulse repetition period ($PRP$) prp 100 us
Number of pulses pulses 256

Receiver¶

Setup the receiver parameters through Receiver module.

The parameters of the receiver are listed in the table below.

Parameter Variable in Receiver Value
Sampling rate ($f_s$) fs 2 Msps
Noise figure ($NF$) noise_figure 8 dB
RF gain/loss ($G_{rf}$) rf_gain 20 dB
Load resistor ($R_L$) load_resistor 500 $\Omega$
Baseband voltage gain ($G_{BB}$) baseband_gain 30 dB
In [2]:
import numpy as np
from radarsimpy import Radar, Transmitter, Receiver

tx_channel = dict(
    location=(0, 0, 0),
)

tx = Transmitter(f=[77e9-50e6, 77e9+50e6],
                 t=[0, 80e-6],
                 tx_power=25,
                 prp=100e-6,
                 pulses=256,
                 channels=[tx_channel])

rx_channel = dict(
    location=(0, 0, 0),
)

rx = Receiver(fs=2e6,
              noise_figure=8,
              rf_gain=20,
              load_resistor=500,
              baseband_gain=30,
              channels=[rx_channel])

radar = Radar(transmitter=tx, receiver=rx)

Corner reflector model¶

The corner reflector model is with .stl. It can be imported by using meshio module.

In [3]:
target_1 = {
    'model': '../models/cr.stl',
    'location': (50, 0, 0),
    'speed': (-5, 0, 0)
}

targets = [target_1]

Plot the 3D mesh of the corner reflector

In [4]:
import meshio

import plotly.graph_objs as go
from IPython.display import Image

mesh_data = meshio.read('../models/cr.stl')

fig = go.Figure()

fig.add_trace(go.Mesh3d(x=mesh_data.points[:, 0],
                        y=mesh_data.points[:, 1],
                        z=mesh_data.points[:, 2],
                        i=mesh_data.cells[0].data[:, 0],
                        j=mesh_data.cells[0].data[:, 1],
                        k=mesh_data.cells[0].data[:, 2],
                        intensity=mesh_data.points[:, 2],
                        colorscale='Viridis'
                        ))

# fig.show()
# display(SVG(fig.to_image(format='svg', scale=1)))
Image(fig.to_image(format="jpg", scale=2))
Out[4]:

Raytracing¶

In [5]:
from radarsimpy.rt import scene
import time

tic = time.time()
data = scene(radar, targets, density=0.2, noise=True, debug=False)

baseband = data['baseband']
toc = time.time()

print('Exec time:', toc-tic, 's')
Exec time: 0.21518993377685547 s

Radar signal processing¶

Range-Doppler processing¶

In [6]:
from scipy import signal
import radarsimpy.processing as proc

range_window = signal.chebwin(radar.samples_per_pulse, at=60)
doppler_window = signal.chebwin(radar.transmitter.pulses, at=60)
range_doppler = proc.range_doppler_fft(baseband, rwin=range_window, dwin=doppler_window)
In [7]:
max_range = (3e8 * radar.receiver.fs *
             radar.transmitter.pulse_length /
             radar.transmitter.bandwidth / 2)
unambiguous_speed = 3e8 / radar.transmitter.prp[0] / \
    radar.transmitter.fc_vect[0] / 2

range_axis = np.linspace(
    0, max_range, radar.samples_per_pulse, endpoint=False)

doppler_axis = np.linspace(
    -unambiguous_speed, 0, radar.transmitter.pulses, endpoint=False)

fig = go.Figure()
fig.add_trace(go.Surface(x=range_axis, y=doppler_axis, z=20 *
              np.log10(np.abs(range_doppler[0, :, :])), colorscale='Rainbow'))

fig.update_layout(
    title='Range Doppler',
    height=600,
    scene=dict(
        xaxis=dict(title='Range (m)'),
        yaxis=dict(title='Velocity (m/s)'),
        zaxis=dict(title='Amplitude (dB)'),
    ),
    margin=dict(l=0, r=0, b=60, t=100),
    legend=dict(orientation='h'),
)

# fig.show()
# display(SVG(fig.to_image(format='svg', scale=1)))
Image(fig.to_image(format="jpg", scale=2))
Out[7]:
In [8]:
rdop_avg = np.mean(np.abs(range_doppler), axis=0)
cfar = proc.cfar_os_2d(rdop_avg, guard=2, trailing=20, pfa=1e-3, k=1500)
# cfar = proc.cfar_ca_2d(rdop_avg, guard=2, trailing=20, pfa=1e-3)
In [9]:
fig = go.Figure()
fig.add_trace(go.Surface(x=range_axis, y=doppler_axis, z=20 *
              np.log10(rdop_avg), colorscale='Rainbow'))
fig.add_trace(go.Surface(x=range_axis, y=doppler_axis, z=20 *
              np.log10(cfar), colorscale='Viridis', showscale=False))

fig.update_layout(
    title='Range Doppler and CFAR',
    height=600,
    scene=dict(
        xaxis=dict(title='Range (m)'),
        yaxis=dict(title='Velocity (m/s)'),
        zaxis=dict(title='Amplitude (dB)'),
    ),
    margin=dict(l=0, r=0, b=60, t=100),
    legend=dict(orientation='h'),
)

# fig.show()
# display(SVG(fig.to_image(format='svg', scale=1)))
Image(fig.to_image(format="jpg", scale=2))
Out[9]: