陈拓 2020/12/08-2020/12/19
1. 概述
在正弦波上叠加高斯白噪声,再用卡尔曼滤波滤除噪声。
相关文档:
《Echarts动态生成sin曲线》https://blog.csdn.net/chentuo2000/article/details/110622403
《Echarts动态产生高斯白噪声》https://blog.csdn.net/chentuo2000/article/details/110795146
《echarts动态滑动平均滤波》https://blog.csdn.net/chentuo2000/article/details/111088311
2. HTML页面和js程序
<!DOCTYPE html>
<html style="height: 100%">
<head>
<meta charset="utf-8">
</head>
<body style="height: 100%; margin: 0">
<div id="container1" style="position:absolute; left:10px; top:0px; height:320px; width:400px;"></div>
<div id="container3" style="position:absolute; left:400px; top:0px; height:320px; width:400px;"></div>
<div id="container5" style="position:absolute; left:800px; top:0px; height:320px; width:400px;"></div>
<div id="container6" style="position:absolute; left:800px; top:280px; height:320px; width:400px;"></div>
<script type="text/javascript" src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
<script type="text/javascript">
var dom1 = document.getElementById("container1");
var myChart1 = echarts.init(dom1);
var dom3 = document.getElementById("container3");
var myChart3 = echarts.init(dom3);
var dom5 = document.getElementById("container5");
var myChart5 = echarts.init(dom5);
var dom6 = document.getElementById("container6");
var myChart6 = echarts.init(dom6);
var app = {};
var option;
var N_POINT = 500; // 曲线的x轴长度
var angle = 0;
var x_axis1 = [];
var x_data1 = 0;
var y_axis1 = [];
var y_data1 = 0;
var x_axis3 = [];
var x_data3 = 0;
var y_axis3 = [];
var y_data3 = 0;
var x_axis5 = [];
var x_data5 = 0;
var y_axis5 = [];
var y_data5 = 0;
var x_axis6 = [];
var x_data6 = 0;
var y_axis6 = [];
var y_data6 = 0;
// 产生三角函数
function sin_data(x) {
x = x/10;
return Math.sin(x*Math.PI);
}
// 产生服从 U(0,1) 的均匀分布随机数random1和random2
function random1(x) {
return Math.random();
}
function random2(x) {
return Math.random();
}
// 用Box Muller方法生成正态分布随机数
function b_m(x, y) {
var means= 0; // 平均值,决定对称中线
var sigma= 1; // 标准方差,决定曲线的胖瘦
z = Math.sqrt(-2 * Math.log(x)) * Math.cos(2 * Math.PI * y);
return means + z * sigma;
}
/* 卡尔曼滤波
R值固定,Q值越大,代表越信任测量值,Q值无穷大,代表只用测量值。
Q值越小,代表越信任模型预测值,Q值为0,代表只用模型预测值。
Q增大,动态响应变快,收敛稳定性变坏
R增大,动态响应变慢,收敛稳定性变好
*/
var LastP = 0.02;//上次估算协方差初始化值为0.02
var Now_P = 0;//当前估算协方差初始化值为0
var out = 0;//卡尔曼滤波器输出初始化值为0
var Kg = 0;//卡尔曼增益初始化值为0
var Q = 0.0005;//过程噪声协方差初始化值为0.0005
var R = 0.6;//观测噪声协方差初始化值为0.543
function KalmanFilter(inData)
{
//预测协方差方程:k时刻系统估算协方差 = k-1时刻的系统协方差 + 过程噪声协方差
Now_P = LastP + Q;
//卡尔曼增益方程:卡尔曼增益 = k时刻系统估算协方差 / (k时刻系统估算协方差 + 观测噪声协方差)
Kg = Now_P/(Now_P + R);
//更新最优值方程:k时刻状态变量的最优值 = 状态变量的预测值 + 卡尔曼增益 * (测量值 - 状态变量的预测值)
out = out + Kg * (inData - out); //因为这一次的预测值就是上一次的输出值
//更新协方差方程: 本次的系统协方差付给 LastP 威下一次运算准备。
LastP = (1-Kg) * Now_P;
return out;
}
// 生成x轴和y轴数据
function addData(shift) {
x_data1++;
x_axis1.push(x_data1);
x_data3++;
x_axis3.push(x_data3);
x_data5++;
x_axis5.push(x_data5);
x_data6++;
x_axis6.push(x_data6);
y_data1 = 10*sin_data(angle); // 生成sin曲线
y_axis1.push(y_data1);
angle+=0.1;
var x = random1(); // 生成均匀分布的伪随机数
var y = random2(); // 生成均匀分布的伪随机数
y_data3 = b_m(x, y); // 生成正态分布的随机数
y_axis3.push(y_data3);
y_data5 = y_data1 + y_data3; // 生成混合信号
y_axis5.push(y_data5);
y_data6 = KalmanFilter(y_data5)
y_axis6.push(y_data6);
if (shift) {
x_axis1.shift();
y_axis1.shift();
x_axis3.shift();
y_axis3.shift();
x_axis5.shift();
y_axis5.shift();
x_axis6.shift();
y_axis6.shift();
}
}
// 生成N_POINT个数据,初始化x_axis和y_axis数组,数组的长度在这里被设置成N_POINT
for (var i = 0; i < N_POINT; i++) {
addData(false);
}
option1 = {
title : {
show:true,
padding: [20,20,100,100],
text: 'sin曲线',
x:'center'
},
xAxis: {
type: 'category',
data: x_axis1
},
yAxis: {
type: 'value'
},
series: [{
animation: false,
showSymbol: false,
clip: true,
data: y_axis1,
type: 'line'
}]
};
option3 = {
title : {
show:true,
padding: [20,20,100,100],
text: '高斯白噪声',
x:'center'
},
xAxis: {
type: 'category',
data: x_axis3
},
yAxis: {
type: 'value'
},
series: [{
animation: false,
showSymbol: false,
clip: true,
data: y_axis3,
type: 'line'
}]
};
option5 = {
title : {
show:true,
padding: [20,20,100,100],
text: '混合信号',
x:'center'
},
xAxis: {
type: 'category',
data: x_axis5
},
yAxis: {
type: 'value'
},
series: [{
animation: false,
showSymbol: false,
clip: true,
data: y_axis5,
type: 'line'
}]
};
option6 = {
title : {
show:true,
padding: [20,20,100,100],
text: '卡尔曼滤波后的结果',
x:'center'
},
xAxis: {
type: 'category',
data: x_axis6
},
yAxis: {
type: 'value'
},
series: [
{
animation: false,
showSymbol: false,
type: 'line',
data: y_axis6,
smooth: true,
itemStyle: {
normal: {
lineStyle: {
color: '#c23531' //改变折线颜色
}
}
}
}
]
};
setInterval(function () {
addData(true); // 生成数据并左移
myChart1.setOption(option1);
myChart3.setOption(option3);
myChart5.setOption(option5);
myChart6.setOption(option6);
}, 500); // 500ms刷新一次
</script>
</body>
</html>
3. 在浏览器中的效果图
可以调整Q和R值来观察不同的滤波效果。