【电机滤波例程5】渐消因子自适应扩展卡尔曼滤波(EKF),MATLAB。PMSM负载突变下的状态估计。附下载链接

附下载链接,有中文注释,可联系我获取代码定制和讲解服务

文章目录

程序讲解

概述

在负载增广扩展卡尔曼滤波(EKF)中加入有界渐消因子,根据新息能量调整预测协方差,展示负载突变时的状态跟踪。单个.m文件,包含数据生成、模型、滤波、评价和全部局部函数。适合课程实验、算法学习和二次开发

算法原理

采用表贴式永磁同步电机模型,满足 Ld=Lq=p.L。通过已知αβ电压驱动机电状态预测,以αβ电流为量测修正电流、机械转速和电角度。 扩展卡尔曼滤波利用离散模型雅可比近似传播局部状态误差。 仿真采用非零初始转速和明确的初始估计误差,展示转速与电角度的估计收敛及变速跟踪过程。

实现流程

  1. 设置参数、固定随机种子,生成电压、真实电机状态和带噪电流。
  2. 初始化带误差的估计状态,核对解析雅可比。
  3. 逐步执行模型预测和当前案例的量测更新。
  4. 检查有限值与协方差正定性,统计指标并输出Figure。

运行结果

转速与位置估计图:对比真实与估计机械转速,并放大展示电角度局部曲线;机械转速以r/min显示,电角度以rad显示。

估计误差图:显示机械转速与环绕处理后的电角度误差,用于观察收敛过程和变速响应。

电流观测与估计图:分别展示α、β电流的真值、带噪观测和滤波估计,观察电流平滑与跟踪情况。

负载转矩估计图:对比负载转矩真值和估计值,并给出负载估计误差,展示负载阶跃跟踪。

渐消因子诊断图:显示有界渐消因子随时间的变化,观察新息能量增大时预测协方差的膨胀程度。

命令行输出:对比全时段与分区间的RMSE、误差均值和方差,列出真值与估计值统计、电流滤波效果及数值诊断。

完整统计量保存在MATLAB工作区的 result.statistics,原有指标保存在 result.metrics,可自行查看。

MATLAB源代码

部分代码如下:

matlab 复制代码
% PMSM渐消因子自适应EKF:独立MATLAB例程
% 2026-09-20/Ver1,作者:matlabfilter,V同号,可获取代码定制、讲解等
% 直接点击"运行"。只依赖基础 MATLAB;本文件末尾包含全部局部函数。
% 固定随机种子0,直接运行并绘图;主输出为工作区中的 result。
clear; clc; close all;
rng(0);

%% 集中参数:SI单位;wm为机械角速度,theta为电角度
p.Rs = 0.45; p.L = 3e-3; p.psi = 0.075;
p.pairs = 4; p.J = 2e-3; p.B = 5e-4;
p.dt = 1e-4; p.duration = 0.65; p.ratedSpeed = 150;
t = 0:p.dt:p.duration; count = numel(t);

%% 真值与观测生成(理想有编码器驱动台架,独立于待验证估计器)
% 台架的理想电流/速度闭环只用于生成物理一致的电压、电流数据。
% 估计器不使用台架的真实角度、转速、速度给定或未知负载。
% 本例验证无位置传感器"估计",并不声称实现无传感器闭环启动。
nx = 5;
plant = [0; 0; 80; 0.3];
truth = zeros(nx,count); voltage = zeros(2,count);
currentObs = zeros(2,count); loadTrue = zeros(1,count);
noiseStd = 0.04*ones(2,count); outlierMask = false(1,count);
speedReference = 80 + 25*(1+tanh((t-0.16)/0.035))/2 ...
                      - 15*(1+tanh((t-0.44)/0.035))/2;
loadTrue(:) = 0.35;
loadTrue(t>=0.25)=1.10; loadTrue(t>=0.43)=0.42;

truth(1:4,1) = plant;
if nx==5, truth(5,:) = loadTrue; end
currentObs(:,1) = plant(1:2) + noiseStd(:,1).*randn(2,1);
speedIntegral = 0;
for k = 2:count
    % 真实台架:有编码器FOC等效电压源;电压限幅为±60 V。
    wm = plant(3); angle = plant(4);
    rot = [cos(angle),sin(angle);-sin(angle),cos(angle)];
    idq = rot*plant(1:2);
    speedError = speedReference(k-1)-wm;
    speedIntegral = max(-8,min(8,speedIntegral+p.dt*speedError));
    iqRef = max(-10,min(10,0.28*speedError+3.0*speedIntegral+0.8));
    udq = [p.Rs*idq(1)-p.pairs*wm*p.L*idq(2); ...
           p.Rs*idq(2)+p.pairs*wm*(p.L*idq(1)+p.psi)] ...
           + 2.8*([0;iqRef]-idq);
    u = max(-60,min(60,rot'*udq));
    voltage(:,k-1) = u;
    % 真值采用4个RK4子步,未知负载只传给真实电机。
    for sub = 1:4
        h = p.dt/4;
        a = motorODE(plant,u,p,loadTrue(k-1));
        b = motorODE(plant+h*a/2,u,p,loadTrue(k-1));
        c = motorODE(plant+h*b/2,u,p,loadTrue(k-1));
        d = motorODE(plant+h*c,u,p,loadTrue(k-1));
        plant = plant+h*(a+2*b+2*c+d)/6;
    end
    plant(4) = wrapAngle(plant(4));
    truth(1:4,k) = plant;
    currentObs(:,k) = plant(1:2)+noiseStd(:,k).*randn(2,1);
end
voltage(:,end) = voltage(:,end-1);

available = true(1,count);

currentObs(:,~available) = NaN;

%% EKF初始化(故意设置初始误差,不从真值数组初始化)
x = [0.15;-0.12;87;0.42];
P = diag([0.3^2,0.3^2,12^2,0.18^2]);
Q = diag([2e-6,2e-6,2e-3,2e-8]);
if nx==5
    x = [x;0.20]; P = blkdiag(P,0.25^2); Q = blkdiag(Q,2e-5);
end
R = 0.04^2*eye(2); H = [eye(2),zeros(2,nx-2)];
estimate = zeros(nx,count); estimate(:,1) = x;
innovation = nan(2,count); nis = nan(1,count);
diagnostic = ones(2,count); rStdEstimate = 0.04*ones(2,count);
minEigenvalue = zeros(1,count); minEigenvalue(1) = min(eig(P));
symmetryError = zeros(1,count); sqrtError = zeros(1,count);
innovationEnergy = 2*0.04^2;
% 对离散预测函数作中心差分,核对链式解析雅可比。
xcheck = x; xcheck(4) = 0.6;
jacobianError = checkJacobian(xcheck,[1;24],p,0.35);
assert(jacobianError<1e-6,'离散模型雅可比检查失败');
assert(abs(wrapAngle((-pi+0.01)-(pi-0.01))-0.02)<1e-12);

%% 预测与量测更新:滤波器只使用电压、电流及已知参数
for k = 2:count
    % 仅第01套使用已知的恒定负载;增广版本从状态读取负载。
    [xp,F] = motorStep(x,voltage(:,k-1),p,0.35);
    Pp = F*P*F'+Q;
    if available(k)
        v = currentObs(:,k)-H*xp;
        innovation(:,k) = v;
        Reff = R;
        
        projected=H*Pp*H'; nominalEnergy=trace(projected+R);
        % 预热后以完整新息能量归一化,15%裕量抑制噪声引起的反复膨胀。
        if k<=200, innovationEnergy=nominalEnergy; end
        innovationEnergy=0.98*innovationEnergy+0.02*(v'*v);
        lambda=max(1,min(1.2,innovationEnergy/(1.15*max(nominalEnergy,eps))));

完整代码下载链接:
https://download.csdn.net/download/callmeup/93496996

如需帮助,或有滤波相关的MATLAB代码定制需求,可从个人主页左侧联系我

相关推荐
H.莓飛1 小时前
【数据结构】二叉树_OJ题
linux·开发语言·数据结构·算法
好想像大佬一样能够ak所有2 小时前
Leetcode35.搜索插入位置
数据结构·算法·leetcode
aqiu1111112 小时前
【C++算法打怪专栏】LeetCode 165. 比较版本号(双指针与字符串流法)
c++·算法·leetcode
黄金龙PLUS2 小时前
如何基于置换算法来设计对称加密算法
算法·网络安全·密码学·哈希算法·同态加密
不会就选b2 小时前
算法日常・每日刷题--<动态规划>14
算法
赛博守夜人2 小时前
跨境业务与出海合规之九:海外买量投放与营销虚假流量(Ad Fraud):跨国机房群控与归因欺诈识别算法
算法·安全
镜子AI5 小时前
教培机构AI推荐系统实战:概念漂移检测算法——为什么“去年有效的推荐今年可能失效“
人工智能·算法
垆边人似月.6 小时前
华为OD算法题:查找众数及中位数
数据结构·算法·leetcode
hetao17338376 小时前
2026-10-08 hetao1733837 的刷题记录
c++·算法