将项目说明按主题集中到 docs,补齐根目录 README 和 AGENTS,移除弃用方案并保留有效测试记录与未实现提案。同步文档索引、引用及改动日志生成路径,README 增加 GitHub Markdown 导航和 Mermaid 图。 - fix(client): 统一状态与操作文案,录制和截图成功后再显示完成提示 - test(client): 按文件名核对媒体类型,避免依赖时间戳排序 验证:23 份项目文档、144 处本地引用、27 条外链、2 张 Mermaid 图;前端构建和 12 项测试;截图与录制的 4 条异步反馈路径;Windows Rust 编译检查和后端测试。后端 40 项返回成功,其中 3 项 ffmpeg 集成用例因本机缺少工具而未实际执行。
293 lines
13 KiB
Markdown
293 lines
13 KiB
Markdown
<p align="center">
|
||
<img src="desktop/src-tauri/icons/128x128.png" width="88" height="88" alt="Simba Robotics 队标">
|
||
</p>
|
||
|
||
# RMIC::2026 · 视野链路系统
|
||
|
||
**黑龙江大学 602 实验室 · Simba Robotics**
|
||
|
||
面向机器人对抗赛的局域网图传与装甲板系统。ESP32-S3 采集 OV5640 的硬件 JPEG,经 UDP 发送到桌面端;ESP32-C3 上报装甲板血量,桌面端提供操作手视野、裁判双路监看、截图录制和 USB 固件维护。
|
||
|
||
[](docs/setup/firmware.md)
|
||
[](docs/hardware/armor.md)
|
||
[](docs/desktop/client.md)
|
||
[](docs/protocol/udp.md)
|
||
|
||
[文档首页](docs/index.md) · [硬件接线](docs/hardware/camera.md) · [故障排查](docs/testing/troubleshooting.md) · [改动记录](docs/releases/changelog.md) · [开发约定](AGENTS.md)
|
||
|
||
> [!NOTE]
|
||
> 版本、构建号与线路协议号以 [`version.json`](version.json) 为准。改动记录从 Git 历史生成,维护方式见[版本说明](docs/development/versioning.md)。
|
||
|
||
## 导航
|
||
|
||
- [系统架构](#系统架构)
|
||
- [功能与验证范围](#功能与验证范围)
|
||
- [快速开始](#快速开始)
|
||
- [发现与收流时序](#发现与收流时序)
|
||
- [仓库结构](#仓库结构)
|
||
- [开发与验证](#开发与验证)
|
||
- [文档与后续工作](#文档与后续工作)
|
||
|
||
## 系统架构
|
||
|
||
```mermaid
|
||
flowchart LR
|
||
subgraph Camera["图传板 · ESP32-S3"]
|
||
Sensor["OV5640<br/>硬件 JPEG"] --> Firmware["采集与分片<br/>最新帧发送"]
|
||
end
|
||
|
||
subgraph Armor["装甲板 · ESP32-C3"]
|
||
Piezo["四路压电片"] --> Rules["受击规则与整车血量"]
|
||
Rules --> LEDs["四路 WS2812"]
|
||
end
|
||
|
||
subgraph Desktop["RMIC::2026 · 桌面端"]
|
||
Core["Rust 核心<br/>发现、重组与血量状态"]
|
||
Backend["Tauri 后端<br/>本地通道、截图与录制"]
|
||
UI["React / WebView<br/>用户端或裁判端"]
|
||
Core --> Backend
|
||
Backend -->|"本地 WebSocket:JPEG 与状态"| UI
|
||
UI -->|"IPC:配置与操作"| Backend
|
||
end
|
||
|
||
Firmware -->|"UDP 5600:Hello 与视频分片"| Core
|
||
Core -->|"Subscribe:广播与定向续订"| Firmware
|
||
Rules -->|"UDP 5601:血量广播"| Core
|
||
```
|
||
|
||
两块图传板各自发送,裁判端同时接收两路;用户端只接收绑定图传板的画面。装甲板主板连接四路传感器和灯带,其余从板不含 MCU。
|
||
|
||
| 网络项 | 配置 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| 图传板 Wi-Fi | 2.4 GHz | 板卡与客户端需处于可互通的局域网 |
|
||
| 视频与发现 | UDP `5600` | Hello、Subscribe 与 JPEG 分片 |
|
||
| 装甲板上报 | UDP `5601` | 每 200 ms 广播四路血量 |
|
||
| 本地界面通道 | 回环 WebSocket + Tauri IPC | JPEG 由 WebView 解码,网络接收线程不做视频解码 |
|
||
|
||
> [!IMPORTANT]
|
||
> 网络需要允许广播和设备间互访。请关闭 AP 客户端隔离,并允许客户端通过防火墙。VPN / 虚拟网卡可能影响广播路由,排查方法见[客户端说明](docs/desktop/client.md#windows-x64-构建)。
|
||
|
||
## 功能与验证范围
|
||
|
||
| 模块 | 已有功能 | 使用条件与边界 |
|
||
| :--- | :--- | :--- |
|
||
| 图传固件 | VGA 彩色 JPEG、UDP 分片、多端订阅、Wi-Fi 重连、过期帧放弃 | 当前记录约 30 fps;不同网络、板卡与画质下需复测[^performance] |
|
||
| 用户端 | 本队画面、双方装甲条、瞄准器、偏移校准、命中反馈 | 先绑定图传板与装甲板;改绑、切换模式和退出受密码限制 |
|
||
| 裁判端 | 双路画面、队名编辑、装甲板发现、槽位分配、截图、录制与回放 | 录制需要 ffmpeg;图传槽位可手动指定 |
|
||
| 装甲板 | 四路受击检测与灯带、整车血量、UDP 上报 | 初始 100 血,每次受击扣 3 点;队伍号在编译期选择 |
|
||
| 固件维护 | USB 读取设备、检查固件包、选择候选槽位、备份和写后回读 | App 写入与回读已有实机记录;完整分区切换尚未验证 |
|
||
|
||
发送端在有限预算内提交当前帧,超时后转向新帧;本地视频通道与 WebView 会放弃滞留超过 100 ms 的旧帧。这个期限约束的是本机积压,**不代表相机到屏幕的端到端延迟**。
|
||
|
||
> [!WARNING]
|
||
> 固件维护会写入设备 Flash。使用前核对芯片、分区和备份,并阅读[已验证与未验证范围](docs/maintenance/firmware.md#已验证--未验证)。ESP32-S3 与 ESP32-C3 的固件不能混用。
|
||
|
||
[^performance]: [最新帧处理记录](docs/testing/realtime.md)、[功率与拥塞记录](docs/testing/power.md)和[延迟测量](docs/testing/latency.md)保留了配置、观察窗口与测量限制。历史数字不是所有部署环境的性能保证。
|
||
|
||
## 快速开始
|
||
|
||
### 1. 无板卡:先看界面
|
||
|
||
安装 Node.js 和 pnpm 后,在仓库根目录执行:
|
||
|
||
```sh
|
||
cd desktop
|
||
pnpm install --frozen-lockfile
|
||
pnpm dev
|
||
```
|
||
|
||
打开 [用户端预览](http://127.0.0.1:1420/) 或 [裁判端预览](http://127.0.0.1:1420/?preview=referee)。预览由浏览器合成状态和画面,无需 Rust 后端或板卡。
|
||
|
||
> [!TIP]
|
||
> 检查首次启动流程时,可使用 `?preview=first-run` 和 `?preview=password`。需要测试实际接收、重组和录制路径时,使用原生客户端的 `--demo` 模式;两种方式显示的都是合成数据。
|
||
|
||
### 2. 连接板卡:运行桌面端
|
||
|
||
先按[客户端说明](docs/desktop/client.md#快速开始)安装宿主平台依赖。Windows x64 需要 Rust stable MSVC、Visual Studio C++ Build Tools、Windows SDK 和 WebView2;录制另需 ffmpeg。
|
||
|
||
<details>
|
||
<summary><strong>Windows x64:开发运行与安装包</strong></summary>
|
||
|
||
在 `desktop/` 执行。显式指定目标,并清空从根固件项目继承的 `build-std`:
|
||
|
||
```powershell
|
||
pnpm install --frozen-lockfile
|
||
pnpm app --target x86_64-pc-windows-msvc -- --locked --config 'unstable.build-std=[]'
|
||
```
|
||
|
||
生成 NSIS 安装包:
|
||
|
||
```powershell
|
||
pnpm tauri build --target x86_64-pc-windows-msvc --bundles nsis --ci -- --locked --config 'unstable.build-std=[]'
|
||
```
|
||
|
||
安装包位于 `desktop/src-tauri/target/x86_64-pc-windows-msvc/release/bundle/nsis/`。显示名为 **RMIC::2026**,Windows 可执行文件和安装包使用 **RMIC-2026**。
|
||
|
||
</details>
|
||
|
||
<details>
|
||
<summary><strong>macOS / Linux:目标选择与演示模式</strong></summary>
|
||
|
||
`desktop/.cargo/config.toml` 默认目标为 `aarch64-apple-darwin`。Intel Mac 使用 `x86_64-apple-darwin`,常见 Linux x64 使用 `x86_64-unknown-linux-gnu`;其他架构先用 `rustc +stable -vV` 核对 host。
|
||
|
||
以 Linux x64 为例,在 `desktop/` 执行:
|
||
|
||
```sh
|
||
pnpm install --frozen-lockfile
|
||
pnpm app --target x86_64-unknown-linux-gnu -- --locked --config 'unstable.build-std=[]'
|
||
```
|
||
|
||
同一命令末尾追加 `-- --demo` 可启动原生演示模式。它将合成数据报送入正常接收与重组路径,适合检查截图、录制和命中反馈;预览与演示的区别见[客户端说明](docs/desktop/client.md#演示模式没有板子也能把整条链路跑起来)。
|
||
|
||
</details>
|
||
|
||
首次启动选择用户端或裁判端。用户端需要设置现场密码并绑定本车板卡;裁判端自动分配图传槽位,装甲板按上报队伍分配。对应关系不符时,在设置中手动指定。
|
||
|
||
### 3. 编译图传或装甲固件
|
||
|
||
| 硬件 | 构建目标 | 入门文档 |
|
||
| :--- | :--- | :--- |
|
||
| Freenove ESP32-S3-WROOM CAM + OV5640 | `xtensa-esp32s3-espidf` | [环境、参数与烧录](docs/setup/firmware.md) |
|
||
| ESP32-C3 装甲板主板 | `riscv32imc-esp-espidf` | [接线、规则与构建](docs/hardware/armor.md) |
|
||
|
||
<details>
|
||
<summary><strong>已装好图传工具链:构建命令</strong></summary>
|
||
|
||
先按[固件入门](docs/setup/firmware.md)安装固定的 `esp-1.97.0.0` 工具链与 ESP-IDF 依赖。在仓库根目录准备 `.env`;已有文件时不要覆盖。
|
||
|
||
Windows PowerShell:
|
||
|
||
```powershell
|
||
if (-not (Test-Path -LiteralPath .env)) {
|
||
Copy-Item -LiteralPath .env.example -Destination .env
|
||
}
|
||
# 用编辑器填写 .env 中的 Wi-Fi 配置后再构建。
|
||
.\scripts\build.ps1 -Package
|
||
```
|
||
|
||
Linux / macOS(Bash):
|
||
|
||
```bash
|
||
test -f .env || cp .env.example .env
|
||
# 用编辑器填写 .env 中的 Wi-Fi 配置后再构建。
|
||
. "$HOME/export-esp.sh"
|
||
scripts/build.sh --package
|
||
```
|
||
|
||
上述命令只构建和打包。烧录步骤、引脚与分区偏移请按[固件入门](docs/setup/firmware.md)核对;不要将 ELF 当作 BIN 写入。
|
||
|
||
</details>
|
||
|
||
Wi-Fi 凭据会编入固件。`.env` 已被 Git 忽略,分享固件前也需检查其中的凭据。
|
||
|
||
## 发现与收流时序
|
||
|
||
```mermaid
|
||
sequenceDiagram
|
||
participant Board as ESP32-S3 图传板
|
||
participant Client as 桌面 Rust 核心
|
||
participant View as WebView 画面
|
||
|
||
Board-->>Client: Hello 广播(每 2 秒,含版本与协议号)
|
||
Client->>Board: Subscribe(每 800 ms 续订)
|
||
Note over Board,Client: 按订阅包源地址推流;6 秒未续订则移除
|
||
|
||
loop 采集与发送
|
||
Board-->>Client: JPEG 分片(27 字节头 + 最多 1400 字节载荷)
|
||
alt 分片完整且通过接收检查
|
||
Client->>View: 本地通道投递完整 JPEG
|
||
View->>View: 解码并绘制最新有效帧
|
||
else 缺片或超时
|
||
Client->>Client: 丢弃未完成帧,等待后续帧
|
||
end
|
||
end
|
||
```
|
||
|
||
分片按 `sender_id` 和 `frame_id` 隔离,不重传缺失分片。线路格式、去重和拒收条件见 [UDP 协议](docs/protocol/udp.md)。
|
||
|
||
## 仓库结构
|
||
|
||
| 路径 | 职责 | 说明 |
|
||
| :--- | :--- | :--- |
|
||
| [`src/`](src/) | ESP32-S3 固件 | 采集、分片、发现订阅、发送与重连 |
|
||
| [`components/`](components/) | C 组件与 FFI | 本地相机驱动、封装及补丁 |
|
||
| [`protocol/`](protocol/) | 共享线路协议 | 编解码与帧重组,可在主机测试 |
|
||
| [`desktop/core/`](desktop/core/) | 桌面核心 | 网络、装甲板、配置、密码与槽位 |
|
||
| [`desktop/src-tauri/`](desktop/src-tauri/) | Tauri 后端 | 本地通道、命令、录制与固件维护 |
|
||
| [`desktop/src/`](desktop/src/) | React 前端 | 用户端、裁判端、维护与延迟校准 |
|
||
| [`armor/`](armor/) | ESP32-C3 独立 workspace | 受击规则、灯带与血量广播 |
|
||
| [`scripts/`](scripts/) | 构建与诊断工具 | 烧录、打包、版本、协议与性能探测 |
|
||
| [`reference/armor/`](reference/armor/) | 早期 C 版参考工程 | 用于核对硬件与实现差异 |
|
||
| [`docs/`](docs/index.md) | 项目文档 | 入门、开发、硬件、测试、发布与提案 |
|
||
|
||
> [!CAUTION]
|
||
> `components/esp32-camera/target/` 是按芯片分类的**驱动源码**,包含本地补丁。它不是构建缓存,不能随其他 `target/` 目录一起清理。
|
||
|
||
## 开发与验证
|
||
|
||
按修改范围运行对应检查。主机 Rust 测试需显式选择宿主目标,避免继承 ESP32 的构建配置;各平台说明见[开发与验证](docs/development/firmware.md)。
|
||
|
||
<details>
|
||
<summary><strong>前端检查与 Windows 主机 Rust 检查</strong></summary>
|
||
|
||
前端命令在 `desktop/` 执行:
|
||
|
||
```sh
|
||
pnpm build
|
||
pnpm test:stream
|
||
pnpm test:latency
|
||
```
|
||
|
||
以下 Rust 命令在仓库根目录执行:
|
||
|
||
```powershell
|
||
cargo +stable test --locked --manifest-path protocol/Cargo.toml --target x86_64-pc-windows-msvc --config 'unstable.build-std=[]'
|
||
cargo +stable test --locked --manifest-path desktop/core/Cargo.toml --target x86_64-pc-windows-msvc --config 'unstable.build-std=[]'
|
||
cargo +stable check --locked --manifest-path desktop/src-tauri/Cargo.toml --target x86_64-pc-windows-msvc --config 'unstable.build-std=[]'
|
||
```
|
||
|
||
录制相关测试会调用 ffmpeg / ffprobe。主机测试、前端构建通过后,仍需按变更范围检查真实 WebView、板卡与网络行为。
|
||
|
||
</details>
|
||
|
||
提交使用 Conventional Commits,如 `docs(readme): 完善项目入口`。版本由 Git 历史计算,在根目录执行:
|
||
|
||
```sh
|
||
node scripts/version.mjs --write
|
||
node scripts/version.mjs --check
|
||
```
|
||
|
||
生成的改动记录位于 `docs/releases/`;派生文件清单见[版本维护](docs/development/versioning.md)。
|
||
|
||
## 文档与后续工作
|
||
|
||
文档沿用 Firefox 仓库的分类与索引思路:根目录保留项目入口和协作约定,详细说明集中到 [`docs/index.md`](docs/index.md)。
|
||
|
||
| 要做什么 | 从哪里开始 |
|
||
| :--- | :--- |
|
||
| 首次准备图传板 | [固件入门](docs/setup/firmware.md) → [硬件接线](docs/hardware/camera.md) |
|
||
| 使用或调试桌面端 | [客户端说明](docs/desktop/client.md) → [故障排查](docs/testing/troubleshooting.md) |
|
||
| 更新设备固件 | [固件维护](docs/maintenance/firmware.md) |
|
||
| 修改受击规则或灯带 | [装甲板说明](docs/hardware/armor.md) |
|
||
| 复核帧率和延迟 | [最新帧记录](docs/testing/realtime.md) → [延迟测量](docs/testing/latency.md) |
|
||
| 参与开发 | [AGENTS.md](AGENTS.md) → [开发与验证](docs/development/firmware.md) |
|
||
|
||
实现状态与待验证事项分开记录:
|
||
|
||
- [x] UDP 图传、发现订阅与桌面双模式
|
||
- [x] 装甲板血量上报、HUD、命中反馈与录制
|
||
- [x] USB 固件包校验、App 写入与回读
|
||
- [ ] 完成固件维护的完整实机分区切换验证
|
||
- [ ] 确认并实现[比赛控制与直播提案](docs/design/match-and-broadcast.md)
|
||
|
||
<details>
|
||
<summary><strong>仓库地址</strong></summary>
|
||
|
||
仓库已由 `ESP32S3_vt` 改名为 `simba-rmic-2026`,旧地址会重定向。SSH 地址:
|
||
|
||
```text
|
||
git@git.simba-robotics.com:PRAM/simba-rmic-2026.git
|
||
```
|
||
|
||
</details>
|