LFM/NLFM波形库

文件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('测试完成,已清理');

使用说明

  1. 文件存放结构:将上述4个.m文件放在同一目录下,或按方案建议放在src/config/目录下

  2. 依赖关系LFM_ConfigNLFM_Config继承WFM_ConfigLibManager依赖前三个类

  3. MATLAB版本:需要R2019b或更高版本(支持arguments块和string类型)

  4. 测试方法:每个文件底部的验证脚本可直接复制到MATLAB命令行或保存为独立测试文件运行

所有代码均包含完整的错误处理、参数验证和中文注释,符合您方案中的接口定义。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VectorShift

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值