fmcw测距 matlab%% FMCW雷达信号干扰消除与距离测量
clear; close all; clc;
%% 参数设置
c = 3e8; % 光速 (m/s)
fc = 24e9; % 中心频率 (Hz)
B = 100e6; % 带宽 (Hz)
T = 5e-6; % 扫频周期 (s)
max_range = 150; % 最大作用距离 (m)
num_signals = 5; % 每文件信号段数量
L = 100; % FFT零填充倍数
files = {'fmcw_range_20210530_013230.mat', 'fmcw_range_20210530_013250.mat'};
% 计算理论频率分辨率
range_res = c / (2 * B); % 理论距离分辨率
fprintf('理论距离分辨率: %.2f m\n', range_res);
% 创建结果目录
if ~exist('results', 'dir')
mkdir('results');
end
%% 主处理循环
for file_idx = 1:length(files)
filename = files{file_idx};
fprintf('\n处理文件: %s\n', filename);
% 加载数据
data = load(filename);
% 检查数据结构
if isfield(data, 'data')
radar_data = data.data;
else
error('文件 %s 中未找到 "data" 结构', filename);
end
distances = zeros(1, num_signals); % 存储各段距离测量值
all_results = cell(1, num_signals);
% 创建文件专属结果目录
[~, name] = fileparts(filename);
result_dir = fullfile('results', name);
if ~exist(result_dir, 'dir')
mkdir(result_dir);
end
for k = 1:num_signals
% 获取当前信号段
if isfield(radar_data{k}, 'I') && isfield(radar_data{k}, 'Q')
I_orig = radar_data{k}.I;
Q_orig = radar_data{k}.Q;
else
error('信号段 %d 缺少 I 或 Q 数据', k);
end
N = length(I_orig); % 信号长度
fs = N / T; % 采样率 (Hz)
t = (0:N-1)/fs * 1e6; % 时间向量 (微秒)
% ===== 1. 原始信号分析 =====
s_orig = I_orig + 1j*Q_orig; % 原始复信号
% 时域绘图
fig1 = figure('Name', sprintf('信号 %d - 原始时域', k), 'Position', [100, 100, 1200, 800]);
subplot(2,1,1);
plot(t, I_orig, 'b', 'LineWidth', 1.5);
title(sprintf('原始信号 - 段 %d - I 通道', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
subplot(2,1,2);
plot(t, Q_orig, 'r', 'LineWidth', 1.5);
title(sprintf('原始信号 - 段 %d - Q 通道', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
% 保存图像
saveas(fig1, fullfile(result_dir, sprintf('signal_%d_original_time.png', k)));
% 频域分析 (FFT)
f = (-N/2:N/2-1)*(fs/N)/1e6; % 频率轴 (MHz)
S_orig = fftshift(fft(s_orig, N));
fig2 = figure('Name', sprintf('信号 %d - 原始频域', k), 'Position', [100, 100, 1200, 600]);
plot(f, abs(S_orig), 'LineWidth', 1.5);
title(sprintf('原始频谱 - 段 %d', k));
xlabel('频率 (MHz)'); ylabel('幅度');
xlim([-fs/2/1e6, fs/2/1e6]);
grid on;
% 保存图像
saveas(fig2, fullfile(result_dir, sprintf('signal_%d_original_freq.png', k)));
% ===== 2. 干扰分析 =====
% 检查直流偏移
DC_I = mean(I_orig);
DC_Q = mean(Q_orig);
fprintf('文件 %s - 段 %d: DC偏移 - I: %.4f, Q: %.4f\n', filename, k, DC_I, DC_Q);
% 检查频谱异常峰值
[max_val, max_idx] = max(abs(S_orig));
fprintf('文件 %s - 段 %d: 主导频率: %.2f MHz\n', filename, k, f(max_idx));
% 频谱统计
power_total = sum(abs(S_orig).^2);
power_dc = abs(S_orig(floor(N/2)+1))^2; % DC分量
power_ratio_dc = power_dc / power_total * 100;
% 检查其他干扰峰值
threshold = 0.1 * max_val; % 峰值检测阈值
peak_mask = abs(S_orig) > threshold;
peak_mask(floor(N/2)-10:floor(N/2)+10) = 0; % 排除DC附近
num_peaks = sum(peak_mask);
fprintf('文件 %s - 段 %d: DC功率占比: %.2f%%, 检测到 %d 个干扰峰值\n', ...
filename, k, power_ratio_dc, num_peaks);
% ===== 3. 干扰消除 =====
% 消除直流偏移
I_clean = I_orig - DC_I;
Q_clean = Q_orig - DC_Q;
s_clean = I_clean + 1j*Q_clean;
% 如果检测到其他干扰峰值,应用带阻滤波器
if num_peaks > 0
% 识别主要干扰频率
[pks, locs] = findpeaks(abs(S_orig), 'MinPeakHeight', threshold);
[~, idx] = sort(pks, 'descend');
num_to_filter = min(3, length(locs)); % 最多过滤3个最强干扰
for p = 1:num_to_filter
freq_idx = locs(idx(p));
freq_hz = f(freq_idx) * 1e6; % 转换为Hz
% 设计带阻滤波器
bw = 0.1e6; % 带宽100kHz
f0 = freq_hz;
notch_filter = designfilt('bandstopiir', ...
'FilterOrder', 4, ...
'HalfPowerFrequency1', f0 - bw/2, ...
'HalfPowerFrequency2', f0 + bw/2, ...
'SampleRate', fs);
% 应用滤波器
I_clean = filtfilt(notch_filter, I_clean);
Q_clean = filtfilt(notch_filter, Q_clean);
end
s_clean = I_clean + 1j*Q_clean;
fprintf('文件 %s - 段 %d: 已应用带阻滤波器消除 %d 个干扰频率\n', filename, k, num_to_filter);
end
% ===== 4. 处理前后对比 =====
% 时域对比
fig3 = figure('Name', sprintf('信号 %d - 时域对比', k), 'Position', [100, 100, 1200, 800]);
subplot(2,2,1);
plot(t, I_orig, 'b', 'LineWidth', 1.5);
title(sprintf('原始信号 - I 通道 (段 %d)', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
subplot(2,2,2);
plot(t, I_clean, 'b', 'LineWidth', 1.5);
title(sprintf('处理后信号 - I 通道 (段 %d)', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
subplot(2,2,3);
plot(t, Q_orig, 'r', 'LineWidth', 1.5);
title(sprintf('原始信号 - Q 通道 (段 %d)', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
subplot(2,2,4);
plot(t, Q_clean, 'r', 'LineWidth', 1.5);
title(sprintf('处理后信号 - Q 通道 (段 %d)', k));
xlabel('时间 (\mus)'); ylabel('幅度');
grid on;
% 保存图像
saveas(fig3, fullfile(result_dir, sprintf('signal_%d_time_comparison.png', k)));
% 频域对比
S_clean = fftshift(fft(s_clean, N));
fig4 = figure('Name', sprintf('信号 %d - 频域对比', k), 'Position', [100, 100, 1200, 600]);
subplot(1,2,1);
plot(f, abs(S_orig), 'b', 'LineWidth', 1.5);
title(sprintf('原始频谱 (段 %d)', k));
xlabel('频率 (MHz)'); ylabel('幅度');
xlim([-fs/2/1e6, fs/2/1e6]);
grid on;
subplot(1,2,2);
plot(f, abs(S_clean), 'r', 'LineWidth', 1.5);
title(sprintf('处理后频谱 (段 %d)', k));
xlabel('频率 (MHz)'); ylabel('幅度');
xlim([-fs/2/1e6, fs/2/1e6]);
grid on;
% 保存图像
saveas(fig4, fullfile(result_dir, sprintf('signal_%d_freq_comparison.png', k)));
% ===== 5. 高精度频率估计 =====
% 零填充FFT
N_zp = N * L; % 零填充后点数
s_clean_zp = [s_clean, zeros(1, N_zp - N)];
S_zp = fft(s_clean_zp, N_zp);
f_zp = (0:N_zp-1)*(fs/N_zp);
% 只考虑正频率部分
S_zp_pos = S_zp(1:floor(N_zp/2));
f_zp_pos = f_zp(1:floor(N_zp/2));
% 寻找主峰 (排除直流附近)
search_min = 0.1e6; % 100kHz
search_max = 40e6; % 40MHz
search_range = find(f_zp_pos > search_min & f_zp_pos < search_max);
if isempty(search_range)
error('在有效频率范围内未找到峰值');
end
[~, idx] = max(abs(S_zp_pos(search_range)));
peak_idx = search_range(1) + idx - 1;
f_est = f_zp_pos(peak_idx);
% 频率估计精度验证
peak_val = abs(S_zp_pos(peak_idx));
second_peak = max(abs(S_zp_pos(search_range(1:idx-1))));
if isempty(second_peak)
second_peak = max(abs(S_zp_pos(search_range(idx+1:end))));
end
snr = 20*log10(peak_val / second_peak);
fprintf('文件 %s - 段 %d: 估计频率: %.2f MHz, 信噪比: %.2f dB\n', ...
filename, k, f_est/1e6, snr);
% ===== 6. 距离计算 =====
R = (f_est * c * T) / (2 * B);
distances(k) = R;
% 保存结果
all_results{k} = struct(...
'I_orig', I_orig, ...
'Q_orig', Q_orig, ...
'I_clean', I_clean, ...
'Q_clean', Q_clean, ...
'S_orig', S_orig, ...
'S_clean', S_clean, ...
'f_est', f_est, ...
'distance', R, ...
'DC_offset', [DC_I, DC_Q], ...
'num_peaks', num_peaks);
end
% 结果汇总
avg_distance = mean(distances);
std_distance = std(distances);
fprintf('\n===== 文件 %s 距离测量结果 =====\n', filename);
for k = 1:num_signals
fprintf('段 %d: %.4f m\n', k, distances(k));
end
fprintf('平均距离: %.4f m\n', avg_distance);
fprintf('标准差: %.6f m\n', std_distance);
% 保存所有结果
save(fullfile(result_dir, 'processed_results.mat'), 'all_results', 'distances', 'avg_distance', 'std_distance');
% 绘制所有段距离测量结果
fig5 = figure('Name', sprintf('文件 %s 距离测量结果', filename), 'Position', [100, 100, 800, 600]);
bar(1:num_signals, distances);
hold on;
yline(avg_distance, 'r--', 'LineWidth', 2);
title(sprintf('文件 %s 距离测量结果', filename));
xlabel('信号段');
ylabel('距离 (m)');
legend('各段测量值', sprintf('平均值: %.4f m', avg_distance));
grid on;
% 保存图像
saveas(fig5, fullfile(result_dir, 'distance_results.png'));
end
fprintf('\n处理完成!所有结果保存在 results 目录\n');
最新发布