Java 如何对角度值进行低通滤波
我从一个以弧度为单位的传感器接收角度更新,我想通过一个低通滤波函数来平滑它们,因为噪声 我的低通滤波器函数如下所示Java 如何对角度值进行低通滤波,java,math,geometry,filtering,computational-geometry,Java,Math,Geometry,Filtering,Computational Geometry,我从一个以弧度为单位的传感器接收角度更新,我想通过一个低通滤波函数来平滑它们,因为噪声 我的低通滤波器函数如下所示 protected void lowPass(float alpha, double[] input, double[] output) { for (int i = 0; i < input.length; i++) { output[i] = alpha * output[i] + (1 - alpha) * input[i]; } }
protected void lowPass(float alpha, double[] input, double[] output) {
for (int i = 0; i < input.length; i++) {
output[i] = alpha * output[i] + (1 - alpha) * input[i];
}
}
而且它在大多数情况下都非常有效
问题是,有时角度会转一整圈,例如从2π到0,0到-2π,等等。当然,这会导致不正确的输出,因为滤波函数将2π和0简单地视为6.28和0.0
如何实现能够正确处理此类角度的过滤函数?对于这样的指数平滑,最简单的方法是从每个输入中添加或减去2*pi,使其尽可能接近之前的平滑值。或者,等效地,在平滑到输入之前,从先前的输出中加上或减去2*pi。在任何一种情况下,您的输出都可能暂时超出[0,2*pi范围,因此,如果需要,请确保将其返回到该范围
顺便说一句,您的代码有一个错误,因为它从错误的输出索引中读取,并且不能正确处理第一个时间值。对于这样的指数平滑,最简单的方法是从每个输入中添加或减去2*pi,使其尽可能接近之前的平滑值。或者,等效地,从在平滑到输入之前,m是上一个输出。在任何一种情况下,您的输出都可能暂时超出[0,2*pi范围,因此,如果需要,请确保将其环绕回该范围
顺便说一句,您的代码有一个bug,因为它从错误的输出索引中读取,并且不能正确处理第一时间值。有一种有趣的方法用于 获取角度α的余弦和正弦作为向量的分量,并使用它们进行单独滤波,然后获取结果向量的角度
cosa = alpha * cos(output) + (1 - alpha) * cos(input);
sina = alpha * sin(output) + (1 - alpha) * sin(input);
output = atan2(sina, cosa)
有一种有趣的方法可以用于 获取角度α的余弦和正弦作为向量的分量,并使用它们进行单独滤波,然后获取结果向量的角度
cosa = alpha * cos(output) + (1 - alpha) * cos(input);
sina = alpha * sin(output) + (1 - alpha) * sin(input);
output = atan2(sina, cosa)
您需要执行相位展开,即恢复周期性发生的2π跳变。为此,您可以检测异常,例如接近2π的值紧接着接近0的值,反之,并进行补偿 注意,如果值以较大的增量变化,比如大于π,则跳转是不可恢复的
请参阅。您需要执行相位展开,即恢复周期性发生的2π跳变。为此,您可以检测异常,如接近2π的值紧接着接近0的值,反之,并进行补偿 注意,如果值以较大的增量变化,比如大于π,则跳转是不可恢复的
参见。确实有趣。α1/2有一点偏差,因为它在弦的分数α处构造点,而不是在弧的分数α处。但这是二阶效应。确实有趣。α1/2有一点偏差,因为它在弦的分数α处构造点,即s不完全在弧的分数α处,但这是二阶效应。