搭建机器人电控系统——滤波算法——数据处理的十种滤波算法

滤波算法

我们需要精确的数据,但是数据回传并不完全准确时,比如十个数据里面有一个不正常时,我们就需要做滤波处理。不同滤波算法要结合实际情况来考虑,甚至有些时候需要自己写一个完全不同的以适应你的数据特征。以下介绍十种滤波的方法。


限幅滤波

方法:确定数据偏差的最大值MAX;求每次采样数据与上一次数据之差,若<=MAX则有效,若无效,则用上一次数据代替此次数据。
代码

1./* MAX值根据实际调,Value有效值,new_Value当前采样值,程序返回有效的实际值 */  
2.#define A 10  
3.char Value;  
4.char filter()  
5.{  
6.  char new_Value;  
7.  new_Value = get_ad();                             //获取采样值  
8.  if( abs(new_Value - Value) > MAX)   return Value;   //abs()取绝对值函数  
9.  return new_Value;  
10.}  

适用:有脉冲干扰的情形,无法抑制周期性干扰,平滑度差。


限幅平均滤波

方法:每次通过的数据先限幅滤波后再使用;取平均值。
代码

1.#define MAX 10  
2.#define N 12 //总数量  
3.char value,i=0;  
4.char value_buf[N];  
5.char filter()  
6.{  
7. char new_value,sum=0;  
8. new_value=get_ad();  
9. if(Abs(new_value-value)<MAX)  
10.  value_buf[i++]=new_value;  
11. if(i==N)i=0;  
12. for(count =0 ;count<N;count++)  
13.  sum+=value_buf[count];  
14. return (char)(sum/N);  
15.}  

适用:消除脉冲干扰,随机干扰,占用RAM资源较多。


中位值滤波

方法:连续采样N次,按大小排列;取中间值。
代码

1.#define N 11  
2.char filter()  
3.{  
4. char value_buf[N];  
5. char count,i,j,temp;  
6. for(count = 0;count < N;count++)         //获取采样值  
7. {  
8.  value_buf[count] = get_ad();  
9.  delay();  
10. }  
11. for(j = 0;j<(N-1);j++)  
12.  for(i = 0;i<(n-j);i++)  
13.  if(value_buf[i]>value_buf[i+1])  
14.  {  
15.   temp = value_buf[i];  
16.   value_buf[i] = value_buf[i+1];  
17.   value_buf[i+1] = temp;  
18.  }  
19. return value_buf[(N-1)/2];  
20.}  

适用:克服波动干扰,对变化缓慢的参数比较良好,不适用于速度变化快的参数。


中位值平均滤波

方法:采样N个值,去掉最大最小,计算平均值。
代码

1.char filter()  
2.{  
3. char count,i,j;  
4. char Value_buf[N];  
5. int sum=0;  
6. for(count=0;count<N;count++)  
7.  Value_buf[count]= get_ad();  
8. for(j=0;j<(N-1);j++)  
9.  for(i=0;i<(N-j);i++)  
10.   if(Value_buf[i]>Value_buf[i+1])  
11.   {  
12.     temp = Value_buf[i];  
13.     Value_buf[i]= Value_buf[i+1];  
14.      Value_buf[i+1]=temp;  
15.   }  
16.   for(count =1;count<N-1;count++)  
17.    sum += Value_buf[count];  
18.   return (char)(sum/(N-2));  
19.} 

适用:克服波动干扰(中位),随机误差(平均),脉冲干扰(限幅)。占用RAM资源较多。


算术平均滤波

方法:连续采样取平均值。
代码

1.#define N 12  
2.char filter()  
3.{  
4. int sum = 0;  
5. for(count = 0;count<N;count++)  
6.  sum += get_ad();  
7. return (char)(sum/N);  
8.}  

适用:采样数量较大时平滑度高、灵敏度低;数量少时平滑度低、灵敏度高。适用于存在随机干扰的情况,占用RAM资源较多。


递推平均滤波

方法:取N个值,形成队列,先进先出,取平均值。
适用:随机干扰的系统,占用RAM较多。


加权平均递推滤波

方法:对不同时刻采样的数据加以不同的权重,如越新的数据权重越大,这样灵敏度比较高,但平滑度低。
代码

1./* coe数组为加权系数表 */  
2.#define N 12  
3.char code coe[N]={1,2,3,4,5,6,7,8,9,10,11,12};  
4.char code sum_coe={1+2+3+4+5+6+7+8+9+10+11+12};  
5.char filter()  
6.{  
7. char count;  
8. char value_buf[N];  
9. int sum=0;  
10. for(count=0;count<N;count++)  
11. {  
12.  value_buf[count]=get_ad();  
13. }  
14. for(count=0;count<N;count++)  
15.  sum+=value_buf[count]*coe[count];  
16. return (char)(sum/sum_coe);  
17.}  

适用:如果以后进数据权重较大,那么适用于滞后系统、采样周期短系统,对变化慢的信号不能迅速反应。


一阶滞后滤波(低通滤波)

方法:在本次采样数据和上次数据之间分配不同的信任度(信任度从0到1),也可以是观测数据和你理论计算数据之间分配不同的信任度。
代码

1./*为加快程序处理速度,取a=0~100*/  
2.#define a 30  
3.char value;  
4.char filter()  
5.{  
6. char new_value;  
7. new_value=get_ad();  
8. return ((100-a)*value + a*new_value);  
9.}  

适用:适用于干扰频率较高的场合,但灵敏度低,相位滞后。


限幅消抖滤波

方法:对采样的数据先进行限幅。将采样值和当前值比较,若采样值=当前值,则计数器清零,若采样值不等于当前值,则计数器加一。最终若计数器溢出,则用采样值替换当前值,计数器清零。
代码

1.#define MAX 10  
2.#define N 12  
3.char value;  
4.char filter()  
5.{  
6. char new_value,count=0;  
7. new_value=get_ad();  
8. while(value!=new_value)  
9. {  
10.  if(Abs(value-new_value)<MAX)  
11.  {  
12.  count++;  
13.  if(count>=N) return new_value;  
14.  new_value=get_ad();  
15.  }  
16. return value;  
17. }  
18.}  

适用:适用于变化慢的数据,不适用于变化快的数据,避免脉冲干扰(限幅)。


卡尔曼滤波

适用系统:线性高斯系统(将噪声的分布看成正态分布)。
方法:在理论计算值和观测值之间分配信任度(信任度A从0到1)。用上一次的最优结果得到理论计算的当前值,同时使用观测值修正当前值,得到最优结果。
在这里插入图片描述

我们把用上一次的最优结果得到理论计算的当前值的过程用状态方程来表示:
在这里插入图片描述

其中Wk为状态方程噪声(如环境的随机干扰,场面粗糙程度等),满足正态分布:
在这里插入图片描述

我们把使用观测值修正当前值的过程用观测方程来表示:
在这里插入图片描述

其中Vk为观测方程噪声(传感器返回的噪声),满足正态分布:
在这里插入图片描述

卡尔曼滤波的思路就是调整Q和R的参数值(和PID类似),从而让最终结果变得很好。

  • 2
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的模拟matlab代码,用于演示机器人利用粒子滤波算法搜寻核放射源的过程: ```matlab % 初始化机器人位置和方向 robot_pos = [0, 0]; % 机器人初始位置 robot_dir = 0; % 机器人初始方向 % 初始化粒子滤波器参数 num_particles = 1000; % 粒子数目 particle_pos = repmat(robot_pos, num_particles, 1); % 所有粒子位置都初始化为机器人位置 particle_weight = ones(num_particles, 1) / num_particles; % 所有粒子权重都初始化为相等 % 初始化核放射源位置和辐射强度 source_pos = [3, 4]; source_strength = 10; % 开始搜寻核放射源 for i = 1:100 % 测量当前位置处的辐射强度 measured_strength = measure_radiation(robot_pos, source_pos, source_strength); % 更新所有粒子的权重 for j = 1:num_particles particle_weight(j) = measure_radiation(particle_pos(j,:), source_pos, source_strength); end % 根据粒子的权重重新采样 [particle_pos, particle_weight] = resample_particles(particle_pos, particle_weight); % 根据粒子的位置和权重计算机器人的位置和方向 robot_pos = calculate_robot_pos(particle_pos, particle_weight); robot_dir = calculate_robot_dir(particle_pos, particle_weight); % 输出当前机器人位置和方向 disp(['机器人位置:(', num2str(robot_pos(1)), ',', num2str(robot_pos(2)), ')']); disp(['机器人方向:', num2str(robot_dir)]); end % 测量辐射强度的函数 function strength = measure_radiation(pos, source_pos, source_strength) distance = norm(pos - source_pos); % 计算机器人和核放射源的距离 strength = source_strength / distance^2; % 根据距离计算辐射强度,强度与距离的平方成反比 end % 粒子重采样函数 function [new_pos, new_weight] = resample_particles(pos, weight) num_particles = size(pos, 1); new_pos = zeros(num_particles, 2); new_weight = ones(num_particles, 1) / num_particles; % 使用轮盘赌法进行重采样 r = rand() / num_particles; c = weight(1); i = 1; for j = 1:num_particles u = r + (j-1) / num_particles; while u > c i = i + 1; c = c + weight(i); end new_pos(j,:) = pos(i,:); end % 重新赋值权重,使其相加为1 new_weight = new_weight / sum(new_weight); end % 根据粒子位置和权重计算机器人位置的函数 function pos = calculate_robot_pos(particle_pos, particle_weight) pos = sum(particle_pos .* particle_weight) / sum(particle_weight); end % 根据粒子位置和权重计算机器人方向的函数 function dir = calculate_robot_dir(particle_pos, particle_weight) dir = atan2(sum(sin(particle_dir) .* particle_weight), sum(cos(particle_dir) .* particle_weight)); end ``` 这个代码模拟了一个简单的机器人搜寻核放射源的过程。在每个时刻,机器人会测量当前位置处的辐射强度,并根据粒子滤波算法更新自己的位置和方向。通过重复这个过程,机器人最终可以找到核放射源的位置。当然,这个代码只是一个简单的演示,实际的机器人搜寻任务要涉及更多的复杂性和技术细节。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值