UKF
对于一个非线性系统:
其中,w是系统噪声值,是v测量噪声值。
UKF算法过程如下:
1)确定状态值初始值和后验状态误差协方差初始值;
2)计算采样点。
其中,L为状态向量的长度,本文中状态向量长度为3,权重值计算如下所示:
代码如下:
模型代码
load('R0.mat');
load('R1.mat');
load('C1.mat');
load('discharge.mat');%放电数据
load('OCV_SOC.mat');%OCV-SOC关系
系统矩阵
A=[1-1*Ts/R1/C1 0;0 1];%系统矩阵
B=[1*Ts/C1;-1*Ts/Qn];
C=[-1 0];
D=0;
初始值
Q=0.00000001*eye(2);
R=1;
P0=0.01*[0.01 0;0 1];%状态误差协方差初始值
赋值
tm=discharge(1,:)';
Cur=-discharge(2,:)';
Vot=discharge(3,:)';
RSOC=discharge(4,:)';
T=length(tm);
模型估计得到的电压值
Xekf=[0;0.8];%[U1,U2,SOC]初始值
L=length(Xekf);
Uoc(1)=p(1)*Xekf(2)^8+p(2)*Xekf(2)^7+p(3)*Xekf(2)^6+p(4)*Xekf(2)^5+p(5)*Xekf(2)^4+p(6)*Xekf(2)^3+p(7)*Xekf(2)^2+p(8)*Xekf(2)+p(9);%OCV
Vekf(1)=Uoc(1)+C*Xekf-Cur(1)*R0;%估计得到的端电压值
m=length(Vekf);
alpha=0.01;
ki=0;
beta=2;
lamba=alpha^2*(L+ki)-L;
迭代
for i=1:T-1
delta=c*chol(P0)';
Xekf_i=Xekf(:,i);
Y=Xekf_i(:,ones(1,numel(Xekf_i)));
X=[Xekf_i Y+delta Y-delta];
LL=length(X);
xx=zeros(2,1);
XX=zeros(2,LL);
for k=1:LL
XX(:,k)=A*X(:,k)+B*Cur(i);
xx=xx+Wm(k)*XX(:,k);
end
Xekf(:,i+1)=xx;
X1=XX-xx(:,ones(1,LL));
P_xx=X1*diag(Wc)*X1'+Q;
LL_y=length(XX);
yy=zeros(1,1);
YY=zeros(1,LL_y);
for k=1:LL_y
Uoc(i+1)=p(1)*XX(2,k)^8+p(2)*XX(2,k)^7+p(3)*XX(2,k)^6+p(4)*XX(2,k)^5+p(5)*XX(2,k)^4+p(6)*XX(2,k)^3+p(7)*XX(2,k)^2+p(8)*XX(2,k)+p(9);
YY(k)=Uoc(i+1)+C*XX(:,k)-Cur(i+1)*R0;
yy=yy+Wm(k)*YY(k);
end
Vekf(i+1)=yy;
Y1=YY-yy(:,ones(1,LL_y));
P_yy=Y1*diag(Wc)*Y1'+R;
P_xy=X1*diag(Wc)*Y1';
K(:,i)=P_xy*inv(P_yy);
Xekf(:,i+1)=Xekf(:,i+1)+K(:,i)*(Vot(i+1)-Vekf(i+1));
P0=P_xx-K(:,i)*P_xy';
end
画图
t=0:0.1:length(tm)/10-0.1;
figure(1);
plot(t,Vot,'-k',t,Vekf,'-r','lineWidth',2); grid on
legend('真实值','估计值-UKF');
ylabel('端电压','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
figure(2);
plot(t,RSOC,'-k',t,Xekf(2,:),'-r','lineWidth',2); grid on
legend('真实值','估计值-UKF');
ylabel('SOC','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
V_error=Vot-Vekf';
SOC_error=RSOC-Xekf(2,:)';
SOC_error_mean=mean(abs(SOC_error(5000:end)));
SOC_error_max=max(abs(SOC_error(5000:end)));
figure(3);
plot(t,V_error,'-k','lineWidth',2); grid on
legend('端电压误差');
ylabel('端电压误差','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
figure(4);
plot(t,SOC_error,'-k','lineWidth',2); grid on
legend('SOC误差');
ylabel('SOC误差','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
SOC_UKF=Xekf(2,:);
SOC_error_UKF=SOC_error;
save SOC_UKF.mat SOC_UKF
save SOC_error_UKF.mat SOC_error_UKF
save RSOC.mat RSOC
EKF
二阶RC等效电路模型的等效电路模型框图如下。
其中,Uoc表示理想电压源,与SOC存在非线性关系;R0表示欧姆内阻, R1 R2是极化电阻,C1 C2是极化电容,Ut表示电池的端电压。根据基尔霍夫定律,可以得到系统方程和观测方程如下。定义放电电流方向为正,充电电流为负。
代码如下
load('R0.mat');
load('R1.mat');
load('C1.mat');
load('discharge.mat');%放电数据
load('OCV_SOC.mat');%OCV-SOC关系
Qn=30.23*3600;%容量,单位:A*S
矩阵
A=[1-1*Ts/R1/C1 0;0 1];%系统矩阵
B=[1*Ts/C1;-1*Ts/Qn];
C=[-1 0];
D=0;
赋值
%% 赋值
tm=discharge(1,:)';%时间
Cur=-discharge(2,:)';%电流
Vot=discharge(3,:)';%测量得到的端电压
RSOC=discharge(4,:)';%SOC真实值-安时法计算得到
T=length(tm)-1;%时间
EKF算法
Xekf=[0;0.8];%[U1,U2,SOC]初始值
Uoc=zeros(1,T+1);%OCV
Vekf=zeros(1,T+1);%估计得到的端电压值
Uoc(1)=p(1)*Xekf(2)^8+p(2)*Xekf(2)^7+p(3)*Xekf(2)^6+p(4)*Xekf(2)^5+p(5)*Xekf(2)^4+p(6)*Xekf(2)^3+p(7)*Xekf(2)^2+p(8)*Xekf(2)+p(9);%OCV
Vekf(1)=Uoc(1)+C*Xekf-Cur(1)*R0;%估计得到的端电压值
K=zeros(2,T);%卡尔曼增益
H=zeros(T,2);%观测矩阵
for i=1:T
Xekf(:,i+1)=A*Xekf(:,i)+B*Cur(i+1);%先验状态值
Uoc(i+1)=p(1)*Xekf(2,i+1)^8+p(2)*Xekf(2,i+1)^7+p(3)*Xekf(2,i+1)^6+p(4)*Xekf(2,i+1)^5+p(5)*Xekf(2,i+1)^4+p(6)*Xekf(2,i+1)^3+p(7)*Xekf(2,i+1)^2+p(8)*Xekf(2,i+1)+p(9);
H(i,:)=[-1 p(1)*8*Xekf(2,i+1)^7+p(2)*7*Xekf(2,i+1)^6+p(3)*6*Xekf(2,i+1)^5+p(4)*5*Xekf(2,i+1)^4+p(5)*4*Xekf(2,i+1)^3+p(6)*3*Xekf(2,i+1)^2+p(7)*2*Xekf(2,i+1)+p(8)];
Vekf(i+1)=Uoc(i+1)+C*Xekf(:,i+1)-Cur(i+1)*R0;%估计得到的端电压值
P=A*P0*A'+Q;%先验状态误差协方差
K(:,i)=P*H(i,:)'/(H(i,:)*P*H(i,:)'+R);%卡尔曼增益
Xekf(:,i+1)=Xekf(:,i+1)+K(:,i)*(Vot(i+1)-Vekf(i+1));%后验状态值
P0=(eye(2)-K(:,i)*H(i,:))*P;%后验状态误差协方差
end
画图
t=0:0.1:length(tm)/10-0.1;
figure(1);
% plot(t,Vot,'-k',t,Vekf,'-r','lineWidth',2); grid on
plot(t,Vot,'-k',t,Vekf,'-r','lineWidth',2); grid on
legend('真实值','估计值-EKF');
ylabel('端电压','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
figure(2);
plot(t,RSOC,'-k',t,Xekf(2,:),'-r','lineWidth',2); grid on
legend('真实值','估计值-EKF');
ylabel('SOC','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
V_error=Vot-Vekf';
SOC_error=RSOC-Xekf(2,:)';
SOC_error_mean=mean(abs(SOC_error(5000:end)));
SOC_error_max=max(abs(SOC_error(5000:end)));
figure(3);
% plot(t,V_error ,'-k','lineWidth',2); grid on
plot(t,V_error,'-k','lineWidth',2); grid on
legend('端电压误差');
ylabel('端电压误差','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
figure(4);
plot(t,SOC_error,'-k','lineWidth',2); grid on
legend('SOC误差');
ylabel('SOC误差','Fontsize', 16)
xlabel('时间(s)', 'Fontsize', 16)
figure(5);
plot(t,Cur,'-k','lineWidth',2); grid on
legend('电流');
SOC_EKF=Xekf(2,:);
SOC_error_EKF=SOC_error;
save SOC_EKF.mat SOC_EKF
save SOC_error_EKF.mat SOC_error_EKF
save RSOC.mat RSOC