综合项目 / 通用目标追踪 / EXP-01
EXP-01 · 第 1 章 · 验证性 · 4 学时

需求分析:R1-R13 需求体系

在写任何一行代码之前,先把项目的"宪法"读薄:13 条编号需求(R1-R13)覆盖了从多源输入、检测追踪、指令门控、描述选车到事件日志的完整闭环。本实验带你用 grep 真实通读源工程的 docs 文档,给每条需求标注实现模块与 fail-closed 关卡,为后续八个实验建立可回溯的需求底座。

难度 ⭐ · 4 学时 R1-R13fail-closed 门控防呆需求分层

01问题引入:13 条需求到底管什么

设想你要验收一辆"能听会看"的智能小车:它要在视频文件、图片、ROS 相机话题三种输入下都能跑,闻令锁定目标、说人话回答、坏了还得留下"黑匣子"记录。这样的系统如果只有一句"做一个目标追踪",测试时必然扯皮 —— 所以源工程把验收口径写成了 13 条编号需求:

1输入层R1:多源输入(--video / --image / --camera)统一入口
2感知层R2-R4:YOLOv8n 检测(COCO 80 类 class_filter=[car])+ DeepSORT + ReID
3交互层R5-R11:LLM FunctionCall 门控、VLM 描述选车、清除词、流式 TTS
4可靠性层R12-R13:事件日志 events.jsonl、文本模式 / MJPEG 兜底
💡 一句话认识需求编号R 编号不是文档装饰:后续每个实验的坑表、每个配置项(min_box 32、cell_cap=16、clear_words 词表)都能回溯到某一条 R —— 遇到行为疑问,先查它对应哪条需求,这是本课程贯穿始终的排障第一动作。

02原理通俗讲解:把需求当"点单小票"读

把整个系统想成一家智能餐厅:摄像头是"传菜口",检测+追踪是"后厨认清哪盘菜",语音指令是"客人点单",门控就是柜台服务员—— 客人说什么都能记下来吗?不。服务员只在菜单已有的三道菜(track_ids / clear_track / save_snapshot)里下单;拿不准客人指哪道菜(fail-closed:拿不准就不放行),宁可回一句"请再说清楚点",也绝不把不确定的单子递进后厨。

编号需求内容(源讲义归纳)实现锚点fail-closed?
R1多源输入:--video / --image / --camera 三级模式FrameSource否
R2目标检测:YOLOv8n RKNN,COCO 80 类,class_filter=[car]detect 段否
R3多目标追踪:DeepSORT 级联匹配保持 IDtracker 段否
R4外观重识别:ReID 模型 deepsort.rknn 提特征use_reid挂了退纯 IoU
R5指令理解经 LLM FunctionCall,模型不直接执行NATIVE_TOOLS是
R6原生 FunctionCall 模式 llm.function_call.nativellm 段是
R7描述选车:无 ID 带描述时走 VLM 网格判定track_vlm是
R8VLM 解析不出 / 超 cell_cap=16 一律不锁_vlm_none是
R9清除词表强制 clear_track,不经过模型自由发挥clear_words短路放行
R10口令词预路由:track / clear / color / desc 词表分流interaction 段配合门控
R11语音应答复用流式 TTS,按句切分可打断speech 段—
R12关键状态事件落盘 events.jsonl 可复盘tracking/events.py—
R13无硬件也能验收:文本模式 + MJPEG 浏览器查看--text / :8088—
🔍 两条量化红线检测框进入追踪链前要过 keep(b) 判定:置信度 ≥ min_confidence 0.3,且框宽高 ≥ min_box 32 像素。太小的框 ReID 特征不可靠、置信度太低的框多半是误检 —— 需求层就规定"不合格的框不许进追踪",这是 R2/R3 的第一道防呆。

需求还可以按确定性分两层:R1-R4、R11-R13 是"能力需求"(做到什么);R5-R10 是"安全需求"(不确定时必须拒绝)。

03关联知识点

知识点一
需求可追溯性

每条 R 都有唯一编号与实现锚点,测试用例按编号挂靠 —— 行为变更时能立刻回答"违反了哪条需求",这叫需求→代码→用例的三向追溯。

知识点二
fail-closed vs fail-open

fail-closed:拿不准就不放行(门禁刷不上就锁死);fail-open:出错也放行(消防门断电即开)。会"锁错人"的系统必须选前者。

知识点三
检测 / 追踪 / ReID 三层分工

检测回答"这帧有什么",追踪回答"上一帧的它现在在哪",ReID 回答"两团像素是不是同一个人"—— 三层各管一段,谁也替代不了谁。

知识点四
三级开发模式

--text(stdin 喂指令)→ 语音 → --camera,每级只叠加一层硬件依赖。R13 的意义正是:所有逻辑都能在无硬件条件下先验收。

04实验目标

  • 能脱稿复述 R1-R13 十三条需求的分层结构(输入 / 感知 / 交互 / 可靠性四层)
  • 用 grep -n "R[0-9]" 在两分钟内定位任意编号需求的原文出处
  • 标出全部 fail-closed 节点:R5-R8 的门控与 VLM 解析分支
  • 解释 keep(b) 两条量化红线(min_confidence 0.3 / min_box 32)各自挡住什么噪声
  • 说清 R9 清除词"强制短路"与 R10 词表"预路由"的分工区别
  • 输出一份自己的《需求分层表》,作为后续八个实验的验收索引

05实验环境与准备

源码位置
object_tracking 工程

源码路径:ros2_ws/src/xflz_eai_car1/app/object_tracking/,docs 目录十份文档,本实验主读 01_需求总览 与 05_流程与安全。

工具准备
grep / head / sed

只需 Linux 命令行:grep 按编号检索、head 速读 README、实验后半会用 sed 做临时改动(EXP-03 起大量使用)。

硬件依赖
本实验零硬件

纯文档与代码阅读,不需要相机、麦克风、工控主机 —— 这正是 R13 文本先行理念在课程入口的体现。

# 进入源码目录(后续所有实验统一起点)
cd ~/ros2_ws/src/xflz_eai_car1/app/object_tracking

# 先看目录结构,确认 docs 十份文档就位
ls docs/
# 01_需求总览.md  02_架构设计.md  03_开发模式与验证.md  04_配置方案.md  05_流程与安全.md ...

06动画讲解:检测→追踪→门控→事件全流程

13 条需求串在一条数据流上:画面进检测,框进追踪,指令过门控,结果写事件。看动画里高亮的每个工位对应哪几条 R:

需求链 · 从输入到黑匣子(8 秒循环) 多源输入R1 · video/image/camera 检测+追踪R2-R4 · keep(b) 红线 指令门控R5-R10 · fail-closed 事件落盘R12 有 id 且存在 → 锁定并播报(R11) 拿不准 → 拒绝执行,回引导语 events.jsonl R13 · 任意模式输出 MJPEG 到 :8088/track.mjpg 供浏览器验收 lost / unlock_all 也在 R12 范围
动画 1-1|四工位串起 R1-R13:门控处永远分两条路 —— 确定才放行,拿不准就拒绝并留痕

07互动讲解:需求条目速配台

点选一个验收场景,速配台给出它命中的需求编号、实现锚点,以及该走"放行"还是"fail-closed 拒绝":

需求条目速配台 · R-Matcher
// 点击场景,观察需求编号与门控决策的对应关系 所有场景都能在 docs/01_需求总览.md 里 grep 到对应 R 编号。
💡 快速自测不看上表,先自问:"追踪红色小轿车但全场无红车"该放行还是拒绝?在哪条需求里写死了这个行为?(提示:R7/R8 与 _vlm_none 出口)答不上来就回到第 02 节的表格再对一遍。

08实操步骤:grep 通读需求文档

1按编号把 13 条需求原文全部抓出来,建立编号→原文对照
2检索"门控 / fail-closed / 清除 / 防呆",圈出全部安全相关条款
3head 速读 README 前 60 行,把架构速览与需求对上号
4整理《需求分层表》:编号 / 分层 / 锚点 / 是否 fail-closed 四列
# ① 一次抓全 13 条编号需求(行号即锚点)
grep -n "R[0-9]" docs/01_需求总览.md

# ② 圈出全部安全条款:门控 / fail-closed / 清除 / 防呆
grep -n "门控\|fail-closed\|清除\|防呆" docs/05_流程与安全.md

# ③ README 架构速览前 60 行,对上七层模块自述
head -60 README.md

# ④ 顺手确认核心词在工程里的真实出场位置
grep -rn "clear_words\|cell_cap\|min_confidence" config/ docs/ | head -20
🔍 七层模块对号入座源码分七层:apps / common / tracking / tools / speech / llm / config,依赖方向单一:common ← vision/tracking ← tools ← apps,而 speech、llm 相对独立。你的分层表里"实现锚点"一列先填模块名,EXP-02 再细化到具体文件行号。

09重点与易错点

⚠️ 头号易错需求层面最容易读岔的一条:LLM 不分配 ID。目标 ID 由 DeepSORT 追踪链(DeepTrack 序列)生成,LLM 只做"选哪个已有 ID / 是否清除"的选择题 —— 任何"让模型发明新 ID"的改造都直接违反 R5/R6。
⚠️ 常见坑现象 → 解法
把 R 编号当摆设排障时凭感觉改代码 → 先 grep 需求原文,确认改动不违反该条验收口径
fail-closed 覆盖不全只在门控首分支拒绝 → 校验清单:一切"不确定锁谁"的分支(VLM 解析失败 / 超 cell_cap / ID 不存在)都必须汇入拒绝出口
让清除词走模型"取消"被 LLM 忘掉 → R9 要求清除词表在门控层强制短路为 clear_track,不依赖模型发挥
keep(b) 只查一半只看置信度放过 10px 小框 → 同时校验 min_confidence 0.3 与 min_box 宽高 32 双红线
没硬件就不验收等相机到位才测试 → R13 的 --text + MJPEG 就是让你先在纯软件环境验收全部逻辑
  • 13 条需求全部出现在《需求分层表》中,且标出四层归属
  • 每个 fail-closed 条目都写明"拒绝时用户听到什么"(引导语而非静默)
  • keep(b) 双红线与 03_Config、04-DeepSORT 实验的参数页交叉引用
  • grep 命令可复现:按编号搜索能在 2 秒内回到需求原文

10总结与思考

✅ 完成成果
需求分层表 + grep 定位能力

13 条需求按输入/感知/交互/可靠性四层归位,每条都有原文锚点与实现模块。

🧠 原理收获
fail-closed 验收观

会"锁错人"的系统宁可拒绝也不乱动;R5-R10 构成完整的安全需求簇。

🛠 技能收获
grep 三板斧

按编号抓原文、按关键词圈安全条款、按模块对号入座。

➡ 承上启下
锚点列将被填满

下一步:分层表的"实现锚点"从模块名细化到 EXP-02 的文件行号。

📝 思考题 1为什么 R5 规定 LLM 只能做选择题(track_ids / clear_track / save_snapshot 三选一),而不能直接输出"锁定目标"的执行命令?如果让 0.8B 模型直接支配追踪状态,最先失控的会是哪条需求?
📝 思考题 2把 fail-closed 改成 fail-open(拿不准也放行):在"描述选车"场景下会多出哪几种误锁?对照第 02 节表格,列出你认为最危险的一个后果并说明它为什么违反 R8。