mirror of
https://github.com/m1ngsama/robot_arm.git
synced 2026-03-25 19:53:49 +00:00
254 lines
8.3 KiB
Markdown
254 lines
8.3 KiB
Markdown
# 智能语音机械臂
|
||
|
||
基于"耳-脑-眼-手"全链路闭环的具身智能系统,运行于消费级硬件,完全离线。
|
||
|
||
[English](README_EN.md)
|
||
|
||
---
|
||
|
||
## 系统简介
|
||
|
||
| 能力 | 实现 |
|
||
|:---|:---|
|
||
| **听** | Faster-Whisper,本地中文语音识别 |
|
||
| **想** | DeepSeek-R1-1.5B + QLoRA 微调,自然语言 → JSON |
|
||
| **看** | YOLOv8s 目标检测 + 单应性矩阵手眼标定 |
|
||
| **动** | D-H 逆运动学 + S-Curve 轨迹规划,ESP32 驱动 |
|
||
|
||
硬件总成本 **¥317**,GPU 需求 RTX 3060 6GB(推理 <4GB 显存,延迟 <200ms)。
|
||
|
||
---
|
||
|
||
## 系统架构
|
||
|
||
```mermaid
|
||
flowchart TD
|
||
MIC["🎤 麦克风"] --> STT["Faster-Whisper<br/>中文语音识别"]
|
||
STT --> RULE{"规则解析引擎<br/>简单指令匹配"}
|
||
RULE -- "命中" --> ACT["JSON 动作指令"]
|
||
RULE -- "未命中(含物体名)" --> LLM["DeepSeek-R1-1.5B<br/>QLoRA FP16<br/>自然语言 → JSON"]
|
||
LLM --> ACT
|
||
ACT --> VIS["YOLOv8s + Homography<br/>目标检测 · 手眼标定<br/>像素坐标 → 机械臂坐标 mm"]
|
||
VIS --> MOT["arm_main.py<br/>D-H IK + S-Curve"]
|
||
MOT --> ESP["ESP32 PWM → 舵机"]
|
||
```
|
||
|
||
---
|
||
|
||
## 硬件清单
|
||
|
||
总计 **¥317**
|
||
|
||
| # | 物品 | 规格 | 数量 | 单价 | 合计 |
|
||
|:--|:---|:---|:--:|---:|---:|
|
||
| 1 | 3D 打印机械臂(散件) | 教具级,含亚克力/PLA 结构件 | 1 | ¥71 | ¥71 |
|
||
| 2 | ESP32 开发板 | WiFi+蓝牙双核 MCU | 1 | ¥19 | ¥19 |
|
||
| 3 | ESP32 配件 | 接插件/扩展板 | 1 | ¥5 | ¥5 |
|
||
| 4 | USB 工业摄像头 | 免驱,广角,1280×720 | 1 | ¥61 | ¥61 |
|
||
| 5 | 数字舵机 MG996R | 金属齿轮,高扭矩 | 5 | ¥27 | ¥133 |
|
||
| 6 | 稳压电源 | 6V 6A,舵机专用 | 1 | ¥29 | ¥29 |
|
||
|
||
**硬件连接**
|
||
|
||
- **ESP32 引脚**:X→14, Y→4, Z→5, B→18, 夹爪→23
|
||
- **电源**:舵机与 ESP32 分开供电(外部 6V/6A),防浪涌
|
||
- **摄像头**:USB,固定于机械臂前方,覆盖整个工作台面
|
||
- **串口**:USB 连接 ESP32,默认 `COM3`,可通过 `ROBOT_PORT` 环境变量修改
|
||
|
||
---
|
||
|
||
## 安装
|
||
|
||
### 1. 烧录固件
|
||
|
||
Arduino IDE 2.x,开发板选 "ESP32 Dev Module",打开 `main.ino`,选择串口,点击上传。
|
||
|
||
### 2. Python 环境
|
||
|
||
Python 3.10+,CUDA 11.8 或 12.x。
|
||
|
||
```bash
|
||
# 先去 pytorch.org 安装对应 CUDA 版本的 PyTorch,再安装其余依赖
|
||
pip install -r requirements.txt
|
||
```
|
||
|
||
### 3. 配置
|
||
|
||
所有可调参数集中在 `config.py`,支持环境变量覆盖,无需修改代码:
|
||
|
||
```bash
|
||
ROBOT_PORT=COM5 python voice_main.py # 修改串口
|
||
LLM_MODEL_PATH=D:\models\lora python voice_main.py # 修改 LLM 路径
|
||
YOLO_MODEL_PATH=runs/best.pt python voice_main.py # 修改 YOLO 路径
|
||
```
|
||
|
||
### 4. 模型准备
|
||
|
||
**语音 (Whisper)**:首次运行自动下载 `base` 模型,无需准备。
|
||
|
||
**视觉 (YOLO)**:需自行训练,50 张样本即可迁移学习:
|
||
|
||
```bash
|
||
yolo detect train model=yolov8s.pt data=data.yaml epochs=100 imgsz=640
|
||
# 产出 runs/detect/train/weights/best.pt → 复制到项目根目录
|
||
```
|
||
|
||
**大模型 (LLM)**:需对 DeepSeek-R1-1.5B 或 Qwen1.5-1.8B 进行 LoRA 微调。完整流程见 [`TRAINING.md`](TRAINING.md)。
|
||
|
||
训练数据格式(Alpaca):
|
||
```json
|
||
{
|
||
"instruction": "把削笔刀抬起5厘米",
|
||
"input": "",
|
||
"system": "你是机械臂JSON转换器...",
|
||
"output": "[{\"action\": \"lift\", \"target\": \"part\", \"height\": 50}]"
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 快速上手
|
||
|
||
```bash
|
||
python voice_main.py
|
||
```
|
||
|
||
启动后依次加载:机械臂串口 → YOLO → Whisper → LLM,弹出摄像头窗口。
|
||
|
||
**键盘快捷键**
|
||
|
||
| 按键 | 功能 |
|
||
|:---|:---|
|
||
| **SPACE(按住)** | 录音,松开即识别 |
|
||
| **C** | 进入 / 退出手眼标定模式 |
|
||
| **R** | 手动复位到原始姿态 |
|
||
| **O** | 强制张开夹爪 |
|
||
| **Q** | 退出程序 |
|
||
|
||
---
|
||
|
||
## 语音指令
|
||
|
||
所有指令用普通中文说话即可,无需特殊格式。
|
||
|
||
**抓取与搬运(需视觉定位)**
|
||
```
|
||
"把削笔刀抓起来"
|
||
"抓住那个盒子"
|
||
"把削笔刀抬起5厘米"
|
||
"将零件举高10公分"
|
||
```
|
||
|
||
**空间运动控制(精确移动)**
|
||
```
|
||
"向上三厘米" → Z 轴 +30mm
|
||
"向左移动四毫米" → Y 轴 +4mm
|
||
"往前伸10厘米" → X 轴 +100mm
|
||
```
|
||
|
||
**模糊移动**(不指定数值,默认 5cm)
|
||
```
|
||
"向左" "抬起" "往下"
|
||
```
|
||
|
||
**动作交互**
|
||
```
|
||
"点头" → 当前位置上下往复 3 次(幅度 3cm)
|
||
"摇头" → 当前位置左右往复 3 次(幅度 3cm)
|
||
"放下" → 降至桌面高度(Z=-15mm)并松开夹爪
|
||
"复位" → 回到初始安全姿态 [120, 0, 60] mm
|
||
"松开" → 张开夹爪,不移动
|
||
```
|
||
|
||
**语音兼容性**:内置谐音纠错,如 `"零米"→"厘米"`、`"小笔刀"→"削笔刀"`、`"电头"→"点头"` 等。
|
||
|
||
---
|
||
|
||
## 手眼标定
|
||
|
||
摄像头移动后必须重新标定。按 **C** 键进入标定模式,依次点击 4 个角点:
|
||
|
||
```
|
||
P1(左上)←→ 机械臂坐标 (90, 90)
|
||
P2(右上)←→ 机械臂坐标 (200, 90)
|
||
P3(右下)←→ 机械臂坐标 (200, -90)
|
||
P4(左下)←→ 机械臂坐标 (90, -90)
|
||
```
|
||
|
||
点完第 4 个点后,单应性矩阵立即更新,无需重启。
|
||
|
||
---
|
||
|
||
## 故障排除
|
||
|
||
| 现象 | 原因 | 解决 |
|
||
|:---|:---|:---|
|
||
| 按空格无反应 | 窗口焦点不在摄像头画面 | 点击一下摄像头窗口 |
|
||
| 语音识别乱码 | 麦克风噪声 / 语速过快 | 安静环境,语速适中,按住空格 0.5s 再说话 |
|
||
| "未找到目标" | YOLO 未检测到物体 | 调整物体角度、光照;检查是否在训练类别中 |
|
||
| 抓取位置偏离 | 摄像头被移动 | 按 **C** 重新四点标定 |
|
||
| 无法连接串口 | ESP32 未插入 / 端口号不对 | 检查设备管理器,修改 `ROBOT_PORT` 环境变量 |
|
||
| 启动剧烈抖动 | 五路舵机同时上电浪涌 | 固件已做阶梯式上电;若仍出现,检查电源容量 |
|
||
|
||
---
|
||
|
||
## 核心技术要点
|
||
|
||
以下是开发过程中解决的关键工程问题,供复刻者参考。
|
||
|
||
**D-H 逆运动学**
|
||
130mm 的 L4 连杆导致几何解析法在水平移动时产生 40° 轨迹偏移。最终采用 Scipy SLSQP 数值优化器,加入 `Pitch=-90°` 姿态约束(抓手始终垂直地面),彻底解决非线性偏移。
|
||
|
||
**S-Curve + 多层减震**
|
||
MG996R 在长力臂下惯性震动严重。减震流水线:倾斜补偿 → 移动平均滤波(deque)→ 速度限制 → EMA 阻尼 → 死区过滤。
|
||
|
||
**双通道解析架构**
|
||
简单指令(松开、复位、方向移动)走正则规则引擎,微秒级响应,且避免大模型将"向下三厘米"误判为 `lift`。只有含物体名的复杂指令才交给 LLM(延迟 <200ms)。
|
||
|
||
**Pre-filling 截断**
|
||
DeepSeek-R1 默认输出思维链(`<think>...</think>`)。通过手动追加 `<|Assistant|>` 标签进行 Pre-filling,强制跳过思考过程直接输出 JSON,实现 100% 格式遵循率。
|
||
|
||
**Whisper 反幻觉**
|
||
三道防线,全部封装在 `RobotEar.get_text()` 内:① 首尾静音裁剪 + 时长过滤;② `condition_on_previous_text=False`;③ 重复模式正则检测(去除"向右向右向右..."类幻觉)。相关阈值均在 `config.py` 中统一配置。
|
||
|
||
**工程坑:System Prompt 对齐**
|
||
训练与推理的 System Prompt 必须完全一致,否则模型输出偏移(如输出 500mm 而非 50mm)。已在代码注释中标注警告。
|
||
|
||
---
|
||
|
||
## 大模型训练
|
||
|
||
约 500 条领域数据,QLoRA 微调 DeepSeek-R1-1.5B,Loss 收敛至 0.0519,格式错误率 0%。
|
||
|
||
完整训练流程见 [`TRAINING.md`](TRAINING.md),包括:QLoRA 超参数配置、GGUF vs Transformers 方案对比、Pre-filling 推理方案详解、实验结果。
|
||
|
||
---
|
||
|
||
## 项目结构
|
||
|
||
```
|
||
robot_arm/
|
||
├── README.md 本文档(中文)
|
||
├── README_EN.md English documentation
|
||
├── TRAINING.md 大模型 LoRA 微调研究笔记
|
||
├── requirements.txt Python 依赖
|
||
├── config.py 全局常量:硬件、运动、音频、手势(支持环境变量覆盖)
|
||
│
|
||
├── main.ino ESP32 固件,LEDC PWM 舵机控制
|
||
├── arm_main.py 机械臂运动学核心:D-H IK + S-Curve
|
||
├── whisper_main.py 语音识别全链路:静音裁剪 → 转录 → 纠错
|
||
└── voice_main.py 主程序:语音 → LLM → 视觉 → 控制
|
||
```
|
||
|
||
---
|
||
|
||
## 关键数据
|
||
|
||
| 指标 | 值 |
|
||
|:---|:---|
|
||
| 硬件成本 | ¥317 |
|
||
| GPU 需求 | RTX 3060 6GB(推理 <4GB 显存) |
|
||
| 推理延迟 | <200ms(LLM),<50ms(规则引擎) |
|
||
| 训练数据量 | ~500 条 |
|
||
| 格式错误率 | 0% |
|
||
| 运行模式 | 完全离线 |
|