# yiliao_ws 项目总结

> **生成日期**: 2026-08-09  
> **项目名称**: 智慧医疗2026（第21届全国大学生智能汽车竞赛·地瓜机器人赛项）  
> **ROS 发行版**: ROS 2 Humble  
> **机器人平台**: OriginCar (RDK X5, 四轮阿克曼转向)  
> **工作区路径**: `/home/sunrise/yiliao_ws`  
> **远程仓库**: `https://gitee.com/hikos/smart-healthcare-2026.git`

---

## 一、项目定位

本项目是 RDK X5 机器人上的 ROS 2 Humble 工作区，服务于第21届全国大学生智能汽车竞赛的**医疗赛道**（智慧医疗）。整体采用**调度型架构**：底盘、雷达、相机、二维码、Nav2 导航、VLM 图生文、TTS 语音等功能由独立模块完成，`racing_control` 包作为总调度协调各模块完成比赛流程。
    
---

## 二、项目目录结构总览

```
yiliao_ws/
├── src/                          # 源代码（所有 ROS 2 包）
│   ├── racing_control/           # 🎯 总调度（比赛流程控制）
│   ├── origincar_base/           # 🔧 底盘驱动（串口通信 + EKF + 阿克曼）
│   ├── navigation/               # 🧭 导航相关包集合
│   │   ├── obstacle_nav2/        #   主 Nav2 导航栈（含参数调谐器）
│   │   ├── gc_navigation2_slamtoolbox/  #   仿真版 SLAM + Nav2
│   │   ├── gc_navigation2_real/  #   实车版 SLAM + Nav2
│   │   ├── gc_navigation_fish/   #   另一套导航配置
│   │   ├── cyy_navigation2/      #   备选导航方案
│   │   ├── cyy_slamtoolbox/      #   备选 SLAM 方案
│   │   └── zbw_slamtoolbox/      #   另一套 SLAM 方案
│   ├── qr_detection/             # 📷 二维码检测
│   ├── vlm_detect/               # 🤖 VLM 图生文 + TTS 语音播报
│   ├── car_usb_cam/              # 📸 USB 相机驱动
│   ├── obstacle_scanner/         # 📡 激光雷达障碍物检测
│   ├── origincar_msg/            # 📦 自定义 ROS 2 消息
│   ├── origincar_description/    # 🤖 机器人 URDF 模型描述
│   ├── origincar_birdseye/       # 🐦 鸟瞰图转换
│   ├── my_robot_bringup/         # 🚀 总启动编排（master_launch.py）
│   ├── planner/                  # 🗺️ 备选规划器（Hybrid A* 等）
│   ├── past_control/             # 📝 历史控制方案
│   ├── mtran/                    # 🧠 MTRAN 模型
│   ├── ground_slam/              # 🗺️ 地面 SLAM
│   ├── car_image_proc/           # 🖼️ 图像处理
│   ├── yolov8_launch/            # 🎯 YOLOv8 目标检测
│   ├── data_collection_tools/    # 📊 数据采集工具
│   ├── LSLIDAR_X_ROS2-20240228/  # 📡 镭神激光雷达 ROS 2 驱动
│   └── gc/                       # 📄 项目文档存放
├── build/                        # colcon 构建输出
├── install/                      # colcon 安装输出
├── scripts/                      # 辅助脚本（PID跟踪、陀螺仪标定等）
├── bashes/                       # 自动脚本（WiFi连接、雷达驱动切换）
├── config/dds/                   # DDS 配置
├── datas/                        # 采集数据
├── models/                       # 模型文件
├── docs/                         # 文档
├── bag_outputs/                  # ROS Bag 输出
├── running_logs/                 # 运行日志
├── test_results/                 # 测试结果
├── vlm_server.py                 # VLM 推理服务（FastAPI）
├── cali.npz / cali.txt           # 标定数据
├── path_follower_demo.py         # 路径跟随演示
└── 标定.py                       # 标定脚本
```

---

## 三、核心模块详解

### 3.1 racing_control — 比赛总调度 ⭐

| 项目 | 说明 |
|------|------|
| **包路径** | `src/racing_control` |
| **语言** | C++ (rclcpp) |
| **主节点** | `racing_control.cpp` |
| **配置** | `config/racing_control.yaml` |
| **启动** | `launch/racing_control.launch.py` |

**设计原则**：只做比赛流程调度，不重复实现二维码、VLM、Nav2、底盘控制等子功能。通过 `/sign4return` 信号控制各子模块的开关和参数切换。

**比赛流程（12个阶段）**：

```mermaid
graph TD
    A[Idle 等待启动] --> B[NavigateToQr 二维码点导航]
    B --> C[NavigatePostQr 二维码后置点导航]
    C --> D[WaitForQr 二维码识别+TTS]
    D --> E[NavigateToEntry 通道入口导航]
    E --> F[SwitchToTask2Profile 任务二参数切换]
    F --> G[ComputeCirclePath 任务二轨迹规划]
    G --> H[ExecuteCirclePath 任务二轨迹执行]
    H --> I[SwitchToNormalProfile 恢复导航参数]
    I --> J[WaitForVlm 图生文+TTS]
    J --> K[ReturnOrigin 返回原点]
    K --> L[Finished 比赛完成]
```

**关键接口**：
- Nav2 Actions: `/navigate_to_pose`, `/compute_path_through_poses`, `/follow_path`
- 控制信号: `/sign4return` (Int32)，数值含义：0=启用QR, 5=关闭QR, 9=触发VLM, 10=普通Nav2参数, 11=任务二Nav2参数
- 接收: `/qr_results`, `/vlm_result`, `/odom_combined`

**关键参数（YAML 配置）**：
| 参数 | 默认值 | 说明 |
|------|--------|------|
| `qr_pose` | 坐标数组 | 二维码区域导航点 |
| `post_qr_pose` | 坐标数组 | 二维码后置过渡点 |
| `entry_pose` | 坐标数组 | 正式路线入口点 |
| `clockwise_waypoints` | 坐标数组 | 顺时针路线点（不含home） |
| `counterclockwise_waypoints` | 坐标数组 | 逆时针路线点（不含home） |
| `clockwise_home_pose` | 坐标数组 | 顺时针home点 |
| `counterclockwise_home_pose` | 坐标数组 | 逆时针home点 |
| `vlm_waypoint_number` | 2 | 第几个路线点触发VLM |
| `vlm_capture_mode` | stop | VLM拍摄模式 (stop/pass_through) |
| `use_post_qr_pose` | false | 是否启用QR后置点 |
| `enable_vlm_image_relay` | false | 是否转发单帧图像给VLM |

**二维码方向解析规则**：
- 文本包含 `顺` 或奇数数字 → 顺时针
- 文本包含 `逆` 或偶数数字 → 逆时针

---

### 3.2 origincar_base — 底盘驱动

| 项目 | 说明 |
|------|------|
| **包路径** | `src/origincar_base` |
| **语言** | C++ + Python |
| **主节点** | `origincar_base.cpp` (串口通信), `cmd_vel_to_ackermann_drive.py` (运动转换) |
| **配置** | `config/ekf.yaml`, `config/imu.yaml` |

**功能**：
- STM32 串口通信 (`/dev/ttyACM0`, 921600bps)
- 航迹推算 + Mahony AHRS 姿态解算
- EKF 融合 (odom + IMU → `/odom_combined`)
- Twist → AckermannDriveStamped 转换 (wheelbase=0.143m)
- 帧协议: 24字节收（0x7B/0x7D帧头尾）/ 11字节发

**阿克曼底盘模式** (`akmcar:=true`)：
```
cmd_vel(Twist) → cmd_vel_to_ackermann_drive.py → ackermann_cmd(AckermannDriveStamped) → STM32
```

**关键修改（must_know.md 记录）**：
- EKF 帧名统一 (`odom_combined` → `odom`)
- 底盘驱动默认不再发布 TF（避免与 EKF 冲突）
- 里程计协方差可参数化配置
- 串口异常捕获防崩溃

---

### 3.3 obstacle_nav2 — 主 Nav2 导航栈

| 项目 | 说明 |
|------|------|
| **包路径** | `src/navigation/obstacle_nav2` |
| **启动文件** | `obstacle_nav2.launch.py`, `nav2_profile_tuner.launch.py`, `trajectory_guard.launch.py` |

**功能**：
- 集成 Nav2 导航（MPPI 控制器 + SmacPlannerHybrid 规划器）
- 消费 `/obstacles` 转化为 costmap 障碍物层
- **参数档位切换**：`nav2_profile_tuner` 监听 `/sign4return`，10→普通参数，11→任务二参数
- **轨迹保护**（备用）：`trajectory_guard` 订阅 `/trajectory_guard/input_path`

**关键参数文件**：
| 文件 | 用途 |
|------|------|
| `nav2_params.yaml` | Nav2 主参数 |
| `nav2_profile_10.yaml` | 普通/默认导航参数档 |
| `nav2_profile_11.yaml` | 任务二路线参数档 |
| `trajectory_guard.yaml` | 轨迹保护参数 |
| `nav2_params_basic_tracking.yaml` | 基础跟踪参数 |

**MPPI 参数（CPU 优化后）**：
- `time_steps`: 20, `batch_size`: 200 (原1000)
- `PathAlignCritic.cost_weight`: 7.0 (降低，避障优先)

**代价地图**：`inflation_radius`: 0.2m, `cost_scaling_factor`: 3.0

---

### 3.4 qr_detection — 二维码检测

| 项目 | 说明 |
|------|------|
| **包路径** | `src/qr_detection` |
| **语言** | C++ |
| **输入** | `/image` (CompressedImage) |
| **输出** | `/qr_results` (std_msgs/String) |
| **控制** | `/sign4return=0` 启用, `/sign4return=5` 关闭 |

---

### 3.5 vlm_detect — VLM 图生文 + TTS

| 项目 | 说明 |
|------|------|
| **包路径** | `src/vlm_detect` |
| **语言** | Python |
| **主节点** | `vlm_node.py` (VLM推理), `tts_server.py` (语音合成) |

**数据流**：
```
USB Camera → /image → vlm_node → /vlm_result
                    → qr_dete_node → /qr_results
                                     ↓
                              qr_tts_bridge → /tts/speak → Piper TTS → 语音输出
```

**VLM 触发**：`/sign4return=9`  
**VLM 服务**：外部 FastAPI 服务 (`vlm_server.py`)，运行 AndesVL-1B 模型，OpenAI 兼容 API  
**TTS**：Piper TTS + paplay 本地语音合成

---

### 3.6 obstacle_scanner — 雷达障碍物检测

| 项目 | 说明 |
|------|------|
| **包路径** | `src/obstacle_scanner` |
| **语言** | C++ (使用 OpenCV + Eigen) |
| **功能** | 基于角度聚类+圆拟合的 LiDAR 障碍物检测 |

---

### 3.7 my_robot_bringup — 总启动编排

| 项目 | 说明 |
|------|------|
| **包路径** | `src/my_robot_bringup` |
| **启动文件** | `launch/master_launch.py` |

**分阶段启动时间线**：
```
t=0s   底盘驱动 + EKF + TF + IMU (origincar_bringup)
t=2s   激光雷达 (lslidar_driver)
t=5s   SLAM 建图 (slam_toolbox)
t=8s   Nav2 导航栈
t=10s  VLM 图生文 + TTS 语音播报
```

**常用启动参数**：`use_base`, `use_lidar`, `use_slam`, `use_nav2`, `use_vlm`, `use_tts`, `akmcar`, `vlm_host`

---

### 3.8 其他包

| 包名 | 说明 |
|------|------|
| `origincar_description` | 机器人 URDF 模型 (0.276×0.214×0.211m, wheelbase=0.143m) |
| `origincar_msg` | 自定义消息 (Data.msg, Sign.msg) 和服务 (Speak.srv) |
| `car_usb_cam` | USB 相机驱动 (hobot_usb_cam)，发布 `/image` |
| `planner` | 备选规划方案（Hybrid A*, Pure Pursuit, Ackermann Hybrid A*） |
| `origincar_birdseye` | 鸟瞰图/IPM 变换 |
| `ground_slam` | 地面 SLAM 建图 |
| `yolov8_launch` | YOLOv8 目标检测启动 |
| `car_image_proc` | 图像处理工具 |
| `past_control` | 历史控制方案（竞速参考） |
| `mtran` | MTRAN 模型（含依赖和文档） |
| `data_collection_tools` | X5 UDP 指令桥接 |

---

## 四、导航相关包集合 (`src/navigation/`)

本工作区历史上有多个 SLAM/Nav2 方案迭代：

| 包名 | 用途 | 状态 |
|------|------|:----:|
| `obstacle_nav2` | 主 Nav2 导航栈 + 参数调谐 | ✅ **当前使用** |
| `gc_navigation2_slamtoolbox` | 仿真版 SLAM + Nav2 (Gazebo) | 📦 仿真用 |
| `gc_navigation2_real` | 实车版 SLAM + Nav2 (无 Gazebo) | 📦 实车参考 |
| `gc_navigation_fish` | 另一套导航配置 | 📦 备用 |
| `cyy_navigation2` | 备选导航方案 | 📦 历史 |
| `cyy_slamtoolbox` | 备选 SLAM | 📦 历史 |
| `zbw_slamtoolbox` | 另一套 SLAM | 📦 历史 |

**关键差异（仿真 vs 实车）**：
| 方面 | 仿真版 | 实车版 |
|------|--------|--------|
| `use_sim_time` | true | false |
| odom_frame | `odom` | `odom_combined` (EKF融合后) |
| 底盘驱动 | Gazebo plugin | origincar_base 串口驱动 |
| 激光雷达 | Gazebo ray plugin | lslidar_driver (镭神 N10) |

---

## 五、TF 树结构

```
map ──→ odom ──→ base_footprint ──→ base_link ──→ laser_link
 ↑        ↑           ↑                ↑
slam    EKF融合     静态TF            URDF
```

---

## 六、关键共享信号 `/sign4return`

| 值 | 含义 | 消费者 |
|:--:|------|--------|
| 0 | 启用二维码检测 | qr_detection |
| 5 | 关闭二维码检测 | qr_detection |
| 9 | 触发 VLM 拍摄/推理 | vlm_detect |
| 10 | 应用普通 Nav2 参数档 | nav2_profile_tuner |
| 11 | 应用任务二 Nav2 参数档 | nav2_profile_tuner |

---

## 七、环境与操作

### 7.1 机器人访问
```bash
ssh sunrise@192.168.10.210
```

### 7.2 环境初始化
```bash
cd /home/sunrise/yiliao_ws
source /opt/ros/humble/setup.bash
source install/setup.bash
# 部分相机流程可能还需要: source /opt/tros/humble/setup.bash
```

### 7.3 编译
```bash
# 编译单个包
colcon build --packages-select <package_name> --cmake-args -DBUILD_TESTING=ON

# 全量编译（推荐 --symlink-install 使 Python 修改即时生效）
colcon build --symlink-install
```

### 7.4 运行测试
```bash
colcon test --packages-select racing_control
colcon test-result --verbose --test-result-base build/racing_control
```

### 7.5 常用启动命令
```bash
# 全部启动（比赛模式）
ros2 launch my_robot_bringup master_launch.py

# 仅底盘调试
ros2 launch my_robot_bringup master_launch.py use_lidar:=false use_slam:=false use_nav2:=false use_vlm:=false

# 仅建图
ros2 launch my_robot_bringup master_launch.py use_nav2:=false use_vlm:=false

# 比赛控制（自动开始）
ros2 launch racing_control racing_control.launch.py auto_start:=true

# 带图像转发的比赛控制
ros2 launch racing_control racing_control.launch.py enable_vlm_image_relay:=true
```

---

## 八、硬件与传感器

| 部件 | 型号 | 说明 |
|------|------|------|
| 主控 | RDK X5 | 10 TOPS 算力 |
| 底盘 | OriginCar | 四轮阿克曼转向，276×214×211mm，轴距143mm |
| 激光雷达 | 镭神 N10 | 单线TOF，0.15~12m |
| 深度相机 | 光鉴 Aurora930 | |
| USB相机 | USB 2.0 Camera | 发布 `/image` |
| IMU | 板载 | 与里程计进行 EKF 融合 |

---

## 九、已知问题与调试经验

### 9.1 已修复的关键问题

| 问题 | 修复方案 |
|------|----------|
| TF 树断连（两节点争抢 odom→base_link） | EKF 改为发布 odom→base_footprint；底盘驱动默认不发布 TF |
| 串口异常崩溃 | 为 Stm32_Serial.read() 添加 try-catch |
| LiDAR 扫描出现空扇形面 (60°) | 恢复 `scan_num` 动态计算公式 |
| URDF git 冲突 | 清除冲突标记，统一轮距参数 |
| CPU 负载过高 (77%) | MPPI batch_size 1000→200, throttle_scans 1→10, EKF 30Hz→20Hz |
| cmd_vel_to_ackermann_drive.py 权限 | chmod +x |

### 9.2 调试检查清单

- **二维码区域后不继续走**：检查 `/qr_results` 是否有输出，文本是否可解析为顺/逆
- **VLM 无结果**：检查 `/image` 话题，确认 enable_vlm_image_relay 和 VLM image_topic 配置
- **路线末端卡住**：检查 `/odom_combined` 连续性，circle_goal_tolerance 是否过小
- **Nav2 行为异常**：检查 nav2_profile_tuner 是否收到/应用了 /sign4return 10/11
- **雷达无数据**：`lsusb` 检查物理连接，`ls /dev/tty*` 检查 ttyACM0/ACM1/CH340

---

## 十、辅助脚本

| 脚本 | 用途 |
|------|------|
| `scripts/PIDtracking.py` | PID 轨迹跟踪 |
| `scripts/measure_turning_radius.py` | 测量转弯半径 |
| `scripts/fit_gyro_bias.py` | 陀螺仪偏置拟合 |
| `scripts/publish_sine_path.py` | 发布正弦路径 |
| `scripts/udp_to_cmdvel.py` | UDP→cmd_vel 桥接 |
| `scripts/set_volume.py` | 音量设置 |
| `bashes/radar-driver-switch.sh` | 雷达驱动自动切换 |
| `bashes/auto-wifi-connect.sh` | WiFi 自动连接 |
| `vlm_server.py` | VLM 推理服务 (FastAPI, AndesVL-1B) |
| `path_follower_demo.py` | 路径跟随演示 |

---

## 十一、数据与文档

| 类型 | 路径 | 说明 |
|------|------|------|
| 地图文件 | `src/navigation/*/maps/` | .pgm + .yaml + .posegraph |
| 采集数据 | `datas/` | data4, data5, PIDtracking等 |
| 调试记录 | `调试记录.md` | 2026/6/1 ~ 6/13 调试过程 |
| 变更说明 | `must_know.md` | mo_new→HEAD 101文件变更详解 |
| 启动指南 | `master_launch_使用指南.md` | master_launch.py 完整说明 |
| 竞赛方案 | `竞赛方案_第21届智能汽车竞赛地瓜机器人赛项.md` | 正式竞赛方案文档 |
| 点位移转 | `src/racing_control/点位格式转换.md` | JSON→YAML 点位转换流程 |
| VLM数据流 | `src/vlm_detect/dataflow.md` | VLM+QR→TTS 数据流图 |
| AGENTS.md | `/home/sunrise/yiliao_ws/AGENTS.md` | 项目级说明 |
| CLAUDE.md | `/home/sunrise/yiliao_ws/CLAUDE.md` | 另一视角的项目说明（含 test_ws 内容） |
