第八篇,滤波:二阶低通滤波、卡尔曼滤波

article/2025/10/21 11:13:25

目录

1.引言

2.理解与demo

2.1 二阶低通滤波

2.1.1 LP_2Order的个人理解

2.1.2 refer

2.1.3 demo

2.2 卡尔曼滤波

2.2.1 理解

2.2.2 refer 

2.2.3 卡尔曼滤波的几个tips

2.2.4 demo

3.其它


1.引言

相比于上一篇,这篇会写的简单很多,可能因为难度略低吧。

还是工程化,不大篇幅抄理论,直接上可落地的干货。

2.理解与demo

2.1 二阶低通滤波

2.1.1 LP_2Order的个人理解

低通滤波比较常用,原理不甚了了,至于为什么用二阶而不用一阶三阶一百阶,你懂的。

很容易理解也很容易做,照着公式写就行,下一节会给出参考链接。

要实现二阶低通滤波器,有几个很重要的概念,也是必要的参数,一定要掌握并知道怎么赋值,这些也是《自动控制原理》课程里讲到的传递函数里面的概念:

阻尼比epsilon、截止频率\omega _{c}、采样时间T

阻尼比一般就是0.707\approx \frac{\sqrt{2}}{2},截止频率看你想让不超过多大频率的信号通过了,采样时间就是你的功能的执行周期。

要特别注意的是,这里边提到的频率,包括matlab中的实现,都是rad制,而通常我们拿到的都是s制的采样时间T或者Hz制的频率f,这里要注意做转换:

\omega =2\pi f=2\pi /T

看下matlab中的sine wave模块,注意Frequency参数那里的单位是rad/sec,所以你如果想要个10Hz或者叫周期0.1s的正弦波,你得按图里我那样写:2*pi*10。

 

2.1.2 refer

下面几个链接是二阶的理论推导还有人家写的demo代码,借鉴度很高,致谢。

二阶滤波器原理及算法程序_tuxinbang1989的博客-CSDN博客_二阶滤波算法

数字二阶低通滤波器公式推导及代码实现_苏箭的博客-CSDN博客_二阶低通滤波器公式

2.1.3 demo

代码奉上,很简单,对着上边的讲解一看便知。

function y = fcn_filter_Order2(x, omega_c, epsilon, Tsw)
%二阶低通滤波器,采样频率50Hz,截止频率暂定f=50Hz
%ω=2*pi*fb0 = omega_c*omega_c * Tsw*Tsw;
a0 = b0 + 4*epsilon*omega_c*Tsw + 4;
a1 = 2*b0 - 8;
a2 = b0 - 4*epsilon*omega_c*Tsw + 4;persistent p_x;
if isempty(p_x)p_x = zeros(2,1);
endpersistent p_y;
if isempty(p_y)p_y = zeros(2,1);
endy = (b0*x + 2*b0*p_x(1) + b0*p_x(2) - a1*p_y(1) - a2*p_y(2)) / a0;p_x(2) = p_x(1);
p_x(1) = x;p_y(2) = p_y(1);
p_y(1) = y;

2.2 卡尔曼滤波

2.2.1 理解

kalman filter,神一般的存在,究其本质也是一种低通滤波,甚至极端场景下退化成加权平均,所以不用害怕,花时间啃一啃就懂了。

首先,经典五部曲奉上:

  1. 第一步,利用上一次的KF结果,根据模型预测/估计当前状态。这个是篇理论的模型计算,要对功能建模的,比如经典的s=s_{0}+v_{0}t+\frac{1}{2}at^{2},一定要有个这样的公式,哪怕近似也要近似个出来,把AB矩阵造出来;
  2. 利用上一次的KF协方差计算当前预测/估计协方差
  3. 利用步骤2得到的协方差更新KF增益K,图中公式3、4的顺序颠倒了,怎么可能KF都完了才去计算K;
  4. 利用步骤3得到的KF增益K,结合步骤1里的预测/估计值和当前测量值,做滤波,本次卡尔曼滤波状态最优估计结束;这里有个测量的概念,就是对状态量一下子,比如步骤1里根据模型/公式估计出来走了1米,你噶尺子一量走了9.99米,这个9.99米就是测量值,这是现实世界中物理看得见摸得着的东西,不说人话叫“观测量”;
  5. 最后一步,为了下一循环能继续,需要更新本轮KF最优估计的协方差,over。

2.2.2 refer 

 参考1:卡尔曼滤波理论

卡尔曼滤波原理详解及系统模型建立(simulink)_Donald�的博客-CSDN博客_卡尔曼滤波simulink

参考2:C代码实现,一维版、矩阵版都有

卡尔曼(Kalman)滤波算法原理、C语言实现及实际应用_Beyonderwei的博客-CSDN博客_kalman算法卡尔曼滤波C语言实现(矩阵版)_Fly_Into_The_Sky的博客-CSDN博客_卡尔曼滤波c语言j​​​​​​​j​​​​​​​d卡尔曼(Kalman)滤波算法原理、C语言实现及实际应用_Beyonderwei的博客-CSDN博客_kalman算法

矩阵版这个NB大了,还有均匀分布随机数、正态分布随机数 ,可飨!

参考3:一个无敌的讲解,怎么就这么6! 

【卡尔曼滤波器】1_递归算法_Recursive Processing_哔哩哔哩_bilibili 

2.2.3 卡尔曼滤波的几个tips

  • 状态转移矩阵A、观测矩阵H,一般都是单位阵;
  • 初始建立,没有“上一次的KF协方差”,这时候差不多给个数就行了,别太大太小别是0,据说随着迭代的进行收敛很快,初值影响不大;
  • 对于某些场景,鉴于矩阵乘法的行列特性,B矩阵构造不出来可不予构造,因为B仅在估计的时候使用,可直接用相关公式计算,在其它几个KF算式中用不到B。

2.2.4 demo

为了提高通用性,做了个4维的demo ,不过没考虑控制。

function y = KalmanFilter(measure)
%卡尔曼滤波,通用矩阵形式,未考虑控制u
%measure为当前时刻新的观测值,y为本次KF输出
%维数先固定好dim = 4;persistent p_y;
if isempty(p_y)p_y = zeros(dim,1);
endpersistent p_p;
if isempty(p_p)p_p = eye(dim)*0.01;
end% A = eye(dim);
% B = zeros(dim,1);
% H = eye(dim);Q = eye(dim)*0.01;
R = eye(dim)*0.01;X_predict = p_y; % 公式1,根据上一步最优结果预测当前状态,A为单位阵,不考虑U
p_predict = p_p + Q; % 公式2,根据上一步最优结果的协方差计算当前预测状态协方差,Q为过程噪声协方差,A为单位阵
K = p_predict / (p_predict+R); % 公式3,计算KF增益K,测量矩阵H为单位阵,R为测量噪声协方差
y = X_predict + K*(measure-X_predict); % 公式4,计算最优输出,H为单位阵
p_p = (eye(dim)-K) * p_predict; % 公式5,计算本次最优结果的协方差,供下一步迭代使用
p_y = y; % 保存本次最优结果,供下一步迭代使用

3.其它

滤波的方法很多,经典的还有中值滤波什么的。

滤波的一大问题:实时滤波会带来相移(后处理没这个问题),时域上看滤波结果会比输入数据有延迟。以一维中值滤波为例,假定滤波窗口大小为5,做实时滤波,假设当前数据是x_{5},那么前边几帧的数据是x_{4}x_{3}x_{2}x_{1}x_{0}...,此时做滤波实际滤的是x_{3}不是x_{5},因为用到的数据是x_{1...5}, x_{3}才是中位数据,即延迟两帧,滤波窗口再大,比如我测试过31,很明显就能从波形图上看到一段滞后。

 

 

 


http://chatgpt.dhexx.cn/article/GmrGZTtV.shtml

相关文章

【模电】0007 有源滤波器2(二阶有源滤低通波器)

滤波器的阶数越高,则可以得到越陡峭的频率响应,使得在通带内尽量不衰减信号,而在阻带内尽可能多地衰减信号。 上一节我们讲的一阶有源滤波器,在对数坐标系上,其阻带内的衰减是20dB/十倍频程;如果想要更好的…

什么是二阶滤波器?有什么优点?

原文来自公众号:工程师看海 滤波器是常见的信号调理电路,其中低通滤波器最为普遍,我们常听说一阶滤波器、二阶滤波器,二者有什么差别呢? 低通滤波器有3个重要参数:通带、阻带和过度带,理想的滤…

【滤波器】5. 三种类型二阶低通滤波器

滤波器的品质因数 Q,也称为滤波器的截止特性系数。其值决定于 f f 0 ff_0 ff0​ 附近的频率特性。按照 f f 0 ff_0 ff0​ 附近频率特性的特点,可将滤波器分为 巴特沃斯 ( Butterworth)、切比雪夫(Chebyshev) 和 贝塞尔(Bessel) 三种类型。下图是这三种…

二阶低通有源滤波器设计与仿真测试

前言 传感器输出的测量信号中,除了有用的信息外,往往还包含许多噪声以及其他与被测量无关的信号,从而影响测量精度。这冲噪声般随机性很强,难于从时域中直分离出来,但限于其产生的物理机理、噪声功率是有限的&#xf…

带农历万年历C语言程序,c语言万年历程序代码

本篇文章介绍了使用c语言实现万年历程序的代码,希望对学习c语言的朋友有帮助! c语言万年历程序代码 C语言实现万年历程序的代码如下:#include int year(int y) { if ((y%40) && (y%100!0) || y%4000) return 366; else return 365; …

Java万年历程序

【程序说明】该程序实现了输出任意一年的日历,并输出该年中任意一天是该年的第几周。 【规定】①闰年366天,2月29天;平年365天,2月28天。 ②周日为某月的第一天,周六为该月的最后一天。 ③某年的1月1号为该年的第一天…

Java 实现万年历

通过Java的基本语法来实现我们的万年历 请看代码 public class CalDate{public static void main(String[] args){Scanner sc new Scanner(System.in);System.out.println("请输入年:");int year sc.nextInt();System.out.println("请…

C++万年历程序

C万年历 文章目录 C万年历一、运行结果二、源代码 一、运行结果 二、源代码 #include<iostream> #include<stdio.h> #include<string.h> #include<iomanip> using namespace std;class Calendar{ public :Calendar(){TotalDays 0;MonthDays 0;};voi…

编写万年历程序时的一些意外收获

前些天在CSDN每日一练上做到了万年历程序的一道题&#xff0c;觉得很有意思&#xff0c;于是便尝试自己写写看&#xff0c;结果遇到了“公元1年1月1日是星期几”这个问题。拿着手机翻华为日历翻了半天&#xff0c;找到了这一天是星期六&#xff1a; 然而我发现&#xff0c;根据…

C语言编写小程序——万年历

一、杂谈 大一学了C之后一直困惑&#xff0c;C到底怎么用&#xff1f;它不像HTML那么直观&#xff0c;也没有SQL那么常用&#xff0c;更没有Java那么功能强大&#xff0c;那他为何还存在&#xff0c;并依然火热呢&#xff1f; 答案很简单&#xff1a;编程语言是一家&#xff0c…

前端:运用js制作一个万年历程序

前端&#xff1a;运用js制作一个万年历程序 1.HTML代码 首先&#xff0c;依旧是一个套路&#xff0c;先写HTML代码&#xff0c;就好比如建一座楼先建地基和楼的结构一样。 外部这个class属性值为time的div标签是为了让整个内容处于居中地位。 class属性值为head1的div标签是…

用Java写一个万年历程序

从控制台输入指定年份&#xff08;在1900年至2099年之内&#xff09;和月份&#xff0c;输出当月的日历。要求效果如下图所示 思路分析如下&#xff1a; 假设输出2020年5月份的日历。那么要求得1900年1月1日到2020年5月1日前一天的天数总和 再求总天数余7的值&#xff0c;结果…

C++编写万年历,公元后日历程序,考虑了1582年前后以及该年的特殊情况。

目录 一&#xff0c;万年历的基本要求前言&#xff1a;万年历的创建思路1.公元天数与日期1.日期输入问题2.闰年与平年的数目 3.日历的输出问题1.日数转化为星期2.日历月份开头 二&#xff0c;万年历正确性的额外补丁1.1582年闰年定义的变更解决2.1582年消失的十天 三&#xff0…

C语言 万年历 三种版本

C语言 万年历 万年历 一、第1版&#xff1a; 制作一个万年历&#xff08;阳历版&#xff09;。程序从键盘读入年份和月份&#xff0c;然后输出该年该月的月历。 【实现提示】&#xff1a; 本问题的关键是确定所求月份的第一天是星期几。如我们想确定2009年12月1日是星期几&a…

编制万年历的历程

初入编程之道的学子大都试编过万年历。万年历有二种&#xff1a;一为只有西历的月历&#xff0c;另一为有农历对照的月历或日历。编写万年历程序可以练练手&#xff0c;加深对编程语言的理解。记得我初入此道是在1994年&#xff0c;我那时刚买了486电脑&#xff0c;也刚开始有视…

显示万年历的程序(汇编语言实现,附源代码)

运行环境&#xff1a;Masm for Windows 集成实验环境 2015 一、课题内容和要求 课题内容&#xff1a; 用汇编语言编写一个有简单界面显示的日历&#xff0c;要求输入年月日后&#xff0c;将该月的完整日历显示出来&#xff0c;包括星期几&#xff0c;且每月的星期六&#xff…

c语言编写万年历程序

这个程序最核心的地方在于计算当前日期是周几&#xff0c;然后才好显示万年历&#xff0c;因为输入只知道月&#xff0c;所以默认是1号。 通过这个日期我们就可以计算总天数&#xff0c;通过总天数进行%7运算&#xff0c;就能得到周几。 通过这个周几&#xff0c;在结合这个月有…

C语言实现万年历程序

C语言实现万年历程序 #include <stdio.h>int year(int y) {if ((y%40) && (y%100!0) || y%4000)return 366;elsereturn 365; }int main() {int y;int i,j,sum0; int begin,week;int days[12]{31,28,31,30,31,30,31,31,30,31,30,31};scanf("%d",&y)…

C语言实现万年历(附代码) 小白完成的第一个C语言程序,希望大家多多关注,点赞

C语言实现万年历 前言&#xff1a;本文章向大家介绍如何使用C语言代码实现万年历使用实例&#xff0c;讲解编写万年历的方法&#xff0c;教你轻松学会写出万年历。这个小程序算是我自己写的第一个比较完整的小程序&#xff0c;算是对大一上学期学习的C语言程序设计基础的一个总…

万年日历(C语言)

C Language 万年历程序----&#xff08;1840~2110&#xff09;年 ##声明&#xff1a;此程序并非本人全原创&#xff0c;已修改其中少数内容&#xff0c;仅供小白参考&#xff0c;大佬者若言论&#xff0c;来吧&#xff0c;用点力——后续本人将更新此万年历添加更有丰富的内容…