3.7 KiB
3.7 KiB
红绿灯识别 — 设计与实现
1. 模型检测
NanoDet V10 模型 4 类输出中:
- cls=1: 红灯
- cls=2: 绿灯
模型置信度阈值由 g_thresh[1] 和 g_thresh[2] 控制(src/camera.cpp:25),当前分别为 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. 刹车机制
和斑马线完全一样,复用编码器比例刹车:
ControlUpdate(spd, g_zstate == Z_STOP || 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)
Step 4: 模型推理 → g_boxes[], g_box_count
Step 5: 斑马线状态机
Step 5.5: 红绿灯状态机
├─ 遍历 g_boxes, 统计 red_seen/green_seen
├─ 去抖计数 (3帧确认, 衰减-1/帧)
└─ 状态跃迁
Step 5.6: 锥桶检测 (g_zstate!=Z_STOP && g_tl_state==TL_NORMAL 时才运行)
Step 7: 电机控制
ControlUpdate(spd, g_zstate==Z_STOP || tl_block)
control.cpp:
ControlUpdate(speed, zebra_block)
└─ zebra_block → 编码器线程读速度 → 比例刹车
6. 状态变量
定义在 src/camera.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— 全部正常