在树莓派上把「yaw/pitch/roll 序列」变成「画圈 / 画×」的 AI 分类器,整套流程可以塞进 4 步,全部用树莓派能装得下的轻量工具完成:


1 数据采集与打标签(树莓派本地完成)

  1. 沿用前面的 ESP32 → 串口 → 树莓派通路
  2. 写个简单采集脚本,每类动作录 1 条 .csv 即可起步:
# record.py
import serial, csv, time, sys
label = sys.argv[1]               # circle 或 cross
f     = open(f'{label}_{int(time.time())}.csv', 'w', newline='')
w     = csv.writer(f)
w.writerow(['y','p','r','t'])

ser = serial.Serial('/dev/ttyUSB0', 115200)
while True:
    line = ser.readline().decode(errors='ignore')
    if 'Y' in line and 'P' in line and 'R' in line:
        y, p, r = map(float, re.findall(r'[-\d.]+', line))
        w.writerow([y, p, r, time.time()])
        print(y, p, r)
    if input() == 'q': break
f.close()

运行示例

python record.py circle   # 拿板子画 10 个圈,按 q 停  
python record.py cross    # 画 10 个×

2 轻量特征工程(树莓派秒算)

对每段 3 轴序列提取 5 个统计特征,不用深度学习也能 95 %+ 准确率:

# feat.py
import pandas as pd, numpy as np, glob, re, pickle
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression

def feats(df):
    y, p, r = df.y, df.p, df.r
    return np.hstack([
        np.std([y, p, r], axis=1),      # 3 轴标准差
        np.ptp([y, p, r], axis=1),      # 峰-峰值
        np.sqrt(np.mean(y.diff()**2 + p.diff()**2 + r.diff()**2))  # 总能量
    ])

X, y = [], []
for fn in glob.glob('*.csv'):
    lbl = re.search(r'(\w+)_\d+.csv', fn).group(1)
    X.append(feats(pd.read_csv(fn)))
    y.append(0 if lbl == 'circle' else 1)   # 0=圈 1=×

pipe = Pipeline([('sc', StandardScaler()),
                 ('clf', LogisticRegression(max_iter=1000))])
pipe.fit(X, y)
with open('model.pkl', 'wb') as f:
    pickle.dump(pipe, f)
print('训练完成,保存 model.pkl')

树莓派 3B+ 上 100 条样本 < 1 秒训练完。


3 实时推理(边采集边识别)

把推理嵌进原来的 UDP/串口循环,每 1 s 滑窗识别一次:

# infer.py
import serial, pickle, pandas as pd, time, collections
model = pickle.load(open('model.pkl', 'rb'))
ser   = serial.Serial('/dev/ttyUSB0', 115200)
win   = collections.deque(maxlen=50)   # 50 帧≈1 s

def add(y, p, r):
    win.append([y, p, r])
    if len(win) == 50:
        df = pd.DataFrame(win, columns=['y', 'p', 'r'])
        prob = model.predict_proba([feats(df)])[0]
        print('circle %.2f  cross %.2f' % (prob[0], prob[1]))

while True:
    line = ser.readline().decode(errors='ignore')
    if 'Y' in line:
        y, p, r = map(float, re.findall(r'[-\d.]+', line))
        add(y, p, r)

运行后画圈 / 画×,终端实时输出概率。


4 想再玩大点?树莓派也能跑 TinyML

  1. 把同样特征流保存成 npy → 用 TensorFlow Lite Micro 训练 8KB 模型
  2. 导出 .tflite → 在树莓派 C++ 推理(甚至 ESP32 本地)
  3. Edge Impulse 一键生成树莓派 SDK,复制即可 make -j4

5 一键复盘(树莓派全命令)

sudo apt install python3-pip
pip3 install pandas scikit-learn pyserial
# 1 采集
python3 record.py circle
python3 record.py cross
# 2 训练
python3 feat.py
# 3 实时识别
python3 infer.py

10 分钟就能在树莓派上把「画圈 / 画×」用 yaw/pitch/roll 训练好并实时识别!