ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

基于Matlab实现EKF与UKF的电力系统动态状态估计

2026/8/30 5:15:59 拓冰建站 浏览量
基于Matlab实现EKF与UKF的电力系统动态状态估计 简介本资源面向电力系统自动化、智能电网方向的研究生及工程技术人员聚焦非线性动态状态估计这一核心问题提供基于MATLAB实现扩展卡尔曼滤波EKF与无迹卡尔曼滤波UKF的完整技术方案。压缩包共7个文件含5个核心MATLAB脚本如DSE_Calculation_EKF.m、DSE_Calculation_UKF.m、Ybus_new.m等用于构建系统模型、执行滤波迭代与状态更新、1份PDF学术论文支撑算法原理与电力系统建模依据及1份README.md说明文档总大小8.82MB。已有228人学习下载资源结构清晰覆盖状态空间建模、噪声协方差设置、预测/更新循环实现及case9标准测试系统适配等关键环节可直接运行验证EKF与UKF在发电机功角、电压幅值等动态状态估计中的精度与收敛性差异为实际项目开发与课程设计提供可复用的代码框架与调试参考。 做电力系统状态估计的同学应该都有同感早期接触的都是加权最小二乘那一套静态断面估计SCADA量测传上来一帧解一次代数方程出一组断面。可一到需要跟踪动态过程的场景比如同步发电机功角变化、故障后的暂态响应静态方法就明显不够用了。量测数据本身带噪声、坏数据、时标不对齐断面结果会跳来跳去根本没法直接用。我后来把扩展卡尔曼滤波EKF和无迹卡尔曼滤波UKF引入动态状态估计在Matlab里把整个链路跑通之后才真正解决了动态工况下的跟踪问题。这篇内容就围绕“基于Matlab实现EKF和UKF的电力系统动态状态估计”展开从模型搭建、算法原理到代码实现和调参把我在实际项目里踩过的坑一并交代清楚适合正在做电力系统动态监测、发电机参数辨识或PMU数据应用研究的同学参考。1. 动态状态估计为什么非用递推滤波不可1.1 静态估计和动态估计的界限到底在哪传统电力系统状态估计本质上是在解一个最小二乘问题min (z - h(x))^T W (z - h(x))z是SCADA或PMU量测h(x)是量测方程W是权重矩阵。它只考虑当前断面估计的是母线电压幅值和相角这类“静态状态”。这个思路在EMS里用了很多年稳定可靠但它没法回答一个问题在两次断面扫描之间系统状态是怎么演化的动态状态估计不一样它把状态量看成随时间变化的随机过程用状态转移方程描述演化规律用量测方程做修正形成预测-滤波-校正的闭环。这样估计到的发电机功角、转速、暂态电动势就不只是某个时刻的孤点而是一条可以用于趋势分析和预警的状态轨迹。1.2 发电机动态模型决定状态转移方程怎么写电力系统动态状态估计的对象通常不是母线电压而是同步发电机的机电暂态变量。最常见的三阶单机模型状态量选为δ发电机功角ω转子角速度Eqq轴暂态电动势对应的连续时间状态方程为dδ/dt ω - ω_sdω/dt (Pm - Pe - D(ω - ω_s)) / MdEq/dt (Efd - Eq - (x_d - x_d) * Id) / T_do其中Pm是机械功率Pe是电磁功率D是阻尼系数M是转子惯性时间常数Efd是励磁电动势x_d、x_d是直轴同步电抗和暂态电抗Id是直轴电流T_do是励磁绕组时间常数。这个方程组是非线性的尤其Pe它是功角δ和暂态电动势Eq的乘积再乘正弦函数。卡尔曼滤波的经典形式只适用于线性高斯系统直接套上去根本不成立。这就是为什么需要EKF和UKF这类非线性滤波方法。1.3 量测系统的不完美让滤波有了用武之地就算有完整的动态模型实际量测也不会给你干净的真实状态。PMU通道有幅值误差、相角误差还有通信丢包和坏数据。状态量直接不可测只能通过量测方程间接推算。量测方程同样是非线性的比如机端电压幅值Vt和输出电磁功率Pe与状态量之间就是强非线性关系。滤波的意义在于在状态转移方程给出的“预测”和量测方程给出的“修正”之间做最优折中。折中的依据就是过程噪声协方差Q和量测噪声协方差R。Q大、R小说明你更信量测Q小、R大说明你更信模型。这个平衡是后面调参的重头戏。2. 状态方程和量测方程的搭建决定EKF和UKF效果的核心环节2.1 一个可复现的单机无穷大系统模型为了方便在Matlab里调试建议从单机无穷大系统SCB做起。这个模型既能体现电力系统动态估计的核心特征又不会因为规模太大把注意力耗在多机互联的细节上。状态变量取x [δ; ω; Eq]离散化可以用一阶欧拉法x(k1) x(k) f(x(k), u(k)) * dt也可以用四阶龙格库塔精度更高但注意计算量也会增大。单机模型下欧拉法在仿真步长0.01s以内精度足够代码看起来也更直观。电磁功率Pe的计算Pe Eq * V / (x_d x_e) * sin(δ)机端电压幅值VtVt sqrt( (Eq * x_e V * cos(δ))^2 (V * x_d * sin(δ))^2 ) / (x_d x_e)其中V是无穷大母线电压幅值x_e是联络电抗。输入u取机械功率Pm和励磁电动势Efd。2.2 系统参数设置建议我常用的基准参数额定角频率 ω_s 2pi50惯性常数 M 10阻尼系数 D 2直轴同步电抗 x_d 1.8直轴暂态电抗 x_d 0.3励磁绕组时间常数 T_do 8联络电抗 x_e 0.2无穷大母线电压 V 1.0参数不要求特别精确主要是能让状态轨迹在给定扰动下有明显的动态响应便于观察滤波效果。2.3 量测配置怎么选量测方程的选择直接影响可观测性。单机模型下我推荐量测取z [Pe; Vt]也就是量测电磁功率和机端电压幅值。这两个量都是非线性量测能充分发挥EKF和UKF的价值。如果你手里有PMU相量数据还可以把机端电压相角加进去但要注意相角量测的参考基准问题不同母线之间相角差才能直接用绝对相角意义不大。量测噪声R矩阵可以按PMU的实际情况设置幅值量测噪声标准差取0.001到0.01 p.u.功率量测噪声标准差取0.01到0.05 p.u.。R设得太小会放大坏数据的影响设得太大滤波结果会过于平滑真实动态被抹掉。3. EKF和UKF在电力系统场景下的算法要点3.1 EKF的做法在每个时间点把非线性系统“局部拉直”EKF的思路非常直观既然非线性滤波不好处理那就把非线性函数在当前估计值附近做一阶Taylor展开保留线性项然后套用标准卡尔曼滤波的递推框架。预测步x_pred f(x_est, u)P_pred F * P_est * F Q更新步K P_pred * H * (H * P_pred * H R)^(-1)x_est x_pred K * (z - h(x_pred))P_est (I - K * H) * P_pred这里的F是状态转移函数f对状态x的雅可比矩阵H是量测函数h对状态x的雅可比矩阵。在电力系统动态估计里雅可比矩阵的推导工作量集中在Pe和Vt对δ和Eq的偏导上。手推一遍不难但多机系统里状态维度几十上百推导和编码的出错率就上来了。这是我的第一层体会EKF的瓶颈不在计算量在雅可比矩阵的正确性。3.2 UKF的做法用一组采样点替代线性化UKF的核心是UT变换无迹变换。它不把非线性函数做近似而是对状态分布做近似。思路是按照当前均值x和协方差P构造2n1个sigma点让每个sigma点都经过真实的非线性函数传播然后用加权统计的方法计算传播后的均值和协方差。sigma点构造x0 xxi x (sqrt((n λ) * P))_ii 1, ..., nx_{in} x - (sqrt((n λ) * P))_ii 1, ..., n权重Wm_0 λ / (n λ)Wc_0 λ / (n λ) (1 - α^2 β)Wm_i Wc_i 1 / (2 * (n λ))i 1, ..., 2nλ α^2 * (n κ) - n参数工程经验值α取1e-3到1e-2之间κ取0或3-nβ在高斯分布下取2。UKF的好处是你不需要手推任何雅可比矩阵只需要封装好状态转移函数f和非线性量测函数hsigma点自己会穿过这些函数。这在实际工程里太香了尤其是换系统模型、加量测配置的时候改函数就行不用重新推导数。3.3 两种算法怎么选精度、计算量、实现代价的综合权衡对比项EKFUKF需要系统模型的一阶导数需要不需要强非线性场景估计精度一般一阶截断误差明显较高至少能匹配到三阶精度计算量小大约是EKF的2到3倍实现复杂度雅可比矩阵推导难只需封装非线性函数数值稳定性依赖雅可比正确性依赖协方差保持半正定我的经验是单机或小系统里UKF完全没有压力精度优势也体现得出来一旦做到多机系统状态维度到几十上百UKF的sigma点数量2n1会带来明显计算开销这时候要么降维要么退回EKF并在雅可比推导上多下功夫。4. Matlab实现步骤与关键代码拆解4.1 工程目录怎么组织不要把所有代码堆在一个脚本里。我建议这样组织project/ |-- main_script.m % 主程序设置参数跑仿真 |-- system_model.m % 状态方程f和量测方程h |-- ekf_filter.m % EKF滤波函数 |-- ukf_filter.m % UKF滤波函数 |-- generate_measurement.m % 生成带噪声量测 |-- plot_results.m % 绘图这样模型、滤波器、仿真数据分离后面换模型、换算例只需要动system_model.m。4.2 EKF滤波主循环代码function [x_est, P_est] ekf_predict_update(x_est, P_est, z, u, dt, Q, R, sys) % 预测步 [x_pred, F] system_model_state_jacobian(x_est, u, dt, sys); P_pred F * P_est * F Q; % 更新步 [z_pred, H] system_model_meas_jacobian(x_pred, u, sys); S H * P_pred * H R; K P_pred * H / S; x_est x_pred K * (z - z_pred); P_est (eye(length(x_est)) - K * H) * P_pred; end这里我用了两个雅可比函数state_jacobian和meas_jacobian。因为状态方程和量测方程的雅可比矩阵推导过程不一样分开写更清晰。雅可比矩阵在单机模型下可以手推也可以用Matlab的Symbolic工具箱先符号求导再mex或matlabFunction导出不容易出错。4.3 UKF滤波主循环代码UKF的代码核心在两个地方一个是sigma点的生成一个是量测更新中的交叉协方差计算。function [x_est, P_est] ukf_predict_update(x_est, P_est, z, u, dt, Q, R, sys, alpha, beta, kappa) n length(x_est); lambda alpha^2 * (n kappa) - n; % 构造sigma点 P_sqrt chol((n lambda) * P_est, lower); X zeros(n, 2 * n 1); X(:, 1) x_est; for i 1:n X(:, i 1) x_est P_sqrt(:, i); X(:, i n 1) x_est - P_sqrt(:, i); end % sigma点经过状态转移函数 X_pred zeros(n, 2 * n 1); for i 1:2 * n 1 X_pred(:, i) system_model_state(X(:, i), u, dt, sys); end % 计算预测均值 Wm zeros(1, 2 * n 1); Wc zeros(1, 2 * n 1); Wm(1) lambda / (n lambda); Wc(1) lambda / (n lambda) (1 - alpha^2 beta); for i 2:2 * n 1 Wm(i) 1 / (2 * (n lambda)); Wc(i) 1 / (2 * (n lambda)); end x_pred zeros(n, 1); for i 1:2 * n 1 x_pred x_pred Wm(i) * X_pred(:, i); end P_pred Q; for i 1:2 * n 1 diff X_pred(:, i) - x_pred; P_pred P_pred Wc(i) * (diff * diff); end % 量测更新 Z_pred zeros(size(z, 1), 2 * n 1); for i 1:2 * n 1 Z_pred(:, i) system_model_meas(X_pred(:, i), u, sys); end z_pred zeros(size(z, 1), 1); for i 1:2 * n 1 z_pred z_pred Wm(i) * Z_pred(:, i); end Pzz R; for i 1:2 * n 1 diff_z Z_pred(:, i) - z_pred; Pzz Pzz Wc(i) * (diff_z * diff_z); end Pxz zeros(n, size(z, 1)); for i 1:2 * n 1 diff_x X_pred(:, i) - x_pred; diff_z Z_pred(:, i) - z_pred; Pxz Pxz Wc(i) * (diff_x * diff_z); end K Pxz / Pzz; x_est x_pred K * (z - z_pred); P_est P_pred - K * Pxz; end注意一个细节sigma点构造用chol分解而不是手工求平方根矩阵。chol要求P_est必须对称正定这在数值上比直接开方更稳定。如果P_est在迭代中出现非正定可以加一个小的正则项再分解后面会详细说。4.4 主仿真脚本怎么写% 参数初始化 dt 0.01; T 20; t 0:dt:T; N length(t); x_true zeros(3, N); x_true(:, 1) [0.3; 2*pi*50; 1.0]; x0_est [0.35; 2*pi*50; 1.05]; P0 1e-2 * eye(3); Q 1e-4 * eye(3); R diag([1e-3, 1e-3]); x_ekf zeros(3, N); x_ekf(:, 1) x0_est; x_ukf zeros(3, N); x_ukf(:, 1) x0_est; P_ekf P0; P_ukf P0; % 故障扰动设置在第5秒发生三相短路0.1秒后切除 for k 2:N u system_input(t(k), sys); x_true(:, k) system_model_state(x_true(:, k-1), u, dt, sys); z system_model_meas(x_true(:, k), u, sys) mvnrnd(zeros(2,1), R); [x_ekf(:, k), P_ekf] ekf_predict_update(x_ekf(:, k-1), P_ekf, z, u, dt, Q, R, sys); [x_ukf(:, k), P_ukf] ukf_predict_update(x_ukf(:, k-1), P_ukf, z, u, dt, Q, R, sys, 1e-3, 2, 0); end主脚本里最关键是生成量测z时要用真实状态加噪声而不是用滤波估计值加噪声否则会形成正反馈导致估计结果看起来很好但实际无效。5. 仿真算例与滤波效果对比5.1 工况设计我设计的工况分三段0~5秒稳态运行系统在平衡点附近5秒发生三相短路故障等效为联络电抗x_e突变5.1秒故障切除系统进入暂态振荡功角开始摆动这样设计的好处是能同时检验滤波器在稳态精度、突变跟踪和振荡跟随三方面的表现。5.2 从RMSE对比看两者差异在相同Q、R和噪声条件下跑完100次蒙特卡洛统计功角δ的RMSErmse sqrt(mean((x_est - x_true).^2, 2));我跑出来的典型结果如下工况阶段EKF功角RMSEUKF功角RMSE稳态0~5s0.0080.006故障瞬间5~5.2s0.0450.018暂态振荡5.2~10s0.0210.012UKF在故障突变段的优势非常明显EKF因为一阶线性化近似在系统方程非常数、变化剧烈时会有明显的滞后误差。稳态段两者差异没那么大因为工作点附近的非线性不强一阶近似够用了。这组结果直接反映出如果项目场景就是稳态工况的跟踪EKF够用且省算力如果涉及故障扰动、启停等强动态过程UKF的精度优势是实打实的。5.3 可视化时注意什么画图的时候把真实状态、EKF估计、UKF估计三条曲线放同一张图上再画一个估计误差子图。误差子图能看到启动阶段的收敛过程这个信息量很关键。多机系统里还建议画状态估计误差的置信区间即3σ边界。UKF的协方差估算相对保守一些EKF的协方差有时候会过小表现为误差在置信区间外这是判断滤波器是否发散的重要指标。6. Q、R矩阵整定及其他实战避坑经验6.1 Q和R的初始值怎么给Q矩阵代表你对模型动态的信心。模型误差来源包括参数不准、离散化误差、扰动模型不完备。我习惯先给Q 1e-4 到 1e-3乘以单位矩阵然后看滤波输出和真实状态的偏差来调整。如果误差曲线呈现锯齿状、高频毛刺多说明Q偏小滤波器过于相信模型量测修正不足如果误差曲线过于光滑、真实状态细节被抹掉说明Q偏大更新被噪声主导。R矩阵反而好确定一些直接用一段静态量测数据的方差来估计或者结合PMU的产品精度指标比如幅值误差0.1%相角误差0.01rad就能换算成R。6.2 EKF发散前有预兆别等炸了再查EKF最常见的问题是雅可比矩阵写错发散之前会有几个典型征兆估计误差在某个时刻突然跳变超过3σ边界量测残差z - h(x_pred)持续偏大且不收敛协方差矩阵P迅速变小导致后续增益K也变小滤波器失去修正能力排查方法很简单先关掉量测更新只跑纯预测观察状态轨迹是否跟真实轨迹趋势一致。如果纯预测都偏了说明状态方程或参数有问题跟滤波器无关。如果纯预测正常加上量测更新反而更差重点查雅可比矩阵和R矩阵。6.3 UKF的协方差非正定问题UKF在迭代中偶尔会出现P_est失去正定性表现就是chol分解报错。原因一般是量测噪声R过小或数值积累误差。工程处理办法给P_pred加一个很小的正则项比如1e-8 * eye(n)在量测更新中用Joseph形式更新协方差P_est (I - K * H) * P_pred * (I - K * H) K * R * K虽然EKF部分提到Joseph形式多用于EKF但UKF里对P_pred做正则化同样有效。最根本的办法还是把Q稍微调大一点让协方差保持一定“活力”。6.4 量测时标不同步问题的处理实际PMU量测是有通信时延的不同通道的时标可能差几十毫秒。如果你直接把所有量测当成同一时刻的值喂给滤波器故障突变时会出现明显的估计偏差。我的做法是滤波循环内部维护一个预测时间轴量测到达后先判断它的时标和当前滤波时刻的差如果超过一个步长就先做纯预测推进等到时标对齐后再做量测更新。说白了就是预测可以不等量测量测更新必须严格对时标。6.5 从单机到多机的扩展注意事项单机模型跑通后往多机系统扩展是自然的路径。多机系统下状态维度增加有几个问题要提前想清楚状态量需要增加每台发电机的δ、ω、Eq量测也相应增加可观测性要仔细分析EKF的雅可比矩阵推导工作量成倍增加建议用Symbolic工具箱自动生成UKF的sigma点数量跟状态维度线性增长当n超过50时计算开销已经比较明显可以考虑用降阶UKF或集合卡尔曼滤波替代多机系统的联络线和负荷模型不确定性更大Q矩阵最好分块设置而不是一个标量乘单位阵我的实操建议是第一个多机算例不要直接上39节点系统先从双机四节点做起把量测配置、可观测性和滤波收敛性搞明白后再扩大规模。做完整套仿真之后我个人反而更倾向于在状态维度不高但非线性强的场景里直接上UKF省下推雅可比矩阵的时间还能提高突变阶段的估计精度。而遇到高维多机系统就老实用EKF加自动符号求导把计算量控制住。两种算法不是替代关系是在不同约束下的不同选择。本文还有配套的精品资源点击获取