Can someone help me with performing range fft on FMCW Radar ADC data?

I have a dataset of raw ADC data from an FMCW Radar which is in the form where for each radar frame, its raw data (*.mat) has 4 dimension:
samples (128), chirps (255), receivers (4), transmitters (2). I am unable to perform range FFT analysis on such data. Can someone help me with the same?

15 Kommentare

Please post a sample .mat file. Please post the equation that describes how range is related to your signals. Please post the code you have written thus far. If the code gives an error, what is the error message?
You have described a .mat file with 2040 sets of 128 samples. Do you expect to get 2040 range estimates, i.e. one range estimate from each set of 128 samples? If the answer is no, then please explain how different sets of 128 samples combine to give a range estimate.
I am attatching below a sample .mat file for your reference. I am actually refering to the dataset on this github repo to perform range fft analysis. The code I have written so far is :
function [range_profiles] = perform_range_fft(adcData, fs, c)
if ~isequal(size(adcData), [128, 255, 4, 2])
error('Data dimensions must be (samples, chirps, receivers, transmitters)');
end
% Create empty array for range profiles
range_profiles = zeros(size(adcData, 2), size(adcData, 3), size(adcData, 4));
% FFT parameters
N = size(adcData, 1); % Number of samples per chirp
% Loop through chirps, receivers, and transmitters
for chirp_index = 1:size(adcData, 2)
for receiver_index = 1:size(adcData, 3)
for transmitter_index = 1:size(adcData, 4)
% Extract single-antenna data for this chirp and receiver-transmitter pair
single_data = adcData(:, chirp_index, receiver_index, transmitter_index);
% Apply windowing (optional, uncomment if desired)
%window = hamming(N);
%single_data = single_data .* window;
% Perform FFT with zero-padding for improved resolution
fft_output = fft(single_data, length(single_data) * 2, 1);
% Shift result to center frequencies (optional)
fft_output = fftshift(fft_output);
% Calculate frequency axis (linearly mapped with zero-padding)
f_axis = linspace(-fs/2, fs/2 - fs/N, N * 2);
% Calculate range axis (convert frequency to range using speed of light)
range_axis = c / (f_axis);
% Take magnitude (absolute value) for range profile
range_profile = abs(fft_output);
% Store range profile
range_profiles(chirp_index, receiver_index, transmitter_index) = range_profile;
end
end
end
end
I am getting an error message at the line "range_axis=c/f_axis" :
Error using /
Matrix dimensions must agree.
Error in perform_range_fft (line 34)
range_axis = c / (f_axis);
I am trying to find out the range fft for all the provided files in the dataset.
Use
range_axis = c ./ (f_axis);
to fix the first error. Then you get another error:
Unable to perform assignment because the size of the left side is 1-by-1 and the size
of the right side is 256-by-1.
Error in perform_range_fft_wr (line 39)
range_profiles(chirp_index, receiver_index, transmitter_index) = range_profile;
This is an error because you are attempting to assign a 256x1 complex vector to a scalar value. I do not know what your intent is here.
single_data is a 128x1 complex vector. Why do you pad single_data with 128 zeros before computing the FFT?
William Rose
William Rose am 20 Feb. 2024
Bearbeitet: William Rose am 20 Feb. 2024
[Edit: fix spelling errors]
Now I see that you answered my question about zero-padding in your comments: you zero pad to improve the range resolution. I am not convinced that this gives a real improvement in range resolution. You have not added any additional data, so how can it improve real resolution? Some people zero-pad time-domain signals, to improve frequency resolution. It is true that this will give you a finer grid along the frequency axis, which makes it look like you have improved the frequency resolution. What really happens is that the prior spectral data gets interpolated, in a slightly complicated way, to a finer grid. Therefore the apparent improvement in frequency resolution is illusory. I syspect this is true for radar signal procressing also, but I could bre wrong.
I wrote script radarRanging.m, to call your function. I modified your function "perform_range_fft", to avoid an error, and gave it a new name (I added "_wr"), to distinguish it from your original posting. Script radarRanging.m plots the 8 complex traces for chirp 1 (four receivers, two transmitters). The script reads the data from the file you posted earlier, 000003.mat. The script makes the figure below. I am not sure what the results mean, but I was curious to know what the traces look like. The script and your modified function are attached.
This paper, sections III.A,B,C, has important information for the signal processing.
Do you know if the frame you slected, 000003.mat, has a target in the field of view? If so, do you know its approximate range, velocity, angle?
I am attatching the camera captured image of 000003.mat file. I do not know anything about its approximate range, velocty or angle. These values are exactly what I am trying to find out. Because essentially I want to find out at what range this man on the cycle( in the image) is at and at what velocity is he moving infront of the camera.
Thanks.
I estimate the distance on the order of 12 m, because a standard parking lot stripe is a bout 20 feet. The radial velocity is about zero, because the bike is traveling perpendicular to the view. The angle to center of target is about 3 degrees left of center, assuming 120 degree horizontal field of view, which is roughly consistent with the stripes. The angular resolution is about 15 degrees, so this target angle is more or less zero.
Now your task is to see if the FFT of the data supports this.
I am trying to plot a graph of maginitude versus range after obtaining the range_profiles from perform_range_fft_wr file, but something does not seem right as the graph makes no sense at all. I am attatching both the code and graph below.
figure;
plot(range_axis, range_profile);
xlabel('Range (m)');
ylabel('Magnitude');
title('Range Profile (Chirp 1, Receiver 2, Transmitter 1)');
You need to convert the 4D file to a 3D file, by combining dimensions 3 and 4 into a isngle dimension 3. This will make the 2 transmitters and 4 recievers look like 8 receivers. See this image, from here.
Therefore you want the rearranged array to have the data as follows, along dimension 3:
[R1T1, R2T1, R3T1, R4T1, R1T2, R2T2, R3T2, R4T2].
You do not want
[R1T1, R1T2, R2T1, R2T2,...].
Original adcData has size (128,255,4,2). Let's make one, and combine dimensions 3 and 4, and check that it worked as desired.
adcData=zeros(128,255,4,2);
for i=1:4
for j=1:2
adcData(1,1,i,j)=10*i+j;
end
end
adcData3=reshape(adcData,[128,255,8]);
disp(squeeze(adcData3(1,1,:))')
11 21 31 41 12 22 32 42
This is the ordering we wanted. Therefore you should do
adcData3=reshape(adcData,[128,255,8]);
before starting with the 2D or 3D FFTs.
William Rose
William Rose am 21 Feb. 2024
Bearbeitet: William Rose am 21 Feb. 2024
I would not expect the results from function perform_range_fft_wr.m to be correct. As I said in an earlier comment, a line near the end assigned a vector to a scalar, so I changed it to use only the first element of the vector, so that it would run. But, as I said, I don't know what your intent was. Gao et al., arxiv 2022, say "In this paper, we adopt the 3-DFFT [8] to obtain the 3D radar cube that is named the range-velocity-angle (RVA) heatmap” (top p.2), and they show a 3D FFT in their Figure 5. Therefore I think you need to make changes to the data analysis. Carefully read the references which they cite, including Gao et al., 2019.
If we reshape the adcData into 3 dimensions then the code provided would not work because we are iterating through three loops where we go through chirp_index,reciever_index and transmitter_index.
My final intent is to find out the range,velocity and angle of approach of the cycle.I have never worked on radar data before hence this is very new to me.
I have read through those cited papers, and from my understanding plotting the magnitudes of the range_profile that we obtained in the perform_range_fft_wr.m file should work right? What is the mistake due to which we are getting a wrong plot?
"I have never worked on radar data before hence this is very new to me. " That makes two of us.
"From my understanding, plotting the magnitudes of the range_profile that we obtained in the perform_range_fft_wr.m file should work, right?" I have a different understanding. I think the signal analysis in that function, as it appears above, does not implement the method of Gao et al. Therefore I am not surprised that the function above does not give the desired result.
I think I know what the issue is, but it's complicated. If you wish to discuss this further, please email me by clicking on the envelope icon that appears when you click on the "WR" next to my comments.

@William Rose @Pratham Hai, I am happy to connect with you. I am also working on the range fft with 8192 samples of 512 ramps. Here I am able performing the fft I am getting the range as per input but problem is magnitude calculations (y axis). I am getting more than required for example as per my test I am suppose to get the input power of adc pluse processing gain of the range fft instead more power is coming its 2x times coming. Can you help me get out this.

@A,
I recommend that you post your question as a new question on Matlab Answers. Attach code and data files. Explain what part of the output from your code indicates that an error has occurred.
Maybe take a look at the feature extraction script here: https://github.com/shikuzen/FMCW_radar_features_matlab

Melden Sie sich an, um zu kommentieren.

Antworten (1)

George
George am 7 Aug. 2025
Bearbeitet: George am 7 Aug. 2025
The Radar Toolbox has a few examples that you can look at to help you process this radar data. Your processing will probably consist of a couple of steps, depending on your goals.
First, I am assuming that the radar uses time division multiplexing (switching off between transmit antennas to improve angular resolution) based on the structure of your data. So, you will probably want to re-arrange the data into a 128x255x8 virtual array. You can learn more about this in the examples linked at the end of my post.
If you are only interested in performing a range fft, the phased.RangeResponse object with processing mode set to "FFT" would be helpful:
You can similarly use the phased.RangeDoppler response or phased.RangeAngle response to generate Doppler and angle responses along with the range response:
For more comprehensive examples that demonstrate signal processing that seems very similar to what you are trying to acheive, check these out. One simulates a Texas Instruments radar board and performs signal processing. The other performs signal processing on real data collected with this board:

Kategorien

Produkte

Version

R2023b

Gefragt:

am 13 Feb. 2024

Bearbeitet:

am 7 Aug. 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by