Relevant source code and data files have been updated on github: https://github.com/Wuito/Estimation-of-residual-life-of-particle-filter-lithium-ion-battery

# particle filter sampling

The completeness of the particle filter algorithm is based on the resampling technology proposed by Gordon, Salmond and Smith, and the discovery and continuous improvement of a new sampling algorithm (sampling-importance resampling) also enriches the particle filter algorithm.

# Particle filter resampling

Commonly used resampling methods can be divided into four categories: nearest neighbor resampling method, bilinear resampling method, bicubic resampling method, interpolation resampling method.

1) Nearest neighbor resampling method: refers to comparing the width or height of the target image with the original image, and using the pixel at the relative position of the original image as the value of the pixel of the target image.

2) Bilinear resampling method: refers to the value of four points around the corresponding pixel of the reference original image, and obtains the target image by taking a weight value for each point from the relative position.

3) Bicubic resampling method: refer to the value of 4*4 pixels around the original pixel point, and obtain the target image based on this.

4) Interpolation resampling method: Compared with the above algorithm, this method refers to more original image data information, and can be used to solve symmetric matrix equations and eigenvalue problems, and the resampling effect is generally better.

The resampling algorithm is to copy and eliminate steps according to probability. Those with high weight may be copied multiple times, which ensures that the overall number of particles is basically unchanged, and then normalized to change the weight of all particles to 1/ n, proceed to the next step of forecast update. Although the application of resampling will not completely eradicate the particle degradation problem, it will greatly improve the particle degradation problem.

Although the resampling method can reduce the problem of particle degradation to a certain extent, it will inevitably lead to the loss of the diversity of examples, that is, N=1/(∑▒W_K^i ), the smaller the N, the more serious the problem of particle degradation, and the more Resampling is required, and such multiple resamplings will of course slow down the particle filter.

# Battery capacity fade model

According to the battery capacity calculation formula: Q=∫_tc^td▒〖I(t)dt〗, where tc represents the charging time, td represents the battery discharge time, I(t) represents the current, and Q represents the lithium ion The real-time capacity of the battery, while the elapsed time t records the time from the beginning of the battery cycle to the end of the experiment. Through the exponential fitting of the four battery capacity data through the Matlab curve fitting toolbox, a more accurate exponential decay model can be obtained.

According to the battery decay model, we choose the double exponential empirical model.

Q represents the battery capacity at time k, where k is the number of cycles, a, b, c, and d are all related to the lithium-ion battery itself, so when a, b, c, and d are estimated more accurately, then the battery itself The more realistic the simulation, the more accurately it can predict battery life.

# Algorithm process

To summarize the particle filter algorithm method, there is a flow chart:

use Python3.8, Numpy1.23, matplotlib3.6 software environment to design the above algorithm. Run the Python program to get the capacity prediction map of the CS2 battery. In the experiment, CS2_36 is used as the sample set, and the first 600 data of the sample are randomly sampled at 10:1, and then the double exponential model is fitted using the Matlab fitting toolbox.

# Curve Fitting

With the fitted parameters and algorithm equations, start filtering:

Note that the data loaded by python here has been calculated and saved before.

This is the file structure of my project. You need to download the data of the University of Maryland in the previous blog, process the data and save it as a file in npy format, and then apply it here.

First, the rendering of the particle filter:

the blue is the observed value, the yellow is the calculated value of the filter, starting from the red line, and the green is the calculated value of the natural observation without filtering.

```
# 基于粒子滤波的锂离子电池RUL预测
# From: SWUST IPC14 Dai
import numpy as np
import matplotlib.pyplot as plt
from scipy.linalg import sqrtm
# Python3.8、Numpy1.23、matplotlib3.6
# 除去数据异常的较大值和较小值点
def drop_outlier(array, count, bins):
index = []
range_ = np.arange(1, count, bins)
for i in range_[:-1]:
array_lim = array[i:i + bins]
sigma = np.std(array_lim)
mean = np.mean(array_lim)
th_max, th_min = mean + sigma * 2, mean - sigma * 2
idx = np.where((array_lim < th_max) & (array_lim > th_min))
idx = idx[0] + i
index.extend(list(idx))
return np.array(index)
# 剩余容量双指数方程，状态方程
def hfun(X, k):
Q = X[0] * np.exp(X[1] * k) + X[2] * np.exp(X[3] * k)
return Q
# 重采样步骤：
# 预测：抽取新粒子
# 更新：更新粒子权值
# 状态估计
# 多项式重采样
# 重采样
def randomR(inIndex, q):
outIndex = np.zeros(np.shape(inIndex))
num = np.shape(q)
u = np.random.rand(num[0], 1)
u = np.sort(u, axis = 0)
u = np.array(u)
l = np.cumsum(q, axis=0)
i = 0
for j in np.arange(0, num[0]):
while (i <= (num[0]-1)) and (u[i] <= l[j]):
outIndex[i] = j
i = i + 1
return outIndex
# capacity：阶段放电容量
# resistance：放电阶段电池的的内阻平均值
# CCCT：恒定电流充电时间
# CVCT: 恒定电压充电时间
if __name__ == "__main__":
# ========================================
# 加载数据
# ========================================
Battery_name = 'CS2_38'
Battery = np.load('dataset/' + Battery_name + '.npy', allow_pickle=True)
Battery = Battery.item()
battery = Battery[Battery_name]
names = ['capacity', 'resistance', 'CCCT', 'CVCT']
# battery[1] = battery[1] /(battery[1] + 1.1)
# 粒子滤波步骤
# 初始化
# 更新粒子状态
# 权值计算和归一化
# 重采样
# 判断程序是否结束，迭代
# ========================================
# 预估数据为电池容量
# ========================================
N = len(battery['cycle'])
pf_Number = 200 # 粒子数
Prediction_Interval = 300 # 未来趋势值,预测区间的大小
cita = 1e-4
wa = 0.000001 # 设定状态初始值
wb = 0.01
wc = 0.1
wd = 0.0001
Q = cita * np.diag([wa, wb, wc, wd]) # Q为过程噪声方差矩阵，diag()创建指定对角矩阵
F = np.eye(4) # F为驱动计算矩阵，eye()单位对角矩阵
R = 0.001 # 观测噪声的协方差
# ========= 状态方程赋初值 ==============
a = -0.0000083499
b = 0.055237
c = 0.90097
d = -0.00088543
X0 = np.mat([a, b, c, d]).T # 矩阵转置
# ========= 滤波器状态初始化 ==============
Xpf = np.zeros([4, N])
Xpf[:, 0:1] = X0 # 对齐数组
# ========= 粒子集初始化 ==============
Xm = np.zeros([4, pf_Number, N])
for i in np.arange(0, pf_Number - 1):
sqr1 = np.array(sqrtm(Q))
sqr2 = sqr1.dot(np.random.randn(4, 1)) # 矩阵乘法，直接用*是矩阵点乘
Xm[:, i:i + 1, 0] = X0 + sqr2 # 对齐数组,需要将矩阵对齐后才能相加
# ========= 从数据集读取观测量 =============
capacity = battery[names[0]]
Z = np.array(capacity)
# ========= Zm为滤波器预测观测值，Zm与Xm对应 =============
Zm = np.zeros([1, pf_Number, N])
# ========= Zpf与Xpf对应 =============
Zpf = np.zeros([1, N]) # 计算中得到的Zpf为滤波器更新得到的容量值
# ========= 权值初始化 =============
Weight = np.zeros([N, pf_Number]) # 计算中得到的W为更新的粒子权重
# 粒子滤波算法
for k in np.arange(1, N - 1):
# 重要性采样
for i in np.arange(0, pf_Number - 1):
sqr1 = np.array(sqrtm(Q)) # 观测噪声
sqr2 = sqr1.dot(np.random.randn(4, 1)) # 矩阵乘法，直接用*是矩阵点乘
Xm[:, i:i + 1, k] = F.dot(Xm[:, i:i + 1, k - 1]) + sqr2
# 权值重要性计算
for i in np.arange(0, pf_Number - 1):
Zm[0, i:i + 1, k] = hfun(Xm[:, i:i + 1, k], k) # 观测预测
Weight[k, i] = np.exp(-(Z[k] - Zm[0, i:i + 1, k:k + 1]) ** 2 / 2 / R) + 1e-99 # 重要性权值计算，乘方用 **
Weight[k, :] = Weight[k, :] / sum(Weight[k, :]) # 权值归一化
# 重采样
# 这里的重采样以权值为传入值，返回值为采样后的索引
outlndex = randomR(np.arange(0, pf_Number), Weight[k, :])
# 得到新的样本
for i in np.arange(0, len(outlndex)):
Xm[:, i, k] = Xm[:, int(outlndex[i]), k]
# 滤波后的状态更新，更新参数[a,b,c,d]
Xpf[:, k] = [np.mean(Xm[0, :, k]),
np.mean(Xm[1, :, k]),
np.mean(Xm[2, :, k]),
np.mean(Xm[3, :, k])]
# 更新后的状态计算预测的容量值
Zpf[0, k] = hfun(Xpf[:, k], k)
# ========================================
# 计算自然条件下的预测值
# ========================================
start = N - Prediction_Interval # 预测的区间
Zf = np.zeros(Prediction_Interval) # 自然预测值
Xf = np.zeros(Prediction_Interval)
for k in np.arange(start-1, N-1):
Zf[k-start] = hfun(Xpf[:, start], k)
Xf[k-start] = k
# 画线
nax = [start, start]
nay = [0, 1]
plt.figure(figsize=(12, 9))
plt.title('Particle filter '+ Battery_name) # 折线图标题
plt.xlabel('Number of Cycles', fontsize=14)
plt.ylim((0, 1.1))
plt.ylabel(names[0], fontsize=14)
plt.plot(battery['cycle'], Z, markersize=3)
plt.plot(battery['cycle'], Zpf[0, :], markersize=3)
plt.plot(Xf, Zf, markersize=3)
plt.plot(nax, nay, linewidth=4)
plt.legend(['Measured value', 'pf Predictive value', 'Natural predicted value'])
plt.show()
```

# Matlab particle filter

## main.m

```
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 版权声明：
% 本程序的详细中文注释请参考
% 黄小平，王岩，缪鹏程.粒子滤波原理及应用[M].电子工业出版社，2017.4
% 书中有原理介绍+例子+程序+中文注释
% 如果此程序有错误，请对提示修改
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 函数功能：粒子滤波用于电源寿命预测
% function main
load Battery_Capacity
%%load Battery_Capacity
N=length(A5Cycle);
% error('下面的参数M请参考书中的值设置，然后删除本行代码')
M=200; %%粒子数
Future_Cycle=100; % 未来趋势
if N>260
N=260; % 过滤大于260的数字
end
%过程噪声协方差Q
cita=1e-4;
wa=0.000001;wb=0.01;wc=0.1;wd=0.0001;
Q=cita*diag([wa,wb,wc,wd]);
%驱动矩阵
F=eye(4);
%观测噪声协方差
R=0.001;
a=-0.0000083499;b=0.055237;c=0.90097;d=-0.00088543;
X0=[a,b,c,d]';
%滤波器状态初始化
Xpf=zeros(4,N);
Xpf(:,1)=X0;
% 粒子集初始化
Xm=zeros(4,M,N);
for i=1:M
Xm(:,i,1)=X0+sqrtm(Q)*randn(4,1);
end
% 观测量
Z(1,1:N)=A12Capacity(1:N,:)';
Zm=zeros(1,M,N);
Zpf=zeros(1,N);
W=zeros(N,M);
%粒子滤波算法
for k=2:N
% 采样
for i=1:M
Xm(:,i,k)=F*Xm(:,i,k-1)+sqrtm(Q)*randn(4,1);
end
% 权值重要性计算
for i=1:M
Zm(1,i,k)=feval('hfun',Xm(:,i,k),k);
W(k,i)=exp(-(Z(1,k)-Zm(1,i,k))^2/2/R)+1e-99;
end,
W(k,:)=W(k,:)./sum(W(k,:));
% 重采样
outIndex = randomR(1:M,W(k,:)'); % 调用外部函数
% 得到新样本
Xm( :, :, k)=Xm( :, outIndex, k);
% 滤波后的状态更新
Xpf(:,k)=[mean(Xm(1,:,k));mean(Xm(2,:,k));mean(Xm(3,:,k));mean(Xm(4,:,k))];
% 更新后的状态计算
Zpf(1,k)=feval('hfun',Xpf(:,k),k);
end
%预测未来电容的趋势
start=N-Future_Cycle;
for k=start:N
Zf(1,k-start+1)=feval('hfun',Xpf(:,start),k);
Xf(1,k-start+1)=k;
end
Xreal=[a*ones(1,M);b*ones(1,M);c*ones(1,M);d*ones(1,M)];
figure
subplot(2,2,1);
hold on;box on;
plot(Xpf(1,:),'-r.');plot(Xreal(1,:),'-b.')
legend('粒子滤波后的a','平均值a')
subplot(2,2,2);
hold on;box on;
plot(Xpf(2,:),'-r.');plot(Xreal(2,:),'-b.')
legend('粒子滤波后的b','平均值b')
subplot(2,2,3);
hold on;box on;
plot(Xpf(3,:),'-r.');plot(Xreal(3,:),'-b.')
legend('粒子滤波后的c','平均值c')
subplot(2,2,4);
hold on;box on;
plot(Xpf(4,:),'-r.');plot(Xreal(4,:),'-b.')
legend('粒子滤波后的d','平均值d')
figure
hold on;box on;
plot(Z,'-b.')
plot(Zpf,'-r.')
plot(Xf,Zf,'-g.')
bar(start,1,'y')
legend('实验测量数据','滤波估计数据','自然预测数据')
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```

## hfun.m

```
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 版权声明：
% 本程序的详细中文注释请参考
% 黄小平，王岩，缪鹏程.粒子滤波原理及应用[M].电子工业出版社，2017.4
% 书中有原理介绍+例子+程序+中文注释
% 如果此程序有错误，请对提示修改
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 函数名称：电容的观测函数
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function Q=hfun(X,k)
Q=X(1)*exp(X(2)*k)+X(3)*exp(X(4)*k);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
```

## randomR.m

```
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% 版权声明：
% 本程序的详细中文注释请参考
% 黄小平，王岩，缪鹏程.粒子滤波原理及应用[M].电子工业出版社，2017.4
% 书中有原理介绍+例子+程序+中文注释
% 如果此程序有错误，请对提示修改
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function outIndex = randomR(inIndex,q);
if nargin < 2
error('Not enough input arguments.');
end
outIndex=zeros(size(inIndex));
[num,col]=size(q);
u=rand(num,1);
u=sort(u);
l=cumsum(q);
i=1;
for j=1:num
while (i<=num)&(u(i)<=l(j))
outIndex(i)=j;
i=i+1;
end
end
```