工程算法的知识与拓展
1 一阶低通滤波(IIR)
$$Y(n) = \alpha X(n)+(1-\alpha)Y(n-1)$$
其中 $Y(n)$ 表示当前系统的输出,$X(n)$ 则为系统当前的输入;$\alpha\in(0,1)$ 为滤波系数,而 $Y(n-1)$ 为前一次的输出。
1 | int filter_out; |
其中 filter_prev 对应前一次执行时的输出项,static 修饰保证了其能够继承 filter_prev = filter_out 的效果,进行下一轮运算。
filter_coeff 即滤波系数,假设系统输入为 val ,那么 filter_out ,即当前系统输出的计算形式就对应上文中的公式。最后只需要更新 filter_prev 就可以了。
2 卡尔曼滤波
总体来说是一种预测-修正的过程,用上一次得到的最优结果做先验估计,然后根据实际测量的值对估计值进行修正,不对数学原理做过多探究。
2.1 预测
$$\hat{x_i^-}=F\hat{x_{i-1}}+B\hat{u_{i-1}}\space(Estimate)$$
预测模型表示,先验估计结果由上一次的 后验估计结果 以及上一时刻的 系统控制输入 组成,并且受到状态转移矩阵和控制输入矩阵的影响。
$$P_i^-=FP_{i-1}F^T+Q\space (Covariance\space Estimate)$$
协方差模型表示,预测阶段的误差协方差由 上一时刻的不确定性与 噪声协方差 组成。
2.2 更新(融合)
$$K_{i} = P_i^-H^T(HP_i^-H^T+R)^{-1}$$
卡尔曼增益的计算依赖 预测误差协方差、观测矩阵及其转置 以及 测量噪声协方差。
$$x_i = \hat{x_i^-} + K_i (z_i − H \hat{x_i^-})$$
得到后验估计结果。
$$P_i = (1 − K_i H) P_i^-$$
同时,更新后验的协方差以便下一次使用。
2.3 代码实现(一维卡尔曼)
一维的情况下,矩阵相关运算基本都简化了。
1 | typedef struct |
初始化滤波器结构体:
1 | void Kalman_Init(Kalman_t *filter, float Q, float R, float init_val) |
1 | float Kalman_Updata(Kalman_t *filter, float measurement) |
1 | Kalman_t filter; |
不难看出一维应用的场景下,确定 Q 和 R 也就是噪声项是比较重要的。
Q(过程噪声协方差):反映系统模型的不确定性
- Q越大,表示越不信任模型预测,更依赖测量值
- Q越小,表示模型很准确,滤波器响应较慢
R(测量噪声协方差):反映传感器测量的不确定性
- R越大,表示测量值不可靠,更依赖模型预测
- R越小,表示测量很准确,滤波器响应较快
一般可以在静态系统环境下记录多次传感器数据后记录方差作为 R 的参考值, 然后调节 Q (影响系统响应速度)的值来观察效果。
