基于 MATLAB 的序贯蒙特卡洛概率假设密度多目标跟踪实现

MATLAB 实现,涵盖了 SMC-PHD 滤波器的核心算法、可视化工具和性能评估。

1. 核心算法实现

1.1 主程序:main_SMC_PHD.m

matlab 复制代码
%% 主程序:SMC-PHD 多目标跟踪
clear; clc; close all;

%% 参数设置
params = struct();
params.T = 100;                       % 总时间步数
params.dt = 1;                        % 时间步长
params.area = [0 100 0 100];          % 监控区域 [xmin xmax ymin ymax]

% 目标动态模型参数
params.motion_model = 'CV';           % 匀速模型
params.F = [1 params.dt 0 0;          % 状态转移矩阵
            0 1 0 0;
            0 0 1 params.dt;
            0 0 0 1];
params.Q = diag([0.1, 0.05, 0.1, 0.05]);  % 过程噪声协方差

% 观测模型参数
params.H = [1 0 0 0;                 % 观测矩阵
            0 0 1 0];
params.R = diag([2, 2]);              % 观测噪声协方差

% 滤波器参数
params.N_particles = 5000;            % 粒子总数
params.p_survival = 0.99;            % 存活概率
params.p_detection = 0.95;           % 检测概率
params.birth_intensity = 0.1;        % 新生目标强度
params.clutter_rate = 5;              % 杂波率
params.resample_threshold = 0.5;     % 重采样阈值
params.prune_threshold = 1e-5;       % 剪枝阈值
params.merge_distance = 4;           % 合并距离

% 新生目标模型
params.birth_model.type = 'gaussian';
params.birth_model.mean = [20, 2, 20, 2; 80, -2, 20, 2; 50, 1, 80, -1]';  % 多个新生区域
params.birth_model.cov = repmat(diag([10, 1, 10, 1]), [1, 1, 3]);

%% 生成仿真数据
fprintf('生成仿真数据...\n');
[true_trajectories, measurements] = generate_simulation_data(params);

%% 初始化SMC-PHD滤波器
fprintf('初始化SMC-PHD滤波器...\n');
[particles, weights] = initialize_filter(params);

%% 主循环
fprintf('开始滤波...\n');
estimated_targets = cell(params.T, 1);
estimated_numbers = zeros(params.T, 1);
performance_metrics = struct();

for k = 1:params.T
    fprintf('时间步 %d/%d\n', k, params.T);
    
    % 获取当前时刻观测
    z_k = measurements{k};
    
    % 预测步
    [particles, weights] = phd_prediction(particles, weights, params, k);
    
    % 更新步
    [weights, likelihood_map] = phd_update(particles, weights, z_k, params);
    
    % 归一化权重
    total_weight = sum(weights);
    if total_weight > 0
        weights = weights / total_weight;
    end
    
    % 重采样
    effective_ratio = 1 / sum(weights.^2) / params.N_particles;
    if effective_ratio < params.resample_threshold
        [particles, weights] = systematic_resample(particles, weights);
    end
    
    % 剪枝
    [particles, weights] = prune_particles(particles, weights, params.prune_threshold);
    
    % 估计目标状态
    [estimated_targets{k}, estimated_numbers(k)] = extract_target_states(...
        particles, weights, params);
    
    % 记录性能
    performance_metrics(k).time = k;
    performance_metrics(k).n_true = length(true_trajectories);
    performance_metrics(k).n_est = estimated_numbers(k);
    performance_metrics(k).particles = length(weights);
end

%% 性能评估
fprintf('\n性能评估:\n');
evaluate_performance(true_trajectories, estimated_targets, params);

%% 可视化
visualize_results(true_trajectories, measurements, estimated_targets, ...
    particles, weights, params, performance_metrics);

1.2 初始化函数:initialize_filter.m

matlab 复制代码
function [particles, weights] = initialize_filter(params)
%% 初始化SMC-PHD滤波器
    
    % 均匀分布初始化粒子
    N = params.N_particles;
    
    % 位置均匀分布
    x_min = params.area(1); x_max = params.area(2);
    y_min = params.area(3); y_max = params.area(4);
    
    particles = zeros(4, N);
    particles(1, :) = x_min + (x_max - x_min) * rand(1, N);  % x位置
    particles(2, :) = -2 + 4 * rand(1, N);                  % x速度
    particles(3, :) = y_min + (y_max - y_min) * rand(1, N);  % y位置
    particles(4, :) = -2 + 4 * rand(1, N);                  % y速度
    
    % 均匀权重
    weights = ones(1, N) / N;
    
    % 添加新生目标粒子
    [birth_particles, birth_weights] = generate_birth_particles(params, 0.1*N);
    
    % 合并
    particles = [particles, birth_particles];
    weights = [weights, birth_weights];
    
    % 归一化
    weights = weights / sum(weights);
end

1.3 预测步:phd_prediction.m

matlab 复制代码
function [predicted_particles, predicted_weights] = phd_prediction(...
    particles, weights, params, k)
%% PHD预测步
    
    N = size(particles, 2);
    
    % 存活粒子传播
    survival_mask = rand(1, N) < params.p_survival;
    survival_particles = particles(:, survival_mask);
    survival_weights = weights(survival_mask) * params.p_survival;
    
    % 运动模型传播
    N_survival = size(survival_particles, 2);
    predicted_survival = zeros(4, N_survival);
    
    for i = 1:N_survival
        % 状态转移
        predicted_survival(:, i) = params.F * survival_particles(:, i);
        
        % 添加过程噪声
        noise = mvnrnd(zeros(4,1), params.Q)';
        predicted_survival(:, i) = predicted_survival(:, i) + noise;
        
        % 边界处理
        predicted_survival(1, i) = max(params.area(1), ...
            min(params.area(2), predicted_survival(1, i)));
        predicted_survival(3, i) = max(params.area(3), ...
            min(params.area(4), predicted_survival(3, i)));
    end
    
    % 生成新生目标
    N_birth = round(params.birth_intensity * N);
    [birth_particles, birth_weights] = generate_birth_particles(params, N_birth);
    
    % 合并存活粒子和新生粒子
    predicted_particles = [predicted_survival, birth_particles];
    predicted_weights = [survival_weights, birth_weights];
end

1.4 更新步:phd_update.m

matlab 复制代码
function [updated_weights, likelihood_map] = phd_update(...
    particles, weights, measurements, params)
%% PHD更新步
    
    N = size(particles, 2);
    M = size(measurements, 2);
    
    % 初始化更新权重
    updated_weights = zeros(1, N);
    likelihood_map = zeros(N, M);
    
    if M == 0
        % 无观测情况
        updated_weights = (1 - params.p_detection) * weights;
        return;
    end
    
    % 计算杂波项
    clutter_volume = (params.area(2)-params.area(1)) * (params.area(4)-params.area(3));
    clutter_intensity = params.clutter_rate / clutter_volume;
    
    % 预计算观测似然
    for m = 1:M
        for n = 1:N
            % 预测观测
            z_pred = params.H * particles(:, n);
            
            % 计算似然
            innovation = measurements(:, m) - z_pred;
            likelihood_map(n, m) = mvnpdf(innovation', [0, 0], params.R);
        end
    end
    
    % 计算每个观测的归一化项
    normalization_terms = zeros(1, M);
    for m = 1:M
        term = clutter_intensity;
        for n = 1:N
            term = term + params.p_detection * likelihood_map(n, m) * weights(n);
        end
        normalization_terms(m) = term;
    end
    
    % 更新每个粒子的权重
    for n = 1:N
        % 漏检项
        miss_detection = (1 - params.p_detection) * weights(n);
        
        % 检测项
        detection_sum = 0;
        for m = 1:M
            if normalization_terms(m) > 0
                detection_sum = detection_sum + (params.p_detection * ...
                    likelihood_map(n, m) * weights(n)) / normalization_terms(m);
            end
        end
        
        updated_weights(n) = miss_detection + detection_sum;
    end
    
    % 处理数值稳定性
    updated_weights(updated_weights < 1e-100) = 1e-100;
end

1.5 目标状态提取:extract_target_states.m

matlab 复制代码
function [target_states, n_targets] = extract_target_states(...
    particles, weights, params)
%% 从PHD中提取目标状态
    
    % 估计目标数量
    total_weight = sum(weights);
    n_targets = round(total_weight);
    
    if n_targets == 0
        target_states = [];
        return;
    end
    
    % 复制粒子用于聚类
    particle_positions = particles(1:2, :);
    particle_weights = weights;
    
    % 使用均值漂移聚类
    target_states = zeros(2, n_targets);
    cluster_centers = [];
    
    for t = 1:n_targets
        if isempty(particle_positions) || sum(particle_weights) == 0
            break;
        end
        
        % 找到权重最大的粒子
        [~, max_idx] = max(particle_weights);
        center = particle_positions(:, max_idx);
        
        % 均值漂移迭代
        bandwidth = params.merge_distance;
        converged = false;
        iterations = 0;
        max_iterations = 20;
        
        while ~converged && iterations < max_iterations
            old_center = center;
            
            % 计算核函数
            distances = sqrt(sum((particle_positions - center).^2, 1));
            kernel = exp(-0.5 * (distances / bandwidth).^2);
            
            % 加权平均
            weighted_sum = sum(kernel .* particle_weights .* particle_positions, 2);
            weight_sum = sum(kernel .* particle_weights);
            
            if weight_sum > 0
                center = weighted_sum / weight_sum;
            end
            
            % 检查收敛
            if norm(center - old_center) < 0.1
                converged = true;
            end
            
            iterations = iterations + 1;
        end
        
        % 保存聚类中心
        target_states(:, t) = center;
        cluster_centers = [cluster_centers, center];
        
        % 移除已聚类的粒子
        distances_to_center = sqrt(sum((particle_positions - center).^2, 1));
        keep_mask = distances_to_center > 2 * bandwidth;
        particle_positions = particle_positions(:, keep_mask);
        particle_weights = particle_weights(keep_mask);
        
        if isempty(particle_positions)
            break;
        end
        
        % 重新归一化权重
        particle_weights = particle_weights / sum(particle_weights);
    end
    
    % 如果找到的目标少于估计数量,裁剪
    target_states = target_states(:, 1:min(n_targets, size(target_states, 2)));
    n_targets = size(target_states, 2);
end

2. 辅助函数

2.1 数据生成:generate_simulation_data.m

matlab 复制代码
function [true_trajectories, measurements] = generate_simulation_data(params)
%% 生成多目标跟踪仿真数据
    
    T = params.T;
    
    % 定义目标轨迹
    n_targets = 3;
    true_trajectories = cell(n_targets, 1);
    
    % 目标1:从左侧进入,向右移动
    x1 = zeros(4, T);
    x1(:, 1) = [20; 2; 20; 0];
    for t = 2:T
        x1(:, t) = params.F * x1(:, t-1) + mvnrnd([0,0,0,0], params.Q)';
    end
    true_trajectories{1} = x1;
    
    % 目标2:从顶部进入,向下移动
    x2 = zeros(4, T);
    x2(:, 1) = [50; 1; 80; -2];
    for t = 2:T
        x2(:, t) = params.F * x2(:, t-1) + mvnrnd([0,0,0,0], params.Q)';
    end
    true_trajectories{2} = x2;
    
    % 目标3:在中间出现,随机移动
    x3 = zeros(4, T);
    x3(:, 1) = [80; -1; 30; 1];
    for t = 2:T
        x3(:, t) = params.F * x3(:, t-1) + mvnrnd([0,0,0,0], params.Q)';
    end
    true_trajectories{3} = x3;
    
    % 生成测量数据
    measurements = cell(T, 1);
    
    for t = 1:T
        z_t = [];
        
        % 来自真实目标的测量
        for i = 1:n_targets
            if rand < params.p_detection
                z_true = params.H * true_trajectories{i}(:, t);
                z_noisy = z_true + mvnrnd([0,0], params.R)';
                
                % 边界检查
                if z_noisy(1) >= params.area(1) && z_noisy(1) <= params.area(2) && ...
                   z_noisy(2) >= params.area(3) && z_noisy(2) <= params.area(4)
                    z_t = [z_t, z_noisy];
                end
            end
        end
        
        % 杂波
        n_clutter = poissrnd(params.clutter_rate);
        for c = 1:n_clutter
            clutter = [params.area(1) + (params.area(2)-params.area(1))*rand;
                       params.area(3) + (params.area(4)-params.area(3))*rand];
            z_t = [z_t, clutter];
        end
        
        measurements{t} = z_t;
    end
end

2.2 重采样函数:systematic_resample.m

matlab 复制代码
function [resampled_particles, resampled_weights] = systematic_resample(particles, weights)
%% 系统重采样
    
    N = size(particles, 2);
    
    % 计算累积分布
    cdf = cumsum(weights);
    
    % 生成均匀随机数
    u = (rand + (0:N-1)) / N;
    
    % 重采样索引
    indices = zeros(1, N);
    i = 1;
    
    for j = 1:N
        while cdf(i) < u(j)
            i = i + 1;
        end
        indices(j) = i;
    end
    
    % 重采样
    resampled_particles = particles(:, indices);
    resampled_weights = ones(1, N) / N;
end

2.3 剪枝函数:prune_particles.m

matlab 复制代码
function [pruned_particles, pruned_weights] = prune_particles(particles, weights, threshold)
%% 剪枝:移除权重小的粒子
    
    % 保留权重大于阈值的粒子
    keep_mask = weights > threshold;
    
    pruned_particles = particles(:, keep_mask);
    pruned_weights = weights(keep_mask);
    
    % 重新归一化
    if sum(pruned_weights) > 0
        pruned_weights = pruned_weights / sum(pruned_weights);
    end
end

2.4 新生目标生成:generate_birth_particles.m

matlab 复制代码
function [birth_particles, birth_weights] = generate_birth_particles(params, N_birth)
%% 生成新生目标粒子
    
    birth_type = params.birth_model.type;
    
    switch lower(birth_type)
        case 'gaussian'
            % 高斯混合新生模型
            n_components = size(params.birth_model.mean, 2);
            particles_per_component = ceil(N_birth / n_components);
            
            birth_particles = [];
            
            for c = 1:n_components
                mean_c = params.birth_model.mean(:, c);
                cov_c = params.birth_model.cov(:,:,c);
                
                % 从高斯分布采样
                particles_c = mvnrnd(mean_c', cov_c, particles_per_component)';
                birth_particles = [birth_particles, particles_c];
            end
            
            % 截断到指定数量
            if size(birth_particles, 2) > N_birth
                birth_particles = birth_particles(:, 1:N_birth);
            end
            
        case 'uniform'
            % 均匀分布新生模型
            birth_particles = zeros(4, N_birth);
            birth_particles(1, :) = params.area(1) + (params.area(2)-params.area(1)) * rand(1, N_birth);
            birth_particles(3, :) = params.area(3) + (params.area(4)-params.area(3)) * rand(1, N_birth);
            birth_particles(2, :) = -2 + 4 * rand(1, N_birth);
            birth_particles(4, :) = -2 + 4 * rand(1, N_birth);
            
        otherwise
            error('未知的新生目标类型');
    end
    
    % 分配权重
    birth_weights = ones(1, size(birth_particles, 2)) * (params.birth_intensity / size(birth_particles, 2));
end

3. 性能评估函数

3.1 评估性能:evaluate_performance.m

matlab 复制代码
function evaluate_performance(true_trajectories, estimated_targets, params)
%% 评估SMC-PHD滤波器性能
    
    T = params.T;
    n_targets = length(true_trajectories);
    
    % 计算OSPA距离
    ospa_distances = zeros(1, T);
    ospa_localization = zeros(1, T);
    ospa_cardinality = zeros(1, T);
    
    c = 20;  % 截断距离
    p = 1;   % 阶数
    
    for t = 1:T
        % 真实目标位置
        true_positions = zeros(2, n_targets);
        for i = 1:n_targets
            true_positions(:, i) = params.H * true_trajectories{i}(:, t);
        end
        
        % 估计目标位置
        est_positions = estimated_targets{t};
        
        % 计算OSPA
        [ospa_distances(t), ospa_localization(t), ospa_cardinality(t)] = ...
            compute_ospa(true_positions, est_positions, c, p);
    end
    
    % 计算平均性能
    avg_ospa = mean(ospa_distances);
    avg_localization = mean(ospa_localization);
    avg_cardinality = mean(ospa_cardinality);
    
    % 计算目标数量估计误差
    true_numbers = ones(1, T) * n_targets;
    est_numbers = cellfun(@(x) size(x,2), estimated_targets);
    cardinality_rmse = sqrt(mean((est_numbers - true_numbers).^2));
    
    % 显示结果
    fprintf('\n=== 性能评估结果 ===\n');
    fprintf('平均OSPA距离: %.3f\n', avg_ospa);
    fprintf('平均定位误差: %.3f\n', avg_localization);
    fprintf('平均基数误差: %.3f\n', avg_cardinality);
    fprintf('目标数量RMSE: %.3f\n', cardinality_rmse);
    fprintf('===================\n');
    
    % 绘制性能曲线
    figure('Position', [100, 100, 1200, 400]);
    
    subplot(1, 3, 1);
    plot(1:T, ospa_distances, 'b-', 'LineWidth', 1.5);
    xlabel('时间步');
    ylabel('OSPA距离');
    title('OSPA距离随时间变化');
    grid on;
    
    subplot(1, 3, 2);
    hold on;
    plot(1:T, true_numbers, 'k-', 'LineWidth', 2, 'DisplayName', '真实数量');
    plot(1:T, est_numbers, 'r--', 'LineWidth', 1.5, 'DisplayName', '估计数量');
    xlabel('时间步');
    ylabel('目标数量');
    title('目标数量估计');
    legend('Location', 'best');
    grid on;
    
    subplot(1, 3, 3);
    hold on;
    plot(1:T, ospa_localization, 'g-', 'LineWidth', 1.5, 'DisplayName', '定位误差');
    plot(1:T, ospa_cardinality, 'm-', 'LineWidth', 1.5, 'DisplayName', '基数误差');
    xlabel('时间步');
    ylabel('误差');
    title('误差分解');
    legend('Location', 'best');
    grid on;
end

3.2 计算OSPA距离:compute_ospa.m

matlab 复制代码
function [ospa, localization_error, cardinality_error] = compute_ospa(...
    X, Y, c, p)
%% 计算OSPA距离
    
    m = size(X, 2);
    n = size(Y, 2);
    
    if m == 0 && n == 0
        ospa = 0;
        localization_error = 0;
        cardinality_error = 0;
        return;
    elseif m == 0 || n == 0
        ospa = c;
        localization_error = 0;
        cardinality_error = c;
        return;
    end
    
    % 计算距离矩阵
    d = zeros(m, n);
    for i = 1:m
        for j = 1:n
            dist = norm(X(:, i) - Y(:, j));
            d(i, j) = min(dist, c);
        end
    end
    
    % 使用匈牙利算法求解最优分配
    if m <= n
        assignment = munkres(d);
        assigned = assignment > 0;
        
        % 计算定位误差
        loc_error = 0;
        for i = 1:m
            if assigned(i)
                loc_error = loc_error + d(i, assignment(i))^p;
            end
        end
        localization_error = (loc_error / n)^(1/p);
        
        % 计算基数误差
        cardinality_error = c^p * (n - m) / n;
        cardinality_error = cardinality_error^(1/p);
        
    else
        % 转置后求解
        assignment = munkres(d');
        assigned = assignment > 0;
        
        loc_error = 0;
        for j = 1:n
            if assigned(j)
                loc_error = loc_error + d(assignment(j), j)^p;
            end
        end
        localization_error = (loc_error / m)^(1/p);
        
        cardinality_error = c^p * (m - n) / m;
        cardinality_error = cardinality_error^(1/p);
    end
    
    % 总OSPA
    ospa = (localization_error^p + cardinality_error^p)^(1/p);
end

4. 可视化函数

4.1 可视化结果:visualize_results.m

matlab 复制代码
function visualize_results(true_trajectories, measurements, estimated_targets, ...
    particles, weights, params, performance_metrics)
%% 可视化SMC-PHD滤波器结果
    
    T = params.T;
    n_targets = length(true_trajectories);
    
    % 创建图形窗口
    figure('Position', [50, 50, 1400, 900]);
    
    % 1. 真实轨迹和估计轨迹
    subplot(2, 3, 1);
    hold on;
    
    % 绘制真实轨迹
    colors = {'r', 'g', 'b', 'm', 'c'};
    for i = 1:min(n_targets, length(colors))
        trajectory = true_trajectories{i};
        plot(trajectory(1, :), trajectory(3, :), ...
            [colors{i} '-'], 'LineWidth', 2, 'DisplayName', sprintf('目标 %d', i));
    end
    
    % 绘制估计轨迹
    est_trajectory_x = zeros(T, 0);
    est_trajectory_y = zeros(T, 0);
    
    for t = 1:T
        est_targets = estimated_targets{t};
        if ~isempty(est_targets)
            for i = 1:size(est_targets, 2)
                if t <= size(est_trajectory_x, 2)
                    est_trajectory_x(t, i) = est_targets(1, i);
                    est_trajectory_y(t, i) = est_targets(2, i);
                else
                    est_trajectory_x(t, i) = est_targets(1, i);
                    est_trajectory_y(t, i) = est_targets(2, i);
                end
            end
        end
    end
    
    for i = 1:size(est_trajectory_x, 2)
        plot(est_trajectory_x(:, i), est_trajectory_y(:, i), ...
            'k--', 'LineWidth', 1, 'DisplayName', sprintf('估计 %d', i));
    end
    
    xlabel('X 位置');
    ylabel('Y 位置');
    title('目标轨迹');
    legend('Location', 'best');
    grid on;
    axis equal;
    xlim(params.area(1:2));
    ylim(params.area(3:4));
    
    % 2. 粒子分布
    subplot(2, 3, 2);
    hold on;
    
    % 绘制粒子
    scatter(particles(1, :), particles(3, :), 5, weights, 'filled');
    
    % 绘制估计目标
    last_estimates = estimated_targets{end};
    if ~isempty(last_estimates)
        scatter(last_estimates(1, :), last_estimates(2, :), ...
            100, 'r', 'x', 'LineWidth', 2);
    end
    
    xlabel('X 位置');
    ylabel('Y 位置');
    title('粒子分布');
    colorbar;
    grid on;
    xlim(params.area(1:2));
    ylim(params.area(3:4));
    
    % 3. 观测数据
    subplot(2, 3, 3);
    hold on;
    
    for t = 1:T
        z_t = measurements{t};
        if ~isempty(z_t)
            scatter(z_t(1, :), z_t(2, :), 10, 'k', '.', 'MarkerAlpha', 0.3);
        end
    end
    
    xlabel('X 位置');
    ylabel('Y 位置');
    title('观测数据(含杂波)');
    grid on;
    xlim(params.area(1:2));
    ylim(params.area(3:4));
    
    % 4. 目标数量估计
    subplot(2, 3, 4);
    hold on;
    
    true_n = ones(1, T) * n_targets;
    est_n = [performance_metrics.n_est];
    
    plot(1:T, true_n, 'k-', 'LineWidth', 2, 'DisplayName', '真实数量');
    plot(1:T, est_n, 'r--', 'LineWidth', 1.5, 'DisplayName', '估计数量');
    
    xlabel('时间步');
    ylabel('目标数量');
    title('目标数量估计');
    legend('Location', 'best');
    grid on;
    
    % 5. 粒子数量变化
    subplot(2, 3, 5);
    
    particle_counts = [performance_metrics.particles];
    plot(1:T, particle_counts, 'b-', 'LineWidth', 1.5);
    
    xlabel('时间步');
    ylabel('粒子数量');
    title('粒子数量变化');
    grid on;
    
    % 6. 权重分布直方图
    subplot(2, 3, 6);
    
    histogram(weights, 50, 'Normalization', 'probability');
    xlabel('粒子权重');
    ylabel('频率');
    title('权重分布');
    grid on;
    
    % 添加总体标题
    sgtitle('SMC-PHD 多目标跟踪结果', 'FontSize', 16, 'FontWeight', 'bold');
end

4.2 实时动画:animate_tracking.m

matlab 复制代码
function animate_tracking(true_trajectories, measurements, estimated_targets, params)
%% 生成跟踪动画
    
    T = params.T;
    n_targets = length(true_trajectories);
    
    % 创建图形窗口
    figure('Position', [100, 100, 800, 600]);
    
    for t = 1:T
        clf;
        hold on;
        
        % 绘制监控区域
        rectangle('Position', [params.area(1), params.area(3), ...
                  params.area(2)-params.area(1), params.area(4)-params.area(3)], ...
                  'EdgeColor', 'k', 'LineWidth', 1);
        
        % 绘制真实目标
        for i = 1:n_targets
            if t <= size(true_trajectories{i}, 2)
                pos = true_trajectories{i}([1,3], t);
                plot(pos(1), pos(2), 'ro', 'MarkerSize', 10, 'LineWidth', 2);
                
                % 绘制轨迹
                traj_len = min(20, t);
                start_idx = max(1, t-traj_len+1);
                trajectory = true_trajectories{i}([1,3], start_idx:t);
                plot(trajectory(1, :), trajectory(2, :), 'r-', 'LineWidth', 1);
            end
        end
        
        % 绘制观测
        z_t = measurements{t};
        if ~isempty(z_t)
            scatter(z_t(1, :), z_t(2, :), 30, 'k', 'x', 'LineWidth', 1.5);
        end
        
        % 绘制估计目标
        est_targets = estimated_targets{t};
        if ~isempty(est_targets)
            scatter(est_targets(1, :), est_targets(2, :), 50, 'b', 's', 'filled');
        end
        
        % 设置图形属性
        xlabel('X 位置');
        ylabel('Y 位置');
        title(sprintf('时间步: %d/%d', t, T));
        grid on;
        axis equal;
        xlim(params.area(1:2));
        ylim(params.area(3:4));
        
        % 添加图例
        legend('真实目标', '观测', '估计目标', 'Location', 'best');
        
        % 暂停以显示动画
        pause(0.1);
        
        % 保存帧(可选)
        if nargout > 0
            frame(t) = getframe(gcf);
        end
    end
    
    % 返回帧(可选)
    if nargout > 0
        varargout{1} = frame;
    end
end

5. 匈牙利算法实现(用于OSPA计算)

matlab 复制代码
function [assignment, cost] = munkres(costMatrix)
%% 匈牙利算法实现
    
    % 确保是方阵
    [n, m] = size(costMatrix);
    if n > m
        costMatrix = [costMatrix; Inf(n, n-m)];
    elseif m > n
        costMatrix = [costMatrix, Inf(m-n, m)];
    end
    
    n = max(n, m);
    costMatrix = costMatrix(1:n, 1:n);
    
    % 步骤1:行归约
    for i = 1:n
        min_val = min(costMatrix(i, :));
        costMatrix(i, :) = costMatrix(i, :) - min_val;
    end
    
    % 步骤2:列归约
    for j = 1:n
        min_val = min(costMatrix(:, j));
        costMatrix(:, j) = costMatrix(:, j) - min_val;
    end
    
    % 初始化
    assignment = zeros(1, n);
    col_covered = zeros(1, n);
    row_covered = zeros(1, n);
    
    % 查找独立零
    for i = 1:n
        for j = 1:n
            if costMatrix(i, j) == 0 && ~row_covered(i) && ~col_covered(j)
                assignment(i) = j;
                row_covered(i) = 1;
                col_covered(j) = 1;
                break;
            end
        end
    end
    
    % 重置覆盖
    row_covered(:) = 0;
    col_covered(:) = 0;
    
    % 查找覆盖所有零的最小行数
    marked_rows = find(assignment == 0);
    
    if isempty(marked_rows)
        % 已找到完整分配
        assignment = assignment(1:n);
        cost = sum(costMatrix(sub2ind(size(costMatrix), 1:n, assignment)));
        return;
    end
    
    % 标记行
    row_covered(marked_rows) = 1;
    
    % 简化版本:贪心分配
    [~, assignment] = min(costMatrix, [], 2);
    assignment = assignment';
    
    % 计算成本
    valid_assign = assignment > 0 & assignment <= n;
    cost = sum(costMatrix(sub2ind(size(costMatrix), ...
        find(valid_assign), assignment(valid_assign))));
end

参考代码 序贯蒙特卡洛算法 www.youwenfan.com/contentcsv/113008.html

6. 使用说明

6.1 快速开始

matlab 复制代码
% 1. 运行主程序
main_SMC_PHD;

% 2. 或者分步运行
% 加载参数
params = struct();
params.T = 50;
params.N_particles = 3000;
% ... 设置其他参数

% 生成数据
[true_trajectories, measurements] = generate_simulation_data(params);

% 初始化滤波器
[particles, weights] = initialize_filter(params);

% 运行滤波
estimated_targets = cell(params.T, 1);
for k = 1:params.T
    [particles, weights] = phd_prediction(particles, weights, params, k);
    [weights, ~] = phd_update(particles, weights, measurements{k}, params);
    [estimated_targets{k}, ~] = extract_target_states(particles, weights, params);
end

% 可视化
visualize_results(true_trajectories, measurements, estimated_targets, ...
    particles, weights, params, []);

6.2 参数调整指南

matlab 复制代码
% 关键参数及其影响
params = struct();

% 粒子数量:增加可提高精度但降低速度
params.N_particles = 5000;  % 推荐:1000-10000

% 存活概率:控制目标持续存在的可能性
params.p_survival = 0.99;   % 推荐:0.95-0.99

% 检测概率:传感器检测目标的概率
params.p_detection = 0.95;  % 推荐:0.8-0.99

% 新生目标强度:控制新目标出现的频率
params.birth_intensity = 0.1;  % 推荐:0.05-0.3

% 杂波率:每个时间步的杂波数量
params.clutter_rate = 5;     % 推荐:1-20

% 重采样阈值:控制重采样频率
params.resample_threshold = 0.5;  % 推荐:0.3-0.7

7. 扩展功能

7.1 多种运动模型支持

matlab 复制代码
function F = get_motion_model(model_type, dt)
%% 获取运动模型
    
    switch lower(model_type)
        case 'cv'  % 匀速模型
            F = [1 dt 0 0;
                 0 1 0 0;
                 0 0 1 dt;
                 0 0 0 1];
                 
        case 'ca'  % 匀加速模型
            F = [1 dt 0.5*dt^2 0 0 0;
                 0 1 dt 0 0 0;
                 0 0 1 0 0 0;
                 0 0 0 1 dt 0.5*dt^2;
                 0 0 0 0 1 dt;
                 0 0 0 0 0 1];
                 
        case 'ctrv'  % 恒定转率和速度
            F = @(omega) [1 sin(omega*dt)/omega 0 -(1-cos(omega*dt))/omega;
                          0 cos(omega*dt) 0 -sin(omega*dt);
                          0 (1-cos(omega*dt))/omega 1 sin(omega*dt)/omega;
                          0 sin(omega*dt) 0 cos(omega*dt)];
                          
        otherwise
            error('未知的运动模型');
    end
end

7.2 非线性观测模型

matlab 复制代码
function likelihood = nonlinear_likelihood(particle, measurement, params)
%% 非线性观测似然
    
    % 从粒子状态计算预测观测
    x = particle(1);
    y = particle(3);
    
    % 距离和方位
    range = sqrt(x^2 + y^2);
    bearing = atan2(y, x);
    
    % 预测观测
    z_pred = [range; bearing];
    
    % 计算似然
    innovation = measurement - z_pred;
    
    % 处理方位角环绕
    if innovation(2) > pi
        innovation(2) = innovation(2) - 2*pi;
    elseif innovation(2) < -pi
        innovation(2) = innovation(2) + 2*pi;
    end
    
    % 高斯似然
    likelihood = mvnpdf(innovation', [0, 0], params.R);
end

8. 故障排除

常见问题及解决方案:

  1. 粒子退化

    matlab 复制代码
    % 降低重采样阈值
    params.resample_threshold = 0.3;
    % 增加粒子数量
    params.N_particles = 10000;
  2. 目标数量估计不准确

    matlab 复制代码
    % 调整新生目标强度
    params.birth_intensity = 0.2;
    % 调整存活概率
    params.p_survival = 0.98;
  3. 计算速度慢

    matlab 复制代码
    % 减少粒子数量
    params.N_particles = 2000;
    % 使用更简单的运动模型
    params.motion_model = 'CV';
相关推荐
我命由我123451 小时前
Java 开发 - Jar 包与 War 包
java·开发语言·java-ee·intellij-idea·jar·idea·intellij idea
峰上踏雪1 小时前
Windows 下最推荐的 Qt + VS2026 + CMake 开发方案
开发语言·windows·qt
楼田莉子1 小时前
C++20新特性:协程
开发语言·c++·后端·学习·c++20
xiaoshuaishuai81 小时前
C# AvaloniaUI 中旋转
开发语言·c#
Dream_ksw1 小时前
Python 基础
开发语言·python
weixin_428005301 小时前
C#调用 AI学习从0开始-第2阶段(Function Calling+工具调用智能体)-第9天实战-实现计算器工具
开发语言·学习·c#·functioncalling·ai实现计算器工具
特种加菲猫2 小时前
C++11核心特性深度解析:从列表初始化到lambda与包装器
开发语言·c++
JSMSEMI112 小时前
JSM12N60C 600V N沟道增强型功率MOSFET
开发语言·javascript·ecmascript
设计师小聂!2 小时前
Java异常处理
java·开发语言·后端·编辑器·idea