# VLM + QR → TTS 数据流关系

## 两条数据流总览

```
                    ┌──────────────┐
                    │  USB Camera  │
                    │  /dev/video0 │
                    └──────┬───────┘
                           │
              hobot_usb_cam (car_usb_cam)
                           │
              ┌────────────┼────────────┐
              │            │            │
         /image_mjpeg   /image     (其他话题)
              │            │
              ▼            ▼
    ┌─────────────┐  ┌──────────────┐
    │  vlm_node   │  │ qr_dete_node │
    │  (Python)   │  │   (C++)      │
    └──────┬──────┘  └──────┬───────┘
           │                │
           │          /qr_results
           │                │
           │         ┌──────▼───────┐
           │         │ qr_tts_bridge│
           │         │  (Python)    │
           │         └──────┬───────┘
           │                │
           ▼                ▼
    ┌────────────────────────────────┐
    │         /tts/speak             │
    │     (origincar_msg/Speak)      │
    │                                │
    │         tts_server             │
    │     Piper TTS + paplay         │
    └────────────────────────────────┘
```

---

## 数据流 1：VLM 图生文 → TTS

### 触发条件

| 话题 | 类型 | 说明 |
|------|------|------|
| `/sign4return` | `std_msgs/Int32` | `data=9` 触发 VLM 推理 |

### 数据流

```
/image_mjpeg                     /sign4return (9)
(CompressedImage)                (Int32)
     │                                  │
     ▼                                  ▼
┌─────────────────────────────────────────────────┐
│                    vlm_node                      │
│                                                  │
│  1. image_callback(): 缓存最新帧到 self.latest_image │
│  2. sign_callback(): 收到 data==9 时触发            │
│  3. process_image():                              │
│     a. (可选) 自动裁剪照片区域 (auto_crop)           │
│     b. 缩放到 max_dim (默认 96px)                  │
│     c. JPEG 压缩 (quality=60)                     │
│     d. Base64 编码                                │
│     e. POST → VLM HTTP API (/v1/chat/completions) │
│     f. 返回文字描述                                │
│  4. 发布结果到 /vlm_result                         │
│  5. 调用 /tts/speak 服务播报文字                   │
└────────────┬──────────────────┬──────────────────┘
             │                  │
             ▼                  ▼
    /vlm_result          /tts/speak 服务
  (std_msgs/String)    (origincar_msg/Speak)
```

### 关键参数

| 参数 | 值 | 说明 |
|------|-----|------|
| `image_max_dim` | 96 | 图片最大边长，越小越快 |
| `max_tokens` | 30 | VLM 生成最大 token 数 |
| `temperature` | 0.1 | 低温度 = 更确定 |
| `auto_crop` | false | CPU 优化，默认关闭自动裁剪 |
| `vlm_host` | `http://192.168.10.189:8000` | VLM 服务地址 (Windows WSL) |
| `vlm_model` | `Qwen2-VL-2B-Instruct-Q4_K_M` | 视觉语言模型 |

---

## 数据流 2：QR 二维码识别 → TTS

### 触发条件

| 话题 | 类型 | 说明 |
|------|------|------|
| `/sign4return` | `std_msgs/Int32` | `data=0` 开启二维码检测，`data=5` 关闭 |

### 数据流

```
/image                           (摄像头发布)
(CompressedImage)
     │
     ▼
┌──────────────────────────────┐
│     hobot_codec (可选)       │
│  NV12 解码 → 共享内存        │
│  /hbmem_img                  │
└──────────────┬───────────────┘
               │
               ▼
┌──────────────────────────────────────────────────┐
│              qr_detect / qr_dete_node (C++)       │
│                                                   │
│  1. 订阅图像话题                                   │
│  2. ZBar / OpenCV 二维码检测                      │
│  3. 发布识别结果到 /qr_results (std_msgs/String)   │
│  4. 控制 /sign4return:                            │
│     - 检测到时发 0 开启                            │
│     - 检测后发 5 关闭                              │
└────────────┬──────────────────────────────────────┘
             │
             ▼ /qr_results
┌──────────────────────────────────────────────────┐
│            qr_tts_bridge (Python)                 │
│                                                   │
│  1. 订阅 /qr_results                              │
│  2. 收到二维码文字后调用 /tts/speak 服务             │
└────────────┬──────────────────────────────────────┘
             │
             ▼
    /tts/speak 服务
  (origincar_msg/Speak)
```

---

## TTS 服务 (两条流共享)

### 服务定义

```
# origincar_msg/srv/Speak
string text          # 要播报的文字
---
bool success         # 是否成功
string message       # 错误信息
```

### 服务端 tts_server

```
/tts/speak 请求 (text)
     │
     ▼
┌─────────────────────────────────────┐
│            tts_server               │
│                                     │
│  1. Piper TTS 引擎                  │
│     模型: zh_CN-huayan-medium.onnx  │
│     生成 WAV 文件到 /tmp/tts_out.wav│
│  2. paplay 播放到 USB 音频设备      │
│     设备: USB Audio Device          │
│  3. 失败回退: espeak-ng (cmn)      │
└─────────────────────────────────────┘
```

| 参数 | 值 | 说明 |
|------|-----|------|
| `tts_speed` | 1.5 | 语速倍数 |
| `audio_sink` | USB Audio Device | PulseAudio 音频输出设备 |
| `voice` | zh_CN-huayan-medium | 中文女声 Piper 模型 |

---

## /sign4return 统一控制协议

| 值 | 作用 | 使用者 |
|----|------|--------|
| 0 | 开启二维码检测 | `qr_detection` |
| 5 | 关闭二维码检测 | `qr_detection` |
| 9 | 触发 VLM 图像分析 | `vlm_node` |
| 10 | 切换 Nav2 普通档 | `nav2_profile_tuner` |
| 11 | 切换 Nav2 任务二档 | `nav2_profile_tuner` |

---

## 完整比赛流程 (racing_control 编排)

```
1. 启动各节点 → 机器人开始寻线
2. 摄像头检测到二维码
   → /qr_results = "1"
   → qr_tts_bridge → /tts/speak("检测到一号二维码")
   → /sign4return = 5 (关二维码)
3. 导航到闸门前 (entry_pose)
4. 通过闸门 → 切换赛道
5. VLM 图像分析
   → /sign4return = 9
   → vlm_node 拍照 → VLM 推理 → /tts/speak(图像描述)
6. 导航到目标点 (vlm_pose)
7. 返回起点 (origin_pose)
```

---

## 一键启动命令

```bash
# VLM + TTS (两条流的核心服务)
source /opt/ros/humble/setup.bash && source /home/sunrise/yiliao_ws/install/setup.bash && ros2 launch vlm_detect vlm_detect.launch.py

# QT + TTS 桥接
source /opt/ros/humble/setup.bash && source /home/sunrise/yiliao_ws/install/setup.bash && ros2 launch vlm_detect vlm_detect.launch.py use_qr_tts:=true

# 二维码检测
source /opt/ros/humble/setup.bash && source /home/sunrise/yiliao_ws/install/setup.bash && ros2 launch qr_detection qr_detect.launch.py

# 测试 VLM 推理
source /opt/ros/humble/setup.bash && source /home/sunrise/yiliao_ws/install/setup.bash && ros2 run vlm_detect test_publisher --ros-args -p image_path:="/home/sunrise/yiliao_ws/my_model/image.png"
```
