智能车四种常见滤波和 MATLAB 仿真:一阶 RC 低通滤波,二阶 IIR 低通滤波,五阶 FIR 低通滤波,卡尔曼滤波

简介: 智能车四种常见滤波和 MATLAB 仿真:一阶 RC 低通滤波,二阶 IIR 低通滤波,五阶 FIR 低通滤波,卡尔曼滤波

四种常见滤波和 MATLAB 仿真:一阶 RC 低通滤波,二阶 IIR 低通滤波,五阶 FIR 低通滤波,卡尔曼滤波

开源代码地址: https://github.com/ittuann/Enterprise_E

博客目录:
https://blog.csdn.net/sorcererr/article/details/124989905
https://ittuann.github.io/2021/08/30/Car.html

一阶 RC 低通滤波

FilterData = cof * RawData + (1.000f - cof) * FilterData;

一阶 RC 低通滤波又叫一阶惯性滤波,因为本质上也是积分滤波器。

不能滤除频率高于采样频率的二分之一的干扰。

cof是一阶RC低通滤波参数,代表新采样值在滤波结果中的权重。

滤波系数越小,滤波结果越平稳,灵敏度越低。

滤波系数可以理解为对采样值的相信程度。

float Cof =  = 1.0 / (1.0 + (1.0 / 2Pi * T(s) * fc));

上面是cof的计算公式。但一阶 RC 低通滤波在实际情况也可以不按照公式计算的结果,用上位机比较原始值和滤波后数值波形来试凑出来一版系数也是可行的。

二阶 IIR 低通滤波

IIR 滤波公式:

$$ y_n=\frac{1}{b_0}\left(\sum_{k=0}^{n}{b_kx\left(n-k\right)}-\sum_{k=1}^{n}{a_kx\left(n-k\right)}\right) $$

或是

$$ y_{\left(n\right)}=b_0x_{\left(n\right)}+b_1x_{\left(n-1\right)}+\ldots+b_Mx_{\left(n-M\right)}-a_1y_{\left(n-1\right)}-\ldots-a_Ny_{\left(n-N\right)} $$

IIR滤波就是这个个方程。yn为输出数据,xn为输入数据,a和b为滤波器的系数。

C语言实现:

#define ORDER 2

typedef struct {
    float A[ORDER + 1];
    float B[ORDER + 1];
    float OriginData[ORDER + 1];
    float FilterData[ORDER + 1];
} LpfIIR2nd_t;

/**
 * @brief            二阶IIR低通滤波器
 * @param[out]        lpf : 滤波结构数据指针
 * @param[in]        rawData : 原始数据
 */
void LowPassFilterIIR2nd(LpfIIR2nd_t* lpf, float rawData)
{
    uint8_t i = 0;
    // 递推旧值
    for (i = ORDER; i > 0; i--) {
        lpf->OriginData[i] = lpf->OriginData[i - 1];
        lpf->FilterData[i] = lpf->FilterData[i - 1];
    }
    // 计算滤波结果
    lpf->OriginData[0] = rawData;
    lpf->FilterData[0] = lpf->B[0] * lpf->OriginData[0];    // NUM 分子
    for (i = 1; i <= ORDER; i++) {
        lpf->FilterData[0] = lpf->FilterData[0] + lpf->B[i] * lpf->OriginData[i] - lpf->A[i] * lpf->FilterData[i];
    }
}

最后计算滤波结果也可以写成

lpf->FilterData[0] = (lpf->B[0] * lpf->OriginData[0] + lpf->B[1] * lpf->OriginData[1] + lpf->B[2] * lpf->OriginData[2] - lpf->A[1] * lpf->FilterData[1] - lpf->A[2] * lpf->FilterData[2]) / lpf->A[0];

注意在使用滤波前要先初始化结构体的滤波系数。只需要初始化一次即可。

其中分子系数是成对出现的,可以先合并来提高运算效率。

也可以优化成int型或是用移位器和加法器来代替乘法。

滤波系数的计算:

/**
 * @brief    二阶 IIR 低通滤波
 *            APM 和 PX4 内的计算系数方式
 */
void AccLowpassIIR2Filter_E(void)
{
    const float sample_freq = 500;
    const float _cutoff_freq = 200;
    
    const float fr = sample_freq / _cutoff_freq;
    const float ohm = tanf(M_PI_F / fr);
    const float c = 1.0f + 2.0f * cosf(M_PI_F / 4.0f) * ohm + ohm * ohm;
    
    const float _b0 = ohm * ohm / c;
    const float _b1 = 2.0f * _b0;
    const float _b2 = _b0;
    const float _a1 = 2.0f * (ohm * ohm - 1.0f) / c;
    const float _a2 = (1.0f - 2.0f * cosf(M_PI_F / 4.0f) * ohm +ohm * ohm) / c;
    
//    lFilter[0] = Origin[0] * _b0 + Origin[1] * _b1 + Origin[2] * _b2 - Filter[1] * _a1 - Filter[2] * _a2;
}

滤波系数的计算也可以使用MATLAB仿真的方式计算:

打开 Matlab 在APP中选择 Filter Designer(fdatool)

img

  • 设计方法(Design Method)用于选择IIR滤波器还是FIR滤波器。这里我们选择IIR滤波器,类型选择Butterworth。当然也可以选择其他类型,不同类型的频率响应不同,选择后默认的滤波器结构是直接II型。
  • 响应类型(Response Type)用于选择低通、高通、带通、带阻等类型。这里选择选择低通(Lowpass)。
  • 频率设定(Frequency Specifications)用于设置采样频率以及截止频率,这里填入500以及50,即采样率为500Hz,50Hz以上的频率将被滤除掉。
  • 滤波器阶数(Fiter Order )选择指定滤波器阶数为二阶。
  • 参数设置好后点击设计滤波器(Design filter)按钮,将按要求设计滤波器。
  • 默认生成的IIR滤波器类型是直接Ⅱ型,每个Section是一个二阶滤波器(Direct-Form II, Second-Order Sections)。
  • 在工具栏上点击右数第五个滤波器系数(Filter Coefficients)图标,或菜单栏上选择分析(Analysis)→滤波器系数(Filter Coefficients),即可查看生成的滤波器系数。
  • 最后在菜单栏点击编辑(edit)→转换为二节点(Convert to Single Section),即是我们最终用的滤波器系数。在MATLAB里,IIR公式中的ab又分别叫做分子(Numerator)和分母(Denominator)。
  • 左边实现模型(Realize Model)还可以生成Simulink模型进行仿真。

五阶 FIR 低通滤波

FIR 滤波公式:

$$ y_{(n)}=\sum_{k=0}^{N-1}{k_{(k)}x_{(n-k)}} $$

FIR滤波就是这个个方程。x(n)为输入信号,k(n)为FIR滤波系数,y(n)为经过滤波后的信号;N表示FIR滤波器的抽头数,滤波器阶数为N-1。

C语言实现:

#define ORDER 5

void FIR5Filter(void)
{
    const float H[ORDER + 1] = {...};
    
    Filter[0] = 0;
    for (uint16_t j = 0; j < ORDER + 1; j++) {
         Filter[0] += H[j] * Origin[j];
    }
}

滤波系数的计算:

  • FIR滤波器设计方法有多种,如图4所示,最常用的是窗函数设计法(Window)、等波纹设计法(Equiripple)和最小二乘法 (Least-Squares)等。
  • 设置频率响应的参数,包括采样频率Fs、通带频率Fpass和阻带频率Fstop
  • 可以使用ARM官方DSP库实现FIR和IIR滤波,提高运行速度和效率。

卡尔曼滤波

算法的思想是,根据当前的仪器"测量值" 和上一刻的 "预测量" 和 "误差",计算得到当前的最优量,再预测下一刻的量。卡尔曼滤波器就是一个带有预测功能的低通滤波器。

一维卡尔曼滤波C语言实现:

typedef struct {
    float x;        // state
    float A;        // x(n)=A*x(n-1)+u(n),u(n)~N(0,q)
    float H;        // z(n)=H*x(n)+w(n),w(n)~N(0,r)
    float q;        // process(predict) noise convariance
    float r;        // measure noise(error) convariance
    float p;        // estimated error convariance
    float gain;        // kalman gain
} kalman1_filter_t;


/**
 * @brief            一阶卡尔曼滤波初始化
 * @param[out]        state : 滤波结构数据指针
 * @param[in]        q & r
 */
void kalman1_init(kalman1_filter_t *state, float q, float r)
{
    state->x = 0.0f;
    state->p = 0.0f;
    state->A = 1.0f;
    state->H = 1.0f;
    state->q = q;
    state->r = r;
}

/**
 * @brief            一阶卡尔曼滤波
 * @param[out]        state : 滤波结构数据指针
 * @param[in]        z_measure : 原始数据
 */
float kalman1_filter(kalman1_filter_t *state, float z_measure)
{
    /* Predict */
    // 时间更新(预测): X(k|k-1) = A(k,k-1)*X(k-1|k-1) + B(k)*u(k)
    state->x = state->A * state->x;
    // 更新先验协方差: P(k|k-1) = A(k,k-1)*A(k,k-1)^T*P(k-1|k-1)+Q(k)
    state->p = state->A * state->A * state->p + state->q;

    /* Measurement */
    // 计算卡尔曼增益: K(k) = P(k|k-1)*H(k)^T/(P(k|k-1)*H(k)*H(k)^T + R(k))
    state->gain = state->p * state->H / (state->p * state->H * state->H + state->r);
    // 测量更新(校正): X(k|k) = X(k|k-1)+K(k)*(Z(k)-H(k)*X(k|k-1))
    state->x = state->x + state->gain * (z_measure - state->H * state->x);
    // 更新后验协方差: P(k|k) =(I-K(k)*H(k))*P(k|k-1)
    state->p = (1 - state->gain * state->H) * state->p;

    return state->x;
}
  • 一维卡尔曼滤波全部是标量计算
  • R固定,Q越大,代表越信任侧量值,Q无穷代表只用测量值(Q/R取0无意义)Q/R决定了滤波器的稳态频率响

    应。Q增大和R减小都会导致卡尔曼增益K变大

  • 测量噪声大 R需要设置的较大
  • 模型不准确 Q需要增大
  • 卡尔曼增益的值越大,意味着越相信测量值的输出,从而使得估计值倾向于测量值,收敛速度越快,最优估计值震荡越明显
  • A B H 根据模型来确定
  • P变大也会导致卡尔曼增益变大,但是很快会迭代至稳定值,因此P的初始值只会对前几个周期的估计值有影响。
  • 二维及以上的卡尔曼滤波运算过程涉及到大量的矩阵运算,如果将矩阵运算拆开成基本的四则运算扩展性很差,并且在遇到例如求逆运算的时候比较麻烦。可以使用ARM的DSP库里面的矩阵运算功能
目录
相关文章
|
数据可视化
基于MATLAB的OFDM调制发射与接收仿真
基于MATLAB的OFDM调制发射与接收仿真
|
12月前
|
5G
基于IEEE 802.11a标准的物理层MATLAB仿真
基于IEEE 802.11a标准的物理层MATLAB仿真
579 0
|
12月前
|
算法
基于MATLAB/Simulink平台搭建同步电机、异步电机和双馈风机仿真模型
基于MATLAB/Simulink平台搭建同步电机、异步电机和双馈风机仿真模型
1253 30
|
12月前
|
机器学习/深度学习 算法 数据可视化
基于MVO多元宇宙优化的DBSCAN聚类算法matlab仿真
本程序基于MATLAB实现MVO优化的DBSCAN聚类算法,通过多元宇宙优化自动搜索最优参数Eps与MinPts,提升聚类精度。对比传统DBSCAN,MVO-DBSCAN有效克服参数依赖问题,适应复杂数据分布,增强鲁棒性,适用于非均匀密度数据集的高效聚类分析。
|
12月前
|
开发框架 算法 .NET
基于ADMM无穷范数检测算法的MIMO通信系统信号检测MATLAB仿真,对比ML,MMSE,ZF以及LAMA
简介:本文介绍基于ADMM的MIMO信号检测算法,结合无穷范数优化与交替方向乘子法,降低计算复杂度并提升检测性能。涵盖MATLAB 2024b实现效果图、核心代码及详细注释,并对比ML、MMSE、ZF、OCD_MMSE与LAMA等算法。重点分析LAMA基于消息传递的低复杂度优势,适用于大规模MIMO系统,为通信系统检测提供理论支持与实践方案。(238字)
|
监控
基于MATLAB/Simulink的单机带负荷仿真系统搭建
使用MATLAB/Simulink平台搭建一个单机带负荷的电力系统仿真模型。该系统包括同步发电机、励磁系统、调速系统、变压器、输电线路以及不同类型的负荷模型。
1656 5
|
传感器 资源调度 算法
【数据融合】【状态估计】基于KF、UKF、EKF、PF、FKF、DKF卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波数据融合研究(Matlab代码实现)
【数据融合】【状态估计】基于KF、UKF、EKF、PF、FKF、DKF卡尔曼滤波KF、无迹卡尔曼滤波UKF、拓展卡尔曼滤波数据融合研究(Matlab代码实现)
1134 0
|
机器学习/深度学习 边缘计算 算法
【无人机】无人机群在三维环境中的碰撞和静态避障仿真(Matlab代码实现)
【无人机】无人机群在三维环境中的碰撞和静态避障仿真(Matlab代码实现)
493 0
|
12月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
900 0
|
12月前
|
算法 定位技术 计算机视觉
【水下图像增强】基于波长补偿与去雾的水下图像增强研究(Matlab代码实现)
【水下图像增强】基于波长补偿与去雾的水下图像增强研究(Matlab代码实现)
1185 0

热门文章

最新文章