实现卡尔曼滤波器以平滑来自 deviceOriented API 的数据
Implement a Kalman filter to smooth data from deviceOrientation API
我正在尝试平滑从deviceOrientationAPI获得的数据,以便在浏览器中制作Google Cardboard应用程序。
我将加速度计数据直接输送到 ThreeJs 相机旋转中,但我们在信号上收到了很多噪音,导致视图抖动。
有人建议使用卡尔曼滤波器作为平滑信号处理噪声的最佳方法,我在gitHub上找到了这个简单的Javascript库。
https://github.com/itamarwe/kalman
但是,它在文档中真的很轻。
我知道我需要通过提供一个向量和 3 个矩阵作为参数来创建卡尔曼模型,然后更新模型,再次使用向量和矩阵作为时间范围内的参数。
我还了解到卡尔曼滤波器方程有几个不同的部分:当前估计位置、卡尔曼增益值、方向 API 的当前读数和先前估计的位置。
我可以看到 3D 空间中的一个点可以描述为矢量,因此任何位置值(例如估计位置或当前读数(都可以是矢量。
我不明白的是,如何将这些部分转换为矩阵以形成Javascript库的参数。
好吧,几年前我写了这个令人憎恶的库。如果有兴趣,我绝对愿意升级它,改进文档并编写测试。
让我简要解释一下所有不同的矩阵和向量是什么,以及它们应该如何推导:
x
- 这是您尝试估计的向量。在您的情况下,可能是 3 个角加速度。
P
- 是估计的协方差矩阵,表示估计的不确定性。在卡尔曼滤波器的每个步骤中也估计它与x
.
F
- 描述X
如何根据模型发展。通常,该模型是x[k] = Fx[k-1]+w[k]
的。在您的情况下,如果您预计角加速度相对平滑,则F
可能是单位矩阵,或者如果您预计角加速度完全不可预测,则可能是零矩阵。在任何情况下,w
将表示您期望加速度逐步变化的程度。
w
- 描述过程噪声,即模型与"完美"模型的分歧程度。它被定义为具有协方差矩阵Q
的零均值多元正态分布。
上述所有变量都定义了您的模型,即您要估计的内容。在下一部分中,我们将讨论观测模型 - 您测量的内容以估计模型。
z
- 这就是你衡量的。在您的情况下,由于您使用的是加速度计,因此您正在测量您也在估计的内容。它将是角加速度。
H
- 描述模型与观测值之间的关系。 z[k]=H[k]x[k]+v[k]
.在您的情况下,它是单位矩阵。
v
- 是测量噪声,假定为零均值高斯白噪声,协方差为 R[k]。在这里,您需要测量加速度计的噪声,并计算噪声协方差矩阵。
总而言之,使用卡尔曼滤波器的步骤:
- 确定
x[0]
和P[0]
- 模型的初始状态,以及对x[0]
准确程度的初始估计。 - 根据您的模型确定
F
以及它如何逐步发展。 - 根据模型的随机性质确定
Q
。 - 根据测量内容与要估计的内容之间的关系(模型和测量值之间的关系(确定
H
。 - 根据测量噪声确定
R
。您的测量值有多嘈杂。
然后,对于每个新观测值,您可以使用卡尔曼滤波器更新模型状态估计,并对模型的状态(x[k]
(以及该估计的准确性(P[k]
(进行最佳估计。
var acc = {
x:0,
y:0,
z:0
};
var count = 0;
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', getDeviceRotation, false);
}else{
$(".accelerometer").html("NOT SUPPORTED")
}
var x_0 = $V([acc.x, acc.y, acc.z]); //vector. Initial accelerometer values
//P prior knowledge of state
var P_0 = $M([
[1,0,0],
[0,1,0],
[0,0,1]
]); //identity matrix. Initial covariance. Set to 1
var F_k = $M([
[1,0,0],
[0,1,0],
[0,0,1]
]); //identity matrix. How change to model is applied. Set to 1
var Q_k = $M([
[0,0,0],
[0,0,0],
[0,0,0]
]); //empty matrix. Noise in system is zero
var KM = new KalmanModel(x_0,P_0,F_k,Q_k);
var z_k = $V([acc.x, acc.y, acc.z]); //Updated accelerometer values
var H_k = $M([
[1,0,0],
[0,1,0],
[0,0,1]
]); //identity matrix. Describes relationship between model and observation
var R_k = $M([
[2,0,0],
[0,2,0],
[0,0,2]
]); //2x Scalar matrix. Describes noise from sensor. Set to 2 to begin
var KO = new KalmanObservation(z_k,H_k,R_k);
//each 1/10th second take new reading from accelerometer to update
var getNewPos = window.setInterval(function(){
KO.z_k = $V([acc.x, acc.y, acc.z]); //vector to be new reading from x, y, z
KM.update(KO);
$(".kalman-result").html(" x:" +KM.x_k.elements[0]+", y:" +KM.x_k.elements[1]+", z:" +KM.x_k.elements[2]);
$(".difference").html(" x:" +(acc.x-KM.x_k.elements[0])+", y:" +(acc.y-KM.x_k.elements[1])+", z:" +(acc.z-KM.x_k.elements[2]))
}, 100);
//read event data from device
function getDeviceRotation(evt){
// gamma is the left-to-right tilt in degrees, where right is positive
// beta is the front-to-back tilt in degrees, where front is positive
// alpha is the compass direction the device is facing in degrees
acc.x = evt.alpha;
acc.y = evt.beta;
acc.z = evt.gamma;
$(".accelerometer").html(" x:" +acc.x+", y:" +acc.y+", z:" +acc.z);
}
这是一个演示页面,显示我的结果
http://cardboard-hand.herokuapp.com/kalman.html
我现在已将传感器噪声设置为 2 标量矩阵,以查看卡尔曼是否在做它的事情,但我们注意到当手机平放在桌子上时,传感器在 x 轴上具有更大的方差。我们认为这可能是万向节锁的问题。我们还没有测试过,但每个轴的方差可能会根据设备的方向而变化。
- 如何更改bigquery API中的计费层选项
- Amazon S3 REST API大小不正确
- 客户端服务器REST API captcha实现
- 使用Facebook live API创建实时视频对象时的隐私设置
- 谷歌放置API:按国家或餐馆名称搜索餐馆
- MeteorJS:在带有回调的vzaar api上正确使用wrapAsync
- 是否可以控制获取哪些Google地图脚本(JavaScript API)
- API密钥使用和检查示例
- 谷歌地图API v3不适用于移动浏览器或PhoneGap
- 任何方式使AJAX调用Gmail API,而无需通过JS库
- 谷歌地图JS API+JSON-多个标记没有显示
- 单击超链接时,如何使用Google Maps API v3缩放地图
- 如何在 API 调用后和 if 语句中启用提交按钮
- 与运行长作业(javascript,node.js)的第三方API同步的最佳实践
- 搜索api在mac上显示对话框
- Backbone.js restful json API design
- 标记的实时更新,无需加载页面谷歌地图API V3
- 是否可以使用iframe API在iOS浏览器上播放youtube视频
- 对API数据使用声明性绑定
- 实现卡尔曼滤波器以平滑来自 deviceOriented API 的数据