文件1: WFM_Config.m (基础配置类)
matlab
复制
classdef WFM_Config < handle
%WFM_Config 波形参数基础配置类
% 定义波形参数的抽象基类,提供参数验证和序列化功能
properties
waveformType (1,1) string = "LFM" % 波形类型标识 ('LFM'/'NLFM')
sampleRate (1,1) double = 10e6 % 采样率 (Hz),范围: 1e6 ~ 10e9
bandwidth (1,1) double = 1e6 % 带宽 (Hz),范围: 1e6 ~ 1e9
pulseWidth (1,1) double = 10e-6 % 脉宽 (s),范围: 1e-6 ~ 1e-3
centerFreq (1,1) double = 0 % 中心频率 (Hz),默认: 0 (基带)
prf (1,1) double = 1000 % 脉冲重复频率 (Hz),可选
end
methods
function obj = WFM_Config()
% 构造函数 - 使用默认值初始化
end
function status = validate(obj)
%VALIDATE 验证参数合法性
% 检查项: 采样率≥2*带宽,脉宽>0,带宽>0
status = true;
% 检查带宽范围
if obj.bandwidth <= 0 || obj.bandwidth > 1e9
error('WFM_Config:InvalidBandwidth', ...
'带宽必须在 (0, 1e9] Hz 范围内,当前值: %.2e', obj.bandwidth);
end
% 检查采样率范围
if obj.sampleRate < 1e6 || obj.sampleRate > 10e9
error('WFM_Config:InvalidSampleRate', ...
'采样率必须在 [1e6, 10e9] Hz 范围内,当前值: %.2e', obj.sampleRate);
end
% 检查奈奎斯特采样定理
if obj.sampleRate < 2 * obj.bandwidth
error('WFM_Config:NyquistViolation', ...
'采样率 (%.2e) 必须 ≥ 2*带宽 (%.2e)', obj.sampleRate, 2*obj.bandwidth);
end
% 检查脉宽
if obj.pulseWidth <= 1e-6 || obj.pulseWidth > 1e-3
error('WFM_Config:InvalidPulseWidth', ...
'脉宽必须在 (1e-6, 1e-3] s 范围内,当前值: %.2e', obj.pulseWidth);
end
% 检查PRF(如果设置)
if obj.prf <= 0
error('WFM_Config:InvalidPRF', ...
'PRF必须 > 0,当前值: %.2e', obj.prf);
end
end
function s = toStruct(obj)
%TOSTRUCT 将配置转换为结构体
s = struct();
props = properties(obj);
for i = 1:length(props)
s.(props{i}) = obj.(props{i});
end
end
function fromStruct(obj, s)
%FROMSTRUCT 从结构体恢复配置
% 输入: 参数结构体
% 输出: 配置对象实例 (self modified)
if ~isstruct(s)
error('WFM_Config:InvalidInput', '输入必须是结构体');
end
props = properties(obj);
for i = 1:length(props)
if isfield(s, props{i})
obj.(props{i}) = s.(props{i});
end
end
end
function bt = getTimeBandwidthProduct(obj)
%GETTIMEBANDWIDTHPRODUCT 计算时宽带宽积 (BT)
% 公式: BT = B * T
bt = obj.bandwidth * obj.pulseWidth;
end
function disp(obj)
%DISP 显示配置信息
fprintf('=== WFM_Config ===\n');
fprintf('波形类型: %s\n', obj.waveformType);
fprintf('采样率: %.3e Hz\n', obj.sampleRate);
fprintf('带宽: %.3e Hz\n', obj.bandwidth);
fprintf('脉宽: %.3e s\n', obj.pulseWidth);
fprintf('中心频率: %.3e Hz\n', obj.centerFreq);
fprintf('时宽带宽积 (BT): %.2f\n', obj.getTimeBandwidthProduct());
fprintf('==================\n');
end
end
end
验证脚本:
matlab
复制
% 测试 WFM_Config
config = WFM_Config();
config.waveformType = "LFM";
config.sampleRate = 20e6;
config.bandwidth = 5e6;
config.pulseWidth = 10e-6;
disp('=== 测试验证 ===');
try
config.validate();
disp('验证通过');
catch ME
disp(['验证失败: ' ME.message]);
end
disp('=== 测试结构体转换 ===');
s = config.toStruct();
disp(s);
config2 = WFM_Config();
config2.fromStruct(s);
disp('从结构体恢复的对象:');
config2.disp();
disp('=== 测试BT计算 ===');
fprintf('BT = %.2f\n', config.getTimeBandwidthProduct());
文件2: LFM_Config.m (LFM参数配置)
matlab
复制
classdef LFM_Config < WFM_Config
%LFM_Config LFM波形专用参数配置
% 继承自 WFM_Config,添加LFM特有参数
properties
chirpDirection (1,1) string = "up" % 调频方向 ('up'/'down'/'triangular')
startFreq (1,1) double = 0 % 起始频率偏移 (Hz),相对中心频率
stopFreq (1,1) double = 0 % 终止频率偏移 (Hz),相对中心频率
end
methods
function obj = LFM_Config()
% 构造函数
obj@WFM_Config();
obj.waveformType = "LFM";
obj.chirpDirection = "up";
end
function K = getChirpRate(obj)
%GETCHIRPRATE 计算调频斜率 (Hz/s)
% 公式: K = (stopFreq - startFreq) / pulseWidth
effectiveBW = obj.bandwidth;
switch lower(obj.chirpDirection)
case "up"
K = effectiveBW / obj.pulseWidth;
case "down"
K = -effectiveBW / obj.pulseWidth;
case "triangular"
% 三角波斜率按半脉宽计算
K = 2 * effectiveBW / obj.pulseWidth;
otherwise
error('LFM_Config:InvalidDirection', ...
'无效的调频方向: %s', obj.chirpDirection);
end
% 应用相对频率偏移修正
K = (obj.stopFreq - obj.startFreq) / obj.pulseWidth + K;
end
function fHandle = generateFreqFunc(obj)
%GENERATEFREQFUNC 生成频率函数句柄 f(t)
% 输出: 函数句柄,输入时间t返回瞬时频率
K = obj.getChirpRate();
f0 = obj.centerFreq + obj.startFreq;
switch lower(obj.chirpDirection)
case "up"
fHandle = @(t) f0 + K * t;
case "down"
fHandle = @(t) f0 + K * t;
case "triangular"
% 三角波:前半段上扫,后半段下扫
T = obj.pulseWidth;
fHandle = @(t) f0 + K * min(t, T-t);
otherwise
error('LFM_Config:InvalidDirection', ...
'无效的调频方向: %s', obj.chirpDirection);
end
end
function phiHandle = generatePhaseFunc(obj)
%GENERATEPHASEFUNC 生成相位函数句柄 phi(t)
% 输出: 函数句柄,输入时间t返回瞬时相位
K = obj.getChirpRate();
f0 = obj.centerFreq + obj.startFreq;
switch lower(obj.chirpDirection)
case {"up", "down"}
% φ(t) = 2π(f0*t + 0.5*K*t^2)
phiHandle = @(t) 2 * pi * (f0 * t + 0.5 * K * t.^2);
case "triangular"
T = obj.pulseWidth;
% 三角波相位需要分段积分
phiHandle = @(t) arrayfun(@(ti) obj.triangularPhase(ti, f0, K, T), t);
otherwise
error('LFM_Config:InvalidDirection', ...
'无效的调频方向: %s', obj.chirpDirection);
end
end
function phi = triangularPhase(~, t, f0, K, T)
% 辅助函数:计算三角波在时刻t的相位
if t <= T/2
% 前半段:线性调频上扫
phi = 2 * pi * (f0 * t + 0.5 * K * t^2);
else
% 后半段:线性调频下扫
t1 = T/2;
phi1 = 2 * pi * (f0 * t1 + 0.5 * K * t1^2);
% 下扫斜率为 -K
phi = phi1 + 2 * pi * ((f0 + K*t1) * (t-t1) - 0.5 * K * (t-t1)^2);
end
end
function status = validate(obj)
%VALIDATE 验证LFM参数
% 先调用父类验证
status = validate@WFM_Config(obj);
% 验证调频方向
validDirections = ["up", "down", "triangular"];
if ~ismember(lower(obj.chirpDirection), validDirections)
error('LFM_Config:InvalidDirection', ...
'调频方向必须是: up, down, triangular');
end
% 验证频率偏移在带宽范围内
totalBW = abs(obj.stopFreq - obj.startFreq) + obj.bandwidth;
if totalBW > obj.sampleRate / 2
warning('LFM_Config:BandwidthWarning', ...
'总带宽 (%.2e) 接近奈奎斯特极限 (%.2e)', totalBW, obj.sampleRate/2);
end
status = true;
end
function disp(obj)
%DISP 显示LFM配置
fprintf('=== LFM_Config ===\n');
fprintf('波形类型: %s\n', obj.waveformType);
fprintf('采样率: %.3e Hz\n', obj.sampleRate);
fprintf('带宽: %.3e Hz\n', obj.bandwidth);
fprintf('脉宽: %.3e s\n', obj.pulseWidth);
fprintf('中心频率: %.3e Hz\n', obj.centerFreq);
fprintf('调频方向: %s\n', obj.chirpDirection);
fprintf('起始频率偏移: %.3e Hz\n', obj.startFreq);
fprintf('终止频率偏移: %.3e Hz\n', obj.stopFreq);
fprintf('调频斜率: %.3e Hz/s\n', obj.getChirpRate());
fprintf('时宽带宽积 (BT): %.2f\n', obj.getTimeBandwidthProduct());
fprintf('==================\n');
end
end
end
验证脚本:
matlab
复制
% 测试 LFM_Config
lfm = LFM_Config();
lfm.sampleRate = 100e6;
lfm.bandwidth = 20e6;
lfm.pulseWidth = 10e-6;
lfm.chirpDirection = "up";
disp('=== 测试LFM验证 ===');
try
lfm.validate();
disp('验证通过');
lfm.disp();
catch ME
disp(['错误: ' ME.message]);
end
disp('=== 测试频率函数 ===');
t = linspace(0, lfm.pulseWidth, 100);
fHandle = lfm.generateFreqFunc();
f_inst = fHandle(t);
figure('Name', 'LFM频率函数');
plot(t*1e6, fInst/1e6, 'LineWidth', 2);
xlabel('时间 (\mus)');
ylabel('频率 (MHz)');
title('LFM瞬时频率');
grid on;
disp('=== 测试相位函数 ===');
phiHandle = lfm.generatePhaseFunc();
phi = phiHandle(t);
figure('Name', 'LFM相位函数');
plot(t*1e6, unwrap(phi), 'LineWidth', 2);
xlabel('时间 (\mus)');
ylabel('相位 (rad)');
title('LFM瞬时相位');
grid on;
% 测试三角波
disp('=== 测试三角波 ===');
lfm2 = LFM_Config();
lfm2.chirpDirection = "triangular";
lfm2.bandwidth = 10e6;
lfm2.pulseWidth = 20e-6;
lfm2.sampleRate = 50e6;
fHandle2 = lfm2.generateFreqFunc();
t2 = linspace(0, lfm2.pulseWidth, 200);
figure('Name', '三角波频率');
plot(t2*1e6, fHandle2(t2)/1e6, 'LineWidth', 2);
xlabel('时间 (\mus)');
ylabel('频率 (MHz)');
title('三角调频瞬时频率');
grid on;
文件3: NLFM_Config.m (NLFM参数配置)
matlab
复制
classdef NLFM_Config < WFM_Config
%NLFM_Config NLFM波形专用参数配置
% 基于窗函数设计,使用驻定相位原理
properties
windowType (1,1) string = "hamming" % 窗函数类型
windowParam (1,1) double = 0 % 窗函数参数 (如Kaiser的β值)
spectralShape (1,1) string = "low_sidelobe" % 频谱整形目标
end
properties (Constant)
VALID_WINDOWS = ["hamming", "hann", "kaiser", "taylor", "chebyshev", "blackman"]
end
methods
function obj = NLFM_Config()
% 构造函数
obj@WFM_Config();
obj.waveformType = "NLFM";
obj.windowType = "hamming";
end
function wHandle = getWindowFunction(obj)
%GETWINDOWFUNCTION 获取窗函数句柄
% 输出: 窗函数w(f),输入归一化频率[-0.5, 0.5],输出幅度
switch lower(obj.windowType)
case "hamming"
wHandle = @(f) obj.hammingWindow(f);
case "hann"
wHandle = @(f) obj.hannWindow(f);
case "kaiser"
beta = obj.windowParam;
if beta == 0, beta = 6; end % 默认beta值
wHandle = @(f) obj.kaiserWindow(f, beta);
case "taylor"
nbar = max(4, round(obj.windowParam));
if nbar == 0, nbar = 4; end
sll = 30; % 默认旁瓣电平
wHandle = @(f) obj.taylorWindow(f, nbar, sll);
case "chebyshev"
sll = obj.windowParam;
if sll == 0, sll = 40; end
wHandle = @(f) obj.chebyshevWindow(f, sll);
case "blackman"
wHandle = @(f) obj.blackmanWindow(f);
otherwise
error('NLFM_Config:InvalidWindow', ...
'不支持的窗函数类型: %s', obj.windowType);
end
end
function T = getGroupDelayFunc(obj)
%GETGROUPDELAYFUNC 计算群时延函数 T(f)
% 基于驻定相位原理: T(f) ∝ ∫W(v)dv
wHandle = obj.getWindowFunction();
% 创建频率网格
N = 1024;
f = linspace(-0.5, 0.5, N);
W = wHandle(f);
% 数值积分计算群时延
% T(f) = T0 * cumsum(W) / sum(W)
% 其中 T0 = pulseWidth
cumW = cumtrapz(f, W);
cumW = cumW / max(cumW); % 归一化到 [0,1]
% 映射到实际时间 [0, pulseWidth]
T = obj.pulseWidth * cumW;
% 返回插值函数
T = @(f_query) interp1(f, T, f_query, 'linear', 'extrap');
end
function fHandle = getFreqModulationFunc(obj)
%GETFREQMODULATIONFUNC 计算调频函数 f(t) (群时延反函数)
% 输出: 函数句柄,需数值求解反函数
% 获取群时延函数 T(f)
wHandle = obj.getWindowFunction();
N = 1024;
f_grid = linspace(-0.5, 0.5, N);
W = wHandle(f_grid);
% 计算群时延
cumW = cumtrapz(f_grid, W);
T_grid = obj.pulseWidth * (cumW / max(cumW));
% 创建时间网格并反插值
t_grid = linspace(0, obj.pulseWidth, N);
% 确保单调性(窗函数总是正的,所以T(f)单调递增)
[T_unique, idx_unique] = unique(T_grid, 'stable');
f_unique = f_grid(idx_unique);
% 反函数:给定t,返回f
fHandle = @(t_query) obj.centerFreq + obj.bandwidth * ...
interp1(T_unique, f_unique, t_query, 'linear', 'extrap');
end
function status = validate(obj)
%VALIDATE 验证NLFM参数
status = validate@WFM_Config(obj);
% 验证窗函数类型
if ~ismember(lower(obj.windowType), obj.VALID_WINDOWS)
error('NLFM_Config:InvalidWindow', ...
'窗函数类型必须是: %s', strjoin(obj.VALID_WINDOWS, ', '));
end
% 验证窗函数参数
switch lower(obj.windowType)
case "kaiser"
if obj.windowParam < 0
error('NLFM_Config:InvalidParam', 'Kaiser beta必须 ≥ 0');
end
case "chebyshev"
if obj.windowParam <= 0 || obj.windowParam > 200
error('NLFM_Config:InvalidParam', 'Chebyshev旁瓣电平必须在 (0, 200] dB');
end
end
status = true;
end
function disp(obj)
%DISP 显示NLFM配置
fprintf('=== NLFM_Config ===\n');
fprintf('波形类型: %s\n', obj.waveformType);
fprintf('采样率: %.3e Hz\n', obj.sampleRate);
fprintf('带宽: %.3e Hz\n', obj.bandwidth);
fprintf('脉宽: %.3e s\n', obj.pulseWidth);
fprintf('中心频率: %.3e Hz\n', obj.centerFreq);
fprintf('窗函数类型: %s\n', obj.windowType);
fprintf('窗函数参数: %.2f\n', obj.windowParam);
fprintf('频谱整形目标: %s\n', obj.spectralShape);
fprintf('时宽带宽积 (BT): %.2f\n', obj.getTimeBandwidthProduct());
fprintf('==================\n');
end
end
methods (Static, Access = private)
% 各种窗函数实现(归一化频率域 [-0.5, 0.5])
function w = hammingWindow(~, f)
f = f + 0.5; % 移动到 [0, 1]
w = 0.54 - 0.46 * cos(2 * pi * f);
w(f < 0 | f > 1) = 0;
end
function w = hannWindow(~, f)
f = f + 0.5;
w = 0.5 * (1 - cos(2 * pi * f));
w(f < 0 | f > 1) = 0;
end
function w = kaiserWindow(~, f, beta)
f = f + 0.5;
% Kaiser窗使用修正的零阶贝塞尔函数
w = besseli(0, beta * sqrt(1 - ((2*f - 1)).^2)) / besseli(0, beta);
w(f < 0 | f > 1) = 0;
end
function w = taylorWindow(~, f, nbar, sll)
% 简化的Taylor窗实现
f = f + 0.5;
% 使用近似实现
w = ones(size(f));
A = acosh(10^(abs(sll)/20)) / pi;
for n = 1:(nbar-1)
w = w + 2 * besseli(0, pi*A*sqrt(1-(2*f-1).^2)) * cos(2*pi*n*(f-0.5));
end
w(f < 0 | f > 1) = 0;
w = w / max(w);
end
function w = chebyshevWindow(~, f, sll)
% 简化的Chebyshev窗实现
f = abs(f) * 2; % 归一化到 [0, 1]
gamma = 10^(abs(sll)/20);
w = cosh(sqrt(max(0, gamma^2 - f.^2))) / cosh(gamma);
w(f > 1) = 10^(-abs(sll)/20);
end
function w = blackmanWindow(~, f)
f = f + 0.5;
w = 0.42 - 0.5 * cos(2*pi*f) + 0.08 * cos(4*pi*f);
w(f < 0 | f > 1) = 0;
end
end
end
验证脚本:
matlab
复制
% 测试 NLFM_Config
nlfm = NLFM_Config();
nlfm.sampleRate = 100e6;
nlfm.bandwidth = 20e6;
nlfm.pulseWidth = 10e-6;
nlfm.windowType = "kaiser";
nlfm.windowParam = 6;
disp('=== 测试NLFM验证 ===');
try
nlfm.validate();
disp('验证通过');
nlfm.disp();
catch ME
disp(['错误: ' ME.message]);
end
disp('=== 测试窗函数 ===');
wHandle = nlfm.getWindowFunction();
f = linspace(-0.5, 0.5, 1000);
figure('Name', 'NLFM窗函数');
plot(f, wHandle(f), 'LineWidth', 2);
xlabel('归一化频率');
ylabel('幅度');
title(['窗函数: ' char(nlfm.windowType)]);
grid on;
disp('=== 测试群时延函数 ===');
T_func = nlfm.getGroupDelayFunc();
f_test = linspace(-0.5, 0.5, 100);
T_vals = arrayfun(T_func, f_test);
figure('Name', '群时延特性');
plot(f_test, T_vals*1e6, 'LineWidth', 2);
xlabel('归一化频率');
ylabel('群时延 (\mus)');
title('群时延函数 T(f)');
grid on;
disp('=== 测试调频函数 ===');
fmod_func = nlfm.getFreqModulationFunc();
t = linspace(0, nlfm.pulseWidth, 1000);
f_inst = arrayfun(fmod_func, t);
figure('Name', 'NLFM调频曲线');
plot(t*1e6, (f_inst - nlfm.centerFreq)/1e6, 'LineWidth', 2);
xlabel('时间 (\mus)');
ylabel('频率偏移 (MHz)');
title('NLFM瞬时频率');
grid on;
% 对比不同窗函数
disp('=== 对比不同窗函数 ===');
figure('Name', '窗函数对比');
hold on;
windows = ["hamming", "hann", "kaiser", "blackman"];
colors = lines(length(windows));
for i = 1:length(windows)
nlfm_test = NLFM_Config();
nlfm_test.windowType = windows(i);
if windows(i) == "kaiser"
nlfm_test.windowParam = 6;
end
wH = nlfm_test.getWindowFunction();
plot(f, wH(f), 'Color', colors(i,:), 'LineWidth', 2, 'DisplayName', windows(i));
end
legend('show');
xlabel('归一化频率');
ylabel('幅度');
title('不同窗函数对比');
grid on;
hold off;
文件4: LibManager.m (波形库管理器)
matlab
复制
classdef LibManager < handle
%LIBMANAGER 波形库管理器
% 管理波形库的存储、检索和版本控制
properties
libraryPath (1,1) string = "data/library" % 库文件存储路径
waveformTable (:,:) table % 波形索引表
end
methods
function obj = LibManager(libPath)
% 构造函数
if nargin > 0
obj.libraryPath = libPath;
end
% 确保目录存在
if ~exist(obj.libraryPath, 'dir')
mkdir(obj.libraryPath);
end
% 初始化或加载索引表
obj.loadIndexTable();
end
function loadIndexTable(obj)
% 加载索引表,如果不存在则创建
indexFile = fullfile(obj.libraryPath, "waveform_index.mat");
if exist(indexFile, 'file')
data = load(indexFile);
obj.waveformTable = data.waveformTable;
else
% 创建空表
obj.waveformTable = table('Size', [0, 5], ...
'VariableTypes', {'string', 'string', 'string', 'double', 'string'}, ...
'VariableNames', {'WaveformID', 'Name', 'Type', 'CreateTime', 'FilePath'});
end
end
function saveIndexTable(obj)
% 保存索引表
indexFile = fullfile(obj.libraryPath, "waveform_index.mat");
waveformTable = obj.waveformTable; % 创建局部变量用于保存
save(indexFile, 'waveformTable');
end
function id = addWaveform(obj, config, name)
%ADDWAVEFORM 添加波形到库
% 输入: 配置对象, 波形名称
% 输出: 唯一波形ID
if ~isa(config, 'WFM_Config')
error('LibManager:InvalidConfig', '配置对象必须是WFM_Config或其子类');
end
% 验证配置
config.validate();
% 生成唯一ID
timestamp = datetime('now', 'Format', 'yyyyMMddHHmmssSSS');
randomStr = sprintf('%04d', randi(9999));
id = string(config.waveformType) + "_" + timestamp + "_" + randomStr;
% 构建文件名
fileName = id + ".mat";
filePath = fullfile(obj.libraryPath, fileName);
% 序列化配置
configStruct = config.toStruct();
waveformType = config.waveformType; % 保存类型信息
% 保存到.mat文件
save(filePath, 'configStruct', 'waveformType');
% 更新索引表
newRow = table({id}, {name}, {config.waveformType}, ...
posixtime(datetime('now')), {char(fileName)}, ...
'VariableNames', {'WaveformID', 'Name', 'Type', 'CreateTime', 'FilePath'});
obj.waveformTable = [obj.waveformTable; newRow];
% 保存索引
obj.saveIndexTable();
fprintf('波形已添加: ID=%s, 名称=%s\n', id, name);
end
function config = getWaveform(obj, waveformID)
%GETWAVEFORM 从库中检索波形配置
% 输入: 波形ID
% 输出: 配置对象实例
% 查找索引
idx = find(obj.waveformTable.WaveformID == waveformID);
if isempty(idx)
error('LibManager:WaveformNotFound', '未找到波形ID: %s', waveformID);
end
% 加载文件
filePath = fullfile(obj.libraryPath, obj.waveformTable.FilePath(idx));
data = load(filePath);
% 根据类型创建对应的对象
switch lower(data.waveformType)
case "lfm"
config = LFM_Config();
case "nlfm"
config = NLFM_Config();
otherwise
config = WFM_Config();
end
% 恢复配置
config.fromStruct(data.configStruct);
end
function ids = queryWaveforms(obj, filter)
%QUERYWAVEFORMS 条件查询波形
% 输入: 过滤条件结构体 (如{type:'LFM', bandwidth:[1e6,10e6]})
% 输出: 匹配的波形ID数组
if isempty(obj.waveformTable)
ids = string.empty;
return;
end
% 初始全部匹配
mask = true(height(obj.waveformTable), 1);
% 按类型过滤
if isfield(filter, 'type')
mask = mask & (obj.waveformTable.Type == upper(filter.type));
end
% 获取所有配置进行详细过滤
if isfield(filter, 'bandwidth') || isfield(filter, 'pulseWidth')
tempMask = mask;
for i = 1:height(obj.waveformTable)
if ~tempMask(i), continue; end
try
cfg = obj.getWaveform(obj.waveformTable.WaveformID(i));
% 带宽范围过滤
if isfield(filter, 'bandwidth')
bw = cfg.bandwidth;
if bw < filter.bandwidth(1) || bw > filter.bandwidth(2)
tempMask(i) = false;
continue;
end
end
% 脉宽范围过滤
if isfield(filter, 'pulseWidth')
pw = cfg.pulseWidth;
if pw < filter.pulseWidth(1) || pw > filter.pulseWidth(2)
tempMask(i) = false;
end
end
catch
tempMask(i) = false;
end
end
mask = tempMask;
end
ids = obj.waveformTable.WaveformID(mask);
end
function status = removeWaveform(obj, waveformID)
%REMOVEWAVEFORM 删除指定波形
% 输入: 波形ID
% 输出: 成功返回true
idx = find(obj.waveformTable.WaveformID == waveformID);
if isempty(idx)
warning('LibManager:WaveformNotFound', '未找到波形ID: %s', waveformID);
status = false;
return;
end
% 删除文件
filePath = fullfile(obj.libraryPath, obj.waveformTable.FilePath(idx));
if exist(filePath, 'file')
delete(filePath);
end
% 更新索引表
obj.waveformTable(idx, :) = [];
obj.saveIndexTable();
fprintf('波形已删除: %s\n', waveformID);
status = true;
end
function status = exportLibrary(obj, filePath)
%EXPORTLIBRARY 导出整个库为单个文件
% 输入: 导出文件路径
try
% 收集所有波形数据
allConfigs = {};
allIDs = {};
allNames = {};
for i = 1:height(obj.waveformTable)
try
cfg = obj.getWaveform(obj.waveformTable.WaveformID(i));
allConfigs{end+1} = cfg.toStruct();
allIDs{end+1} = obj.waveformTable.WaveformID(i);
allNames{end+1} = obj.waveformTable.Name(i);
catch ME
warning('导出时跳过波形 %s: %s', ...
obj.waveformTable.WaveformID(i), ME.message);
end
end
% 保存到单个文件
libraryData = struct();
libraryData.configs = allConfigs;
libraryData.ids = allIDs;
libraryData.names = allNames;
libraryData.exportTime = datetime('now');
libraryData.version = "1.0";
save(filePath, 'libraryData');
fprintf('库已导出到: %s (共%d个波形)\n', filePath, length(allConfigs));
status = true;
catch ME
error('LibManager:ExportFailed', '导出失败: %s', ME.message);
end
end
function status = importLibrary(obj, filePath)
%IMPORTLIBRARY 从文件导入库
% 输入: 库文件路径
if ~exist(filePath, 'file')
error('LibManager:FileNotFound', '文件不存在: %s', filePath);
end
try
data = load(filePath);
libraryData = data.libraryData;
importedCount = 0;
for i = 1:length(libraryData.configs)
try
cfgStruct = libraryData.configs{i};
% 根据类型创建对象
switch lower(cfgStruct.waveformType)
case "lfm"
cfg = LFM_Config();
case "nlfm"
cfg = NLFM_Config();
otherwise
cfg = WFM_Config();
end
cfg.fromStruct(cfgStruct);
% 生成新ID避免冲突
obj.addWaveform(cfg, libraryData.names{i} + "_imported");
importedCount = importedCount + 1;
catch ME
warning('导入时跳过条目 %d: %s', i, ME.message);
end
end
fprintf('成功导入 %d/%d 个波形\n', importedCount, length(libraryData.configs));
status = true;
catch ME
error('LibManager:ImportFailed', '导入失败: %s', ME.message);
end
end
function listAll(obj)
%LISTALL 列出库中所有波形
if isempty(obj.waveformTable)
disp('波形库为空');
return;
end
fprintf('\n=== 波形库内容 (%d个波形) ===\n', height(obj.waveformTable));
fprintf('%-30s %-20s %-10s %-20s\n', 'ID', '名称', '类型', '创建时间');
fprintf('%s\n', repmat('-', 1, 80));
for i = 1:height(obj.waveformTable)
dt = datetime(obj.waveformTable.CreateTime(i), 'ConvertFrom', 'posixtime');
fprintf('%-30s %-20s %-10s %-20s\n', ...
extractBefore(obj.waveformTable.WaveformID(i), min(30, strlength(obj.waveformTable.WaveformID(i)))+1), ...
extractBefore(obj.waveformTable.Name(i), min(20, strlength(obj.waveformTable.Name(i)))+1), ...
obj.waveformTable.Type(i), ...
char(dt));
end
fprintf('========================\n\n');
end
end
end
验证脚本:
matlab
复制
% 测试 LibManager
disp('=== 测试LibManager ===');
% 清理测试目录
testPath = "test_library";
if exist(testPath, 'dir')
rmdir(testPath, 's');
end
% 创建管理器
lib = LibManager(testPath);
disp('库管理器创建成功');
% 创建测试波形
lfm1 = LFM_Config();
lfm1.bandwidth = 10e6;
lfm1.pulseWidth = 5e-6;
lfm1.sampleRate = 50e6;
lfm1.chirpDirection = "up";
lfm2 = LFM_Config();
lfm2.bandwidth = 20e6;
lfm2.pulseWidth = 10e-6;
lfm2.sampleRate = 100e6;
lfm2.chirpDirection = "down";
nlfm1 = NLFM_Config();
nlfm1.bandwidth = 15e6;
nlfm1.pulseWidth = 8e-6;
nlfm1.sampleRate = 80e6;
nlfm1.windowType = "hamming";
% 添加波形
disp('=== 添加波形 ===');
id1 = lib.addWaveform(lfm1, "LFM_Up_10MHz");
id2 = lib.addWaveform(lfm2, "LFM_Down_20MHz");
id3 = lib.addWaveform(nlfm1, "NLFM_Hamming_15MHz");
lib.listAll();
% 检索波形
disp('=== 检索波形 ===');
cfg_retrieved = lib.getWaveform(id2);
disp('检索到的配置:');
cfg_retrieved.disp();
% 查询波形
disp('=== 查询波形 (带宽10-20MHz) ===');
filter.bandwidth = [5e6, 20e6];
found_ids = lib.queryWaveforms(filter);
disp(['找到 ' num2str(length(found_ids)) ' 个匹配波形:']);
disp(found_ids);
% 导出库
disp('=== 导出库 ===');
exportPath = fullfile(testPath, "export.mat");
lib.exportLibrary(exportPath);
% 删除波形
disp('=== 删除波形 ===');
lib.removeWaveform(id1);
lib.listAll();
% 重新导入
disp('=== 导入库 ===');
lib2 = LibManager("test_import");
lib2.importLibrary(exportPath);
lib2.listAll();
% 清理
rmdir(testPath, 's');
rmdir("test_import", 's');
disp('测试完成,已清理');
使用说明
-
文件存放结构:将上述4个
.m文件放在同一目录下,或按方案建议放在src/config/目录下 -
依赖关系:
LFM_Config和NLFM_Config继承WFM_Config,LibManager依赖前三个类 -
MATLAB版本:需要R2019b或更高版本(支持
arguments块和string类型) -
测试方法:每个文件底部的验证脚本可直接复制到MATLAB命令行或保存为独立测试文件运行
所有代码均包含完整的错误处理、参数验证和中文注释,符合您方案中的接口定义。

6235

被折叠的 条评论
为什么被折叠?



