# 红绿灯识别 — 设计与实现 ## 1. 模型检测 Mild v12 模型 4 类输出中: - cls=1: 红灯 - cls=2: 绿灯 模型置信度阈值由 `g_thresh[1]` 和 `g_thresh[2]` 控制(`src/camera.cpp:42`),当前分别为 0.75(红灯)和 0.80(绿灯)。 ## 2. 状态机 ``` ┌──────────────────────────────────────────┐ │ │ ▼ │ ┌──────────┐ 红灯连续3帧 ┌──────────┐ │ 正常行驶 │ TL_NORMAL │ ─────────────→ │ TL_STOP │ │ │ │ │ 刹车ON │ │ └──────────┘ └────┬─────┘ │ ▲ │ 红灯消失 │ │ ▼ │ │ ┌──────────────┐ │ │ 绿灯连续3帧 │ TL_WAIT_GREEN │ │ └──────────────────│ 刹车ON │ │ └──────────────┘ │ ``` | 状态 | 刹车 | 锥桶 | 触发条件 | |---|---|---|---| | TL_NORMAL | 无 | 正常 | — | | TL_STOP | ON | 抑制 | 红灯连续 3 帧确认 | | TL_WAIT_GREEN | ON | 抑制 | 红灯从视野消失 | **去抖:** 红灯 3 帧确认触发,衰减 `-1`/帧;绿灯 3 帧确认触发,衰减 `-1`/帧。 **为什么红灯消失后还要等绿灯:** 防止红灯误检消失后误触发通行。确保绿灯确实出现在视野中才放行。 ## 3. 刹车机制 和斑马线完全一样,复用编码器比例刹车: ``` motor_update(zebra_block, tl_block) → ControlUpdate(final_spd, zebra_block || tl_block) 刹车信号 = 斑马线STOP || 红灯STOP || 等待绿灯 ``` 刹车参数(热更新): | 文件 | 默认 | 含义 | |---|---|---| | `./brake_scale` | 10 | 速度(pps) → 刹车占空比(ns) | | `./brake_max` | 10000 | 最大刹车占空比(ns) | ## 4. 与其他模块的交互 ``` 决策优先级: Z_STOP (斑马线) > TL_STOP/WAIT_GREEN (红绿灯) > cone (锥桶) > 正常巡线 锥桶抑制: g_zstate != Z_STOP && g_tl_state == TL_NORMAL 时才运行 电机刹车: zebra_STOP || tl_block 任一为 true 即刹车 LCD 状态: "R"=红灯停车 "G"=等绿灯, 拼接斑马线状态 ``` ## 5. 关键代码路径 ``` CameraHandler (src/camera.cpp:755) Step 5: 模型推理 → g_boxes[], g_box_count Step 6a: 斑马线状态机 Step 6b: 红绿灯状态机 ├─ 遍历 g_boxes, 统计 red_seen/green_seen ├─ 去抖计数 (3帧确认, 衰减-1/帧) └─ 状态跃迁 Step 6c: 锥桶检测 (g_zstate!=Z_STOP && g_tl_state==TL_NORMAL 时才运行) Step 8: 电机控制 motor_update(zebra_block, tl_block) → ControlUpdate(final_spd, zebra_block || tl_block) control.cpp: ControlUpdate(speed, block) └─ block → 编码器线程读速度 → 比例刹车 ``` ## 6. 状态变量 定义在 `src/camera.cpp`: ```cpp enum TLState { TL_NORMAL, TL_STOP, TL_WAIT_GREEN }; static TLState g_tl_state = TL_NORMAL; static int g_tl_red_frames = 0; // 红灯连续计数 static int g_tl_green_frames = 0; // 绿灯连续计数 ``` ## 7. LCD 显示 状态字拼接:`[红绿灯][斑马线]` - `RN` — 红灯停车 + 正常巡线 - `GN` — 等绿灯 + 正常巡线 - `RS` — 红灯 + 斑马线同时 (极少见) - `NN` — 全部正常