超声波测距三大算法实测对比

article/2025/7/2 6:19:37

前言

声波测距的数据包含很大噪声,即使障碍物(以纸板为例)静止,测量距离数据也上下跳变,需要通过数据滤波算法降低测量误差,主要滤波算法有平均值滤波和卡尔曼滤波。

在超声波测距中,无滤波、卡尔曼滤波和均值算法的核心区别在于对噪声的处理方式和对动态变化的适应能力。

  1. 无滤波算法
    直接输出原始测量值:每次测量直接返回超声波模块的原始数据(如时间差计算后的距离值)。
    无抗干扰能力:完全暴露于环境噪声(如温度变化、多路径反射、电磁干扰等)。
    实时性高:没有额外计算延迟。
    精度低:数据波动大,可能出现异常跳变(如突然出现极大或极小值)。
    稳定性差:在动态环境中(如移动物体或振动场景)容易产生误判。
    适用场景:仅适用于对精度要求极低的简单检测(如粗略判断障碍物是否存在)。

  2. 卡尔曼滤波算法
    基于系统模型的预测与更新:结合物理运动模型(如匀速假设)和测量值,动态调整估计。
    动态适应性:通过状态转移矩阵(F)和噪声协方差(Q, R)建模系统不确定性。
    抗噪声能力强:有效抑制高斯白噪声,平滑数据波动。
    精度高:滤波后数据更接近真实值,减少随机误差。
    动态响应好:在物体移动或环境变化时,能快速收敛到真实值。
    参数敏感:需要合理设置过程噪声(Q)和测量噪声(R)协方差矩阵。
    适用场景:适用于动态场景(如机器人避障、移动目标跟踪)。
    Q(过程噪声):表示系统模型的不确定性(如物体加速度变化)。值越大,滤波器越依赖新测量值。
    R(测量噪声):表示传感器本身的噪声水平。值越大,滤波器越信任模型预测。

  3. 均值算法(滑动平均滤波)
    简单平滑噪声:对连续N次测量值取平均,抑制随机噪声。
    无模型依赖:不考虑物理运动规律,仅通过统计学方法平滑数据。
    实现简单:适合资源受限的嵌入式系统。
    中等精度:能有效减少随机噪声,但无法处理系统性误差(如温度导致的声速变化)。
    延迟明显:对快速变化的动态响应差(如移动物体突然靠近)。
    适用场景:适用于静态或缓慢变化的场景(如液位监测、固定障碍物检测)。

一、无滤波算法

  1. 配置硬件:
    根据树莓派的引脚图选择设置GPIO23和GPIO24管脚,即图中BCM23和BCM24的位置,分别为16号和18号针脚。
    在这里插入图片描述
  2. 编写代码:
#导入 GPIO库
import RPi.GPIO as GPIO
import time#设置 GPIO 模式为 BCM
GPIO.setmode(GPIO.BCM)#定义 GPIO 引脚
GPIO_TRIGGER = 23
GPIO_ECHO = 24#设置 GPIO 的工作方式 (IN / OUT)
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)def distance():# 发送高电平信号到 Trig 引脚GPIO.output(GPIO_TRIGGER, True)# 持续 10 us time.sleep(0.00001)GPIO.output(GPIO_TRIGGER, False)start_time = time.time()stop_time = time.time()# 记录发送超声波的时刻1while GPIO.input(GPIO_ECHO) == 0:start_time = time.time()# 记录接收到返回超声波的时刻2while GPIO.input(GPIO_ECHO) == 1:stop_time = time.time()# 计算超声波的往返时间 = 时刻2 - 时刻1time_elapsed = stop_time - start_time# 声波的速度为 343m/s, 转化为 34300cm/s。distance = (time_elapsed * 34300) / 2return distanceif __name__ == '__main__':try:while True:dist = distance()print("Measured Distance = {:.2f} cm".format(dist))time.sleep(1)# Reset by pressing CTRL + Cexcept KeyboardInterrupt:print("Measurement stopped by User")GPIO.cleanup()
  1. 运行:

超声波测距原始算法

二、卡尔曼滤波算法

  1. 硬件搭建不变,仅将卡尔曼算法与原代码结合。
  2. 代码如下:
import RPi.GPIO as GPIO
import timeGPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)# 卡尔曼滤波参数
Q = 0.001  # 过程噪声方差(系统模型误差)
R = 0.1    # 测量噪声方差(传感器误差)
x_est = 0.0  # 初始估计值
P = 1.0    # 初始估计误差协方差def distance():GPIO.output(GPIO_TRIGGER, True)time.sleep(0.00001)GPIO.output(GPIO_TRIGGER, False)start_time = time.time()while GPIO.input(GPIO_ECHO) == 0:start_time = time.time()stop_time = time.time()while GPIO.input(GPIO_ECHO) == 1:stop_time = time.time()time_elapsed = stop_time - start_timereturn (time_elapsed * 34300) / 2def kalman_filter(z_measured):global x_est, P# 预测阶段x_pred = x_estP_pred = P + Q# 更新阶段K = P_pred / (P_pred + R)x_est = x_pred + K * (z_measured - x_pred)P = (1 - K) * P_predreturn x_estif __name__ == '__main__':try:while True:raw_dist = distance()filtered_dist = kalman_filter(raw_dist)print("Raw: {:.2f} cm, Filtered: {:.2f} cm".format(raw_dist, filtered_dist))time.sleep(0.1)except KeyboardInterrupt:print("Measurement stopped by User")GPIO.cleanup()
  1. 运行

超声波测距卡曼算法

三、均值滤波算法

  1. 硬件连接不变,仅修改代码算法。
  2. 代码如下:
import RPi.GPIO as GPIO
import timeGPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)# 卡尔曼滤波参数
Q = 0.001  # 过程噪声方差(系统模型误差)
R = 0.1    # 测量噪声方差(传感器误差)
x_est = 0.0  # 初始估计值
P = 1.0    # 初始估计误差协方差def distance():GPIO.output(GPIO_TRIGGER, True)time.sleep(0.00001)GPIO.output(GPIO_TRIGGER, False)start_time = time.time()while GPIO.input(GPIO_ECHO) == 0:start_time = time.time()stop_time = time.time()while GPIO.input(GPIO_ECHO) == 1:stop_time = time.time()time_elapsed = stop_time - start_timereturn (time_elapsed * 34300) / 2def kalman_filter(z_measured):global x_est, P# 预测阶段x_pred = x_estP_pred = P + Q# 更新阶段K = P_pred / (P_pred + R)x_est = x_pred + K * (z_measured - x_pred)P = (1 - K) * P_predreturn x_estif __name__ == '__main__':try:while True:raw_dist = distance()filtered_dist = kalman_filter(raw_dist)print("Raw: {:.2f} cm, Filtered: {:.2f} cm".format(raw_dist, filtered_dist))time.sleep(0.1)except KeyboardInterrupt:print("Measurement stopped by User")GPIO.cleanup()
wan@pi:/csb $ cat measure_avg.py
import RPi.GPIO as GPIO
import timeGPIO.setmode(GPIO.BCM)
GPIO_TRIGGER = 23
GPIO_ECHO = 24
GPIO.setup(GPIO_TRIGGER, GPIO.OUT)
GPIO.setup(GPIO_ECHO, GPIO.IN)# 定义缓冲区大小
BUFFER_SIZE = 8
distance_buffer = [0.0] * BUFFER_SIZE
buffer_index = 0def distance():GPIO.output(GPIO_TRIGGER, True)time.sleep(0.00001)GPIO.output(GPIO_TRIGGER, False)start_time = time.time()while GPIO.input(GPIO_ECHO) == 0:start_time = time.time()stop_time = time.time()while GPIO.input(GPIO_ECHO) == 1:stop_time = time.time()time_elapsed = stop_time - start_timedistance = (time_elapsed * 34300) / 2return distancedef apply_moving_average(new_distance):global buffer_index# 更新缓冲区distance_buffer[buffer_index] = new_distancebuffer_index = (buffer_index + 1) % BUFFER_SIZE# 计算平均值return sum(distance_buffer) / BUFFER_SIZEif __name__ == '__main__':try:while True:raw_dist = distance()filtered_dist = apply_moving_average(raw_dist)print("Raw: {:.2f} cm, Filtered: {:.2f} cm".format(raw_dist, filtered_dist))time.sleep(0.1)  # 提高采样频率以获取更稳定的数据except KeyboardInterrupt:print("Measurement stopped by User")
  1. 运行

超声波测距均值算法

四、读取超声波测距模块的ECHO和TRIG接口的波形

两者波形在时间上有所差异,TRIG波形快于ECHO波形,在波形形状上十分相似。

  1. TRIG波形
    在这里插入图片描述
  2. ECHO波形
    在这里插入图片描述

http://www.hkcw.cn/article/adtJmwMcRY.shtml

相关文章

【2025年5月】AI生产力再探再报:各家智能体持续内卷,前沿应用不断细分

前言 2025年5月的个人学习笔记。 一、工具尝鲜快报:初探感觉好玩,但还未深入的工具。 二、生产力军火库:开箱即用的神器,以及一些好用的技巧。 三、前沿动态速递:一些可反复品读的优质资料和个人感兴趣的新工具。 文章…

ubuntu22.04安装megaton

前置 sudo apt-get install git cmake ninja-build generate-ninja安装devkitPro https://blog.csdn.net/qq_39942341/article/details/148388639?spm1001.2014.3001.5502 安装cargo https://blog.csdn.net/qq_39942341/article/details/148387783?spm1001.2014.3001.5501 …

shell脚本的条件测试

命令结果判定 && :在命令执行后如果没有任何报错时会执行符号后面的动作 || :在命令执行后如果命令有报错会执行符号后的动作 条件判断 # test 语句 # [],[[]],(()) 语句 # [[]] 可以支持的表达式更多,是最常…

已有的前端项目打包到tauri运行(windows)

1.打包前端项目产生静态html、css、js 我们接下来用vue3 vite编写一个番茄钟案例来演示。 我们执行npm run build 命令产生的dist目录下的静态文件。 2.创建tarui项目 npm create tauri-applatest一路回车,直到出现。 3.启动运行 我们将打包产生的dist目录下的…

随记 nacos + openfegin 的远程调用找不到服务

这里的配置问题就不说了,基本的都没有问题,然后现在的是怎么样的场景呢,就是有两台服务器,两台服务器分别部署了两个模块,B要调用A服务,然后通过nacos找到了这个服务的名称,但是呢发现连不上&am…

【Python 算法零基础 4.排序 ⑦ 桶排序】

草木不争高,争的是生生不息 —— 25.5.26 选择排序回顾 ① 遍历数组:从索引 0 到 n-1(n 为数组长度)。 ② 每轮确定最小值:假设当前索引 i 为最小值索引 min_index。从 i1 到 n-1 遍历,若找到更小元素&am…

天机学堂-分页查询

需求 分页查询我的课表 返回: 总条数、总页数、当前页的课表信息的集合 返回的VO(已经封装成统一的LearningLessonsVO) 定义Controller RestController RequestMapping("/lessons") RequiredArgsConstructor public class Lear…

Transformer 是未来的技术吗?

之前的文章中,聊了不少关于 Transformer 方面的内容: Transformer 中的注意力机制很优秀吗?-CSDN博客初探 Transformer-CSDN博客来聊聊Q、K、V的计算-CSDN博客 现在的大模型基本都是基于 Transformer 或者它的演进技术,那么&…

阿里云国际站,如何通过代理商邀请的链接注册账号

阿里云国际站:如何通过代理商邀请链接注册,解锁“云端超能力”与专属福利? 渴望在全球化浪潮中抢占先机?想获得阿里云国际站的海量云资源、遍布全球的加速节点与前沿AI服务,同时又能享受专属折扣、VIP级增值服务支持或…

[创业之路-404]:企业战略管理案例分析-战略执行-人才战略

一、概述 在BLM(业务领先模型)战略执行中,人才是核心模块和关键要素,其管理需紧密围绕战略目标展开,具体如下: 1. 人才战略与战略目标的对齐 关键任务分解:通过战略解码,将业务目…

C++11 : 智能指针

C11 : 智能指针 目录 C11 : 智能指针引言1. 智能指针的使用场景分析2. RALL和智能指针的设计思路3. C标准库智能指针的使用4. 智能指针的原理5. shared_ptr和weak_ptr5.1 shared_ptr循环引用问题5.2 weak_ptr 6. shared_ptr的线程安全问题7. C11和boost中…

嵌入式开发之STM32学习笔记day16

STM32F103C8T6 I2C通信协议 1 I2C简介 I2C(Inter-Integrated Circuit)是一种两线制的串行通信协议,广泛应用于微控制器与外围设备之间的数据传输,它支持多主多从的通信模式,允许多个设备连接在同一总线上,…

Redis数据类型操作命令

Redis通用命令 keys:查看符合模板的所有key 因为keys命令使用的是模糊查序,比较耗性能,由于有redis是单线程,因此在生成情况下不建议使用该命令。del:删除一个或者多个keyexists:判断一个key是否存在expi…

Leetcode 2123. 使矩阵中的 1 互不相邻的最小操作数

1.题目基本信息 1.1.题目描述 给你一个 下标从 0 开始 的矩阵 grid。每次操作,你可以把 grid 中的 一个 1 变成 0 。 如果一个矩阵中,没有 1 与其它的 1 四连通(也就是说所有 1 在上下左右四个方向上不能与其他 1 相邻)&#x…

STL解析——list的使用

目录 1.简介 2.构造函数 3.迭代器 3.1封装 3.2迭代器分类 4.排序性能 4.1链式与数组 4.2缓存读取 1.简介 STL容器中提供的list容器也是一种顺序容器,底层实现方式是带头双向链表,这种实现方式能比单链表更高效的访问数据。 下面围绕部分重要接口…

数据库系统概论(十一)SQL 集合查询 超详细讲解(附带例题表格对比带你一步步掌握)

数据库系统概论(十一)SQL 集合查询 超详细讲解(附带例题表格对比带你一步步掌握) 前言一、什么是集合查询?二、集合操作的三种类型1. 并操作2. 交操作3. 差操作 三、使用集合查询的前提条件四、常见问题与注意事项五、…

数学建模期末速成 最短路径

关键词:Dijkstra算法 Floyd算法 例题 已知有6个村庄,各村的小学生人数如表所列,各村庄间的距离如图所示。现在计划建造一所医院和一所小学,问医院应建在哪个村庄才能使最远村庄的人到医院看病所走的路最短?又问小学建…

MonitorSDK_监测用户行为(点击、页面路由变化、页面浏览量变化)

点击事件监测 为了实现用户点击事件的监控和数据埋点,可以通过监听全局的 mousedown 和 touchstart 事件,收集用户交互数据,并将其上报到服务器。 export default function onClick(){[mousedown, touchstart].forEach( eventType > { …

NE555输出PWM驱动NMOS控制灯光电路Multisim仿真

仿真电路: 遇到的一些问题: 1、NE555怎么产生PWM波形? 解: 555定时器频率计算器_555定时器频率在线计算_电路参数计算 - 电子发烧友(www.elecfans.com) 这个在线工具可以通过设定频率、占空比、电阻,从而求出电阻值…

ThinkPrune:在RL中引入长度限制,在保持性能一致或略有提升下,显著提升推理效率

摘要:我们提出了THINKPRUNE,这是一种简单而有效的方法,用于缩短长思考型大语言模型(LLMs)的思考长度。这些模型被发现常常会产生低效且冗余的思考过程。现有的关于减少思考长度的初步探索主要集中在迫使思考过程提前结…