As I started researching FMCW radar signals, I discovered a popular reference code for FMCW simulation in Github. One of the most important things that I still don't understand is the parameters Number of Chirps: Nd=128. The code shows that the instantaneous frequency of transmitted FMCW signal still increases after the first Tchirp until it finishes all 128 Tchirp periods. This is very different from what is defined in the theory for the working principles of FMCW radar as in the following figure. The question is that do we need to retransmit signals with the instantaneous frequency raising from Fc in next time chirp periods over a whole time frame or we can just transmit one continuous signal over the hold time frame. Subsequently, what are the differences in the results for the estimation for Range and Doppler for these two generation methods? Thank you! Figure 1:

clear all
%pkg load control % octave packages
%pkg load signal 

%% Radar Specifications 
% Frequency of operation = 77GHz
% Max Range = 200m
% Range Resolution = 1 m
% Max Velocity = 100 m/s

c = 3e8
%% User Defined Range and Velocity of target
% *%TODO* :
% define the target's initial position and velocity. Note : Velocity
% remains contant
range = 110
vel = -20
max_range = 200
range_res = 1
max_vel = 100 % m/s
%% FMCW Waveform Generation

% *%TODO* :
%Design the FMCW waveform by giving the specs of each of its parameters.
% Calculate the Bandwidth (B), Chirp Time (Tchirp) and Slope (slope) of the FMCW
% chirp using the requirements above.
B = c / (2*range_res)
Tchirp = 5.5 * 2 * (max_range/c)  
slope = B/Tchirp

%Operating carrier frequency of Radar 
fc= 77e9;             %carrier freq
%The number of chirps in one sequence. Its ideal to have 2^ value for the ease of running the FFT
%for Doppler Estimation. 
Nd=128;                   % #of doppler cells OR #of sent periods % number of chirps

%The number of samples on each chirp. 
Nr=1024;                  %for length of time OR # of range cells

% Timestamp for running the displacement scenario for every sample on each
% chirp
t=linspace(0,Nd*Tchirp,Nr*Nd); %total time for samples

%Creating the vectors for Tx, Rx and Mix based on the total samples input.
Tx=zeros(1,length(t)); %transmitted signal
Rx=zeros(1,length(t)); %received signal
Mix = zeros(1,length(t)); %beat signal

%Similar vectors for range_covered and time delay.

%% Signal generation and Moving Target simulation
% Running the radar scenario over the time. 

for i=1:length(t)         
  % *%TODO* 
  %For each time stamp update the Range of the Target for constant velocity. 
  r_t(i) = range + (vel*t(i));
  td(i) = (2 * r_t(i)) / c;

  % *%TODO* :
  %For each time sample we need update the transmitted and
  %received signal. 

  Tx(i)   = cos(2*pi*(fc*t(i) + (slope*t(i)^2)/2 ) );
  Rx(i)   = cos(2*pi*(fc*(t(i) -td(i)) + (slope * (t(i)-td(i))^2)/2 ) );
  % *%TODO* :
  %Now by mixing the Transmit and Receive generate the beat signal
  %This is done by element wise matrix multiplication of Transmit and
  %Receiver Signal

  Mix(i) = Tx(i) .* Rx(i);


 % *%TODO* :
%reshape the vector into Nr*Nd array. Nr and Nd here would also define the size of
%Range and Doppler FFT respectively.
Mix = reshape(Mix, [Nr, Nd]);

 % *%TODO* :
%run the FFT on the beat signal along the range bins dimension (Nr) and
signal_fft = fft(Mix, Nr);

 % *%TODO* :
% Take the absolute value of FFT output
signal_fft = abs(signal_fft);
signal_fft = signal_fft ./ max(signal_fft); % Normalize

 % *%TODO* :
% Output of FFT is double sided signal, but we are interested in only one side of the spectrum.
% Hence we throw out half of the samples.
signal_fft = signal_fft(1 : Nr/2-1);

%plotting the range
figure ('Name','Range from First FFT')
% *%TODO* :
% plot FFT output 
axis ([0 180 0 1]);
title('Range from First FFT');
ylabel('Amplitude (Normalized)');
xlabel('Range [m]');
axis ([0 200 0 1]);

% The 2D FFT implementation is already provided here. This will run a 2DFFT
% on the mixed signal (beat signal) output and generate a range doppler
% map.You will implement CFAR on the generated RDM

% Range Doppler Map Generation.
% The output of the 2D FFT is an image that has reponse in the range and
% doppler FFT bins. So, it is important to convert the axis from bin sizes
% to range and doppler based on their Max values.


% 2D FFT using the FFT size for both dimensions.
signal_fft2 = fft2(Mix,Nr,Nd);

% Taking just one side of signal from Range dimension.
signal_fft2 = signal_fft2(1:Nr/2,1:Nd);
signal_fft2 = fftshift (signal_fft2);

RDM = abs(signal_fft2);
RDM = 10*log10(RDM) ;

%use the surf function to plot the output of 2DFFT and to show axis in both

doppler_axis = linspace(-100,100,Nd);
range_axis = linspace(-200,200,Nr/2)*((Nr/2)/400);

title('Amplitude and Range From FFT2');
  • $\begingroup$ Have you tried to run this and see what results it produces? $\endgroup$
    – Envidia
    Dec 3, 2023 at 21:13
  • $\begingroup$ Yes, the results from this simulation were suited to its predefined constraints. However, the considering thing is the required total bandwidth being significantly large. $\endgroup$
    – Rayzain
    Dec 4, 2023 at 6:18
  • $\begingroup$ Which is not required. The implementation uses an unnecessary amount of bandwidth. It also doesn't calculate the range and Doppler using the appropriate formulas, it uses fixed axes to fit the example. I would recommend that you seek radar theory and examples from more established sources. If you're interested, I will post an answer that goes into more detail. $\endgroup$
    – Envidia
    Dec 4, 2023 at 6:23
  • $\begingroup$ I believe that your answer will help me to understand the basics of the FMCW signal. I appreciate your help. $\endgroup$
    – Rayzain
    Dec 4, 2023 at 8:06
  • $\begingroup$ A link to the GitHub repo you're using would be nice, thanks. $\endgroup$
    – Envidia
    Dec 4, 2023 at 22:48

2 Answers 2


What the code is trying to do is simply collect 128 FMCW returns off a moving target to form a range-Doppler map (RDM). The implementation and simulation eventually turns out sort of ok, but shows a misunderstanding of how FMCW actually works.

I didn't take a super-deep dive into the code, but at first glance the simulation does a few things incorrectly (both theoretically and practicality wise):

  1. The system uses excessive bandwidth by continuously increasing the frequency across all pulses.
  2. The maximum range and velocity capabilities of the waveform and its series of pulses is greater than what is assumed.
  3. Overall the simulation is in a sense hard-coded to fit the scenario and doesn't really show how to truly calculate what is going on.

The bandwidth of the FMCW pulse to achieve a range resolution of 1 m is 150 MHz. When you plot the frequency as a function of time as it's used in the loop, the frequency reaches approximately 510 MHz:

enter image description here

The range-Doppler map (RDM) produced by the simulation looks as follows:

enter image description here

I picked the peak of the response as well as a few points around the "noise" to get a rough idea of the noise level. Note the quotations, because in this simulation there is no noise simulated at all, which was another giveaway that something was wrong.

I've made some minor changes and ignored other parts of the code:

  1. I reset the time after every pulse back to 0 in the sweep, so that the pulse only sweeps the required bandwidth.
  2. Calculated range and Doppler axes using the appropriate formulas.
  3. Formed the RDM slightly differently.

By resetting the timer to 0 after every pulse, you get the following frequency (baseband) sweep (cut to only the first few pulses):

enter image description here

Notice that the sweep never gets above 150 MHz as desired.

And the new RDM looks like this:

enter image description here

Placed a marker at the target's peak at the bottom, along with a few samples around the map (much lower values). Notice that now you can see artifacts of the 2D FFT since there is no "noise" to cover it up, which is expected. The target is more accurately resolved, and notice the larger range and Doppler axes.

You might also want to look at this answer. As I said in the comments, I recommend that you look at more established radar theory sources than GitHub.

  • $\begingroup$ Your answer clarified my considerations. Could you suggest any references that you find suitable for a newcomer to this subject? Many thanks for considering my request. $\endgroup$
    – Rayzain
    Dec 5, 2023 at 5:29
  • $\begingroup$ @Rayzain Since you're getting into these types of details, I would recommend Fundamentals of Radar Signal Processing by Mark A. Richards. $\endgroup$
    – Envidia
    Dec 10, 2023 at 5:21

It looks like they transmit one long chirp signal, but subdivide the received signal into 128 segments before running the FFT-based algorithm.

The idea is that the target moves closer to the radar during the long chirp, so range isn't just a single number. By subdividing the received signal, they can measure how range evolves over time and thus determine velocity. Knowing velocity also improves the range estimate because a Doppler shift in a (sawtooth slope) FMCW radar results in a range offset.

I'm not sure if this method is a good one, because the long chirp requires excessive bandwidth (which might not be a problem at 77GHz). You can probably achieve the same result using multiple shorter chirps and processing the received signals together in a 2D-FFT to capture range evolution over time.

  • $\begingroup$ Thank you for your response! So if I want to transmit two shorter chirps, say: Tx(t) = [r(t) r(t)], r(t) = Acos(2*pifct + 2*piK*t^2/2) The received signal: Rx(t) = [r(t-t1) r(t-t2)], t1 = [0 ... end of chirp1], t2 = [end of chirp1 ... end of chirp 2] So, I just need to reshape the received signal into the matrix of size (2, samples per chirp), and then apply 2D-FFT to plot the Range-Doppler Map? I want to ask whether this process is correct or if there is any additional assumption added to the received signal. $\endgroup$
    – Rayzain
    Dec 3, 2023 at 14:26
  • $\begingroup$ The code from OP is simply a bad implementation and simulation. It primarily wastes bandwidth by continuously increasing the frequency across all 128 pulses. The person who wrote the code was trying to do a simple set of 128 FMCW returns to form a range-Doppler map. Anything beyond this, you would be attempting stepped-FM or stepped-FMCW which is a more advanced technique which I doubt was the intent. $\endgroup$
    – Envidia
    Dec 3, 2023 at 21:41
  • $\begingroup$ @Rayzain - With multiple chirps in a sawtooth pattern, the result after demodulation (multiplication of rx and tx signal) should be the same as with one long chirp, except for some glitching around the time when the frequency jumps back to start. You want to mask out those regions (windowing) before running the FFT. $\endgroup$
    – Rainer P.
    Dec 4, 2023 at 8:30

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.