低通罗盘平滑怪异

时间:2016-03-20 20:54:18

标签: javascript

我正在尝试为罗盘轴承输入实现一个低通滤波器,我已经整理了一个如下所示的基本功能:

var smoothing = 0.15;

function lowPass(degree) {
    var oldVal = $scope.compassBearing || 0;
    var smoothedValue = oldVal + smoothing * (degree - oldVal);
    return smoothedValue;
}

效果很好,除了指南针轴承向北经过时(即突然从0变为359,反之亦然。

有没有人遇到类似的问题,如果有的话,它是如何解决的?

2 个答案:

答案 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)

如果您利用复杂的数学,有一种更优雅的方法可以做到这一点。基本上,使用复数,您可以在罗盘上代表一个点。

enter image description here

如果要“平均”或“平滑”两个罗盘读数,可以在复杂域中执行此操作,然后转换回角度域。

有了这个,我们可以使用数学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

你可以在这里弄乱它:http://jsbin.com/zelokaqoju/edit?html,output