在树莓派上把「yaw/pitch/roll 序列」变成「画圈 / 画×」的 AI 分类器,整套流程可以塞进 4 步,全部用树莓派能装得下的轻量工具完成:
1 数据采集与打标签(树莓派本地完成)
- 沿用前面的 ESP32 → 串口 → 树莓派通路
- 写个简单采集脚本,每类动作录 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
- 把同样特征流保存成
npy
→ 用 TensorFlow Lite Micro 训练 8KB 模型 - 导出
.tflite
→ 在树莓派 C++ 推理(甚至 ESP32 本地) - 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 训练好并实时识别!