You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 15:05:23