Javascript 低通罗盘平滑怪异
我正在尝试为指南针方位输入实现一个低通滤波器,我已经组合了一个基本函数,如下所示:Javascript 低通罗盘平滑怪异,javascript,Javascript,我正在尝试为指南针方位输入实现一个低通滤波器,我已经组合了一个基本函数,如下所示: var smoothing = 0.15; function lowPass(degree) { var oldVal = $scope.compassBearing || 0; var smoothedValue = oldVal + smoothing * (degree - oldVal); return smoothedValue; } 除了指南针方位向北(即从0到359突然改
var smoothing = 0.15;
function lowPass(degree) {
var oldVal = $scope.compassBearing || 0;
var smoothedValue = oldVal + smoothing * (degree - oldVal);
return smoothedValue;
}
除了指南针方位向北(即从0到359突然改变,或反之亦然)时,工作正常
有没有人遇到过类似的问题,如果是,是如何解决的?假设您总是希望它在最短路径上平滑。因此,如果变化是从270度到5度,它会经过north,那么您必须检查这些值,看看它们之间的差异是否超过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;
}
功能低通(度){
var oldVal=$scope.compassBearing | | 0;
var平滑值;
如果(旧值-度<-180){
//颠倒逻辑
平滑值=oldVal-平滑*(oldVal+360度);
if(平滑值<0){
平滑值=平滑值+360;
}
}否则,如果(旧值-度数>180){
平滑值=oldVal+(360+度-oldVal)*平滑;
如果(平滑值>360){
平滑值=平滑值-360;
}
}
否则{
平滑值=oldVal+平滑*(度-oldVal);
}
返回平滑值;
}
它看起来很乱,但我只是随便玩了玩。希望这是你需要的。如果你利用复杂的数学,有一种更优雅的方法可以做到这一点。基本上,用复数你可以表示指南针上的一个点 如果你想“平均”或“平滑”两个罗盘读数,你可以在复数域中这样做,然后转换回角度域 有了它,我们可以使用math 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
var平滑=.9;
函数低通(度数,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)
.减去(complexOldVal)
.乘法(平滑)
.add(complexOldVal)
.完成();
var平滑值=math.arg(complexSmoothedValue)*(180/math.pi);
如果(SmoothdValue<0){return 360+SmoothdValue;}
返回平滑值;
}
写(低通(20,30)+'
');
// 20.99634415156203
写(低通(10350)+“
”;
// 8.029256754215519
你可以在这里摆弄它:问题出在哪里?
smoothValue
变成例如361,-2等?这是平滑试图将读数“平滑”到另一侧-因此,它不是平滑从356->358->0->2过渡,而是尝试平均这两个值,以便罗盘在相反方向快速旋转适应新价值观的方向。是的,我想到了。我自己刚试过你的剧本,看到了你真正的问题。从359到10的转变是“倒退的”,不是通过0。这个问题还不清楚。@SharkAlley用trig来解决这个问题,真是太棒了。我只是想挑逗一下,但你赢了我。周日的宿醉会让我的逻辑思维变得迟钝:)我必须承认,我真的可以用这个解决方案来解决我的问题。但对于这个简单的应用程序,我认为引入一个外部库,并疏远那些不熟悉弧度的人的代码,可能有点过分了。尽管如此,我还是很喜欢:)我听到了你的话,并且大体上同意。。。这种方法的一个优点是,如果您想进行更高级的平滑,它可以轻松地进行缩放。除了在角度域中求平均值之外,做任何事情都可能导致不期望的结果。在所有方面达成一致:P选择了danny,并纯粹为了可读性而实现了它。这个解决方案看起来很优雅,但对我来说,它本质上是一个黑匣子!