我正在尝试为罗盘轴承输入实现一个低通滤波器,我已经整理了一个如下所示的基本功能:
var smoothing = 0.15;
function lowPass(degree) {
var oldVal = $scope.compassBearing || 0;
var smoothedValue = oldVal + smoothing * (degree - oldVal);
return smoothedValue;
}
效果很好,除了指南针轴承向北经过时(即突然从0变为359,反之亦然。
有没有人遇到类似的问题,如果有的话,它是如何解决的?
答案 0 :(得分:4)
让我们说你总是希望它在最短的路径上顺畅。因此,如果更改是从270度到5度,它会通过北,然后你必须检查值,看看它们之间的差异是否大于180.如果是这样,那么稍微修改一下这个函数。
如果差异小于-180,则翻转几个运算符并将360添加到混音中。如果差异大于180,则相同。最后检查结果是否大于360或小于0,并更正。
function lowPass(degree) {
var oldVal = $scope.compassBearing || 0;
var smoothedValue;
if(oldVal - degree < -180){
// Invert the logic
smoothedValue = oldVal - smoothing * (oldVal + 360 - degree);
if (smoothedValue < 0){
smoothedValue = smoothedValue + 360;
}
} else if (oldVal - degree > 180){
smoothedValue = oldVal + (360 + degree - oldVal) * smoothing;
if (smoothedValue > 360){
smoothedValue = smoothedValue - 360;
}
}
else {
smoothedValue = oldVal + smoothing * (degree - oldVal);
}
return smoothedValue;
}
看起来很乱,但我只是玩弄它。希望它是你所需要的。
答案 1 :(得分:1)
如果您利用复杂的数学,有一种更优雅的方法可以做到这一点。基本上,使用复数,您可以在罗盘上代表一个点。
如果要“平均”或“平滑”两个罗盘读数,可以在复杂域中执行此操作,然后转换回角度域。
有了这个,我们可以使用数学js库并使你的函数基本上保持与你的相同形式:
var smoothing = .9;
function lowPass(degree, oldVal) {
// var oldVal = $scope.compassBearing || 0;
var complexOldVal = math.complex({r:1, phi:oldVal * (math.pi/180)});
var complexNewVal = math.complex({r:1, phi:degree * (math.pi/180)});
var complexSmoothedValue = math.chain(complexNewVal)
.subtract(complexOldVal)
.multiply(smoothing)
.add(complexOldVal)
.done();
var smoothedValue = math.arg(complexSmoothedValue) * (180/math.pi);
if (smoothedValue < 0) { return 360 + smoothedValue; }
return smoothedValue;
}
document.write(lowPass(20, 30)+'<br>');
// 20.99634415156203
document.write(lowPass(10, 350)+'<br>');
// 8.029256754215519