RPLidar A1M8运行Matplotlib绘图时出现缓冲区及描述符字节异常
RPLidar A1M8 采集数据报错:Incorrect descriptor starting bytes
问题现象
通过USB连接RPLidar A1M8,使用Python结合Matplotlib持续采集激光雷达数据并绘制散点图,程序初始可正常输出约25组坐标数据,但随后触发解析错误。
正常输出示例
x is -424.2619428142333 y is -103.69361783394488 x is -425.2488450237623 y is -113.94508460638478 x is -426.76680234448065 y is -122.49937312764901 x is -428.54349054785354 y is -132.29787114334755 x is -429.7437088814488 y is -142.4882703130912 x is -430.94972519517984 y is -154.32885943399893 x is -433.00149846184235 y is -163.239899625671 x is -433.649229732051 y is -174.65564849955132 x is -434.9438784567277 y is -185.8838954643981 x is -436.894825594578 y is -196.37696241841425 x is -439.7883509307727 y is -205.66102301017438
错误信息
Too many bytes in the input buffer: 4030/3000. Cleaning buffer... Traceback (most recent call last): File "/home/garb/TESTING/lidar_testing/plotting.py", line 24, in <module> for scan in enumerate(lidar.iter_scans()): File "/usr/local/lib/python3.10/dist-packages/rplidar.py", line 446, in iter_scans for new_scan, quality, angle, distance in iterator: File "/usr/local/lib/python3.10/dist-packages/rplidar.py", line 394, in iter_measures self.start(self.scanning[2]) File "/usr/local/lib/python3.10/dist-packages/rplidar.py", line 319, in start status, error_code = self.get_health() File "/usr/local/lib/python3.10/dist-packages/rplidar.py", line 279, in get_health dsize, is_single, dtype = self._read_descriptor() File "/usr/local/lib/python3.10/dist-packages/rplidar.py", line 216, in _read_descriptor raise RPLidarException('Incorrect descriptor starting bytes') rplidar.RPLidarException: Incorrect descriptor starting bytes
原代码
from rplidar import RPLidar from pprint import pprint import csv from math import sin, cos, radians lidar = RPLidar('/dev/ttyUSB0') from math import sin, cos, radians import time import numpy as np import matplotlib.pyplot as plt def polar2cart(angle, distance): length = distance angle = angle angle = radians(angle) x,y = (length * cos(angle)), (length * sin(angle)) print('x is ', str(x) + ' y is ', str(y)) plt.xlim(-300, 300) plt.ylim(-300, 300) plt.scatter(x, y, color="black") plt.pause(0.05) for scan in enumerate(lidar.iter_scans()): list_version_data = list(scan) for data in list_version_data: if isinstance(data, list): for indiv_data_points in data: if isinstance(indiv_data_points, tuple): list_indiv_data_points = list(indiv_data_points) list_indiv_data_points.pop(0) # print(list_indiv_data_points) # Angle is first, distance is second # Angle is in degrees, distance is in mm angle = list_indiv_data_points[0] distance = list_indiv_data_points[1] polar2cart(angle, distance) elif isinstance(data, int): print("int") if KeyboardInterrupt: lidar.stop() lidar.stop_motor() lidar.disconnect() scan() plt.show()
解决方案
1. 核心问题:缓冲区溢出
报错根源是数据处理速度跟不上雷达输出速度:原代码逐点调用Matplotlib绘制,加上冗余的类型判断,导致串口缓冲区堆积,最终触发协议解析错误。
2. 针对性优化措施
- 批量绘制数据:收集整帧扫描数据后一次性转换并绘制,大幅减少Matplotlib调用开销
- 简化数据遍历逻辑:移除不必要的类型判断,直接提取扫描数据中的角度和距离
- 修复异常处理:用
try-except正确捕获键盘中断,确保雷达资源正常释放 - 增大缓冲区:初始化RPLidar时调整缓冲区大小,降低溢出概率
优化后的代码
from rplidar import RPLidar from math import sin, cos, radians import matplotlib.pyplot as plt import numpy as np def polar2cart(angles, distances): # 批量转换极坐标到笛卡尔坐标 angles_rad = np.radians(angles) x = distances * np.cos(angles_rad) y = distances * np.sin(angles_rad) return x, y def main(): # 初始化雷达,增大缓冲区避免溢出 lidar = RPLidar('/dev/ttyUSB0', buffer_size=8192) plt.ion() # 开启交互模式,支持动态更新 fig, ax = plt.subplots() ax.set_xlim(-300, 300) ax.set_ylim(-300, 300) scatter = ax.scatter([], [], color="black") # 初始化空散点图 try: # 遍历每帧扫描数据 for scan_num, scan_data in enumerate(lidar.iter_scans()): # 批量提取当前帧的角度和距离 angles = [point[1] for point in scan_data] distances = [point[2] for point in scan_data] # 转换坐标并更新散点图 x, y = polar2cart(angles, distances) scatter.set_offsets(np.column_stack((x, y))) plt.pause(0.01) # 缩短暂停时间,提升刷新率 except KeyboardInterrupt: print("Stopping lidar...") finally: # 确保雷达资源正确释放 lidar.stop() lidar.stop_motor() lidar.disconnect() plt.close() if __name__ == "__main__": main()
额外注意事项
- 确保串口权限:执行
sudo chmod 666 /dev/ttyUSB0避免权限不足问题 - 检查USB连接:使用短且质量好的USB线,减少信号干扰
- 关闭其他串口程序:避免多个进程占用同一串口
内容的提问来源于stack exchange,提问作者Garberchov
相关产品推荐
相关产品推荐

