# 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
硬件 JPEG"] --> Firmware["采集与分片
最新帧发送"]
end
subgraph Armor["装甲板 · ESP32-C3"]
Piezo["四路压电片"] --> Rules["受击规则与整车血量"]
Rules --> LEDs["四路 WS2812"]
end
subgraph Desktop["RMIC::2026 · 桌面端"]
Core["Rust 核心
发现、重组与血量状态"]
Backend["Tauri 后端
本地通道、截图与录制"]
UI["React / WebView
用户端或裁判端"]
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。
Windows x64:开发运行与安装包
在 `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**。
macOS / Linux:目标选择与演示模式
`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#演示模式没有板子也能把整条链路跑起来)。
首次启动选择用户端或裁判端。用户端需要设置现场密码并绑定本车板卡;裁判端自动分配图传槽位,装甲板按上报队伍分配。对应关系不符时,在设置中手动指定。
### 3. 编译图传或装甲固件
| 硬件 | 构建目标 | 入门文档 |
| :--- | :--- | :--- |
| Freenove ESP32-S3-WROOM CAM + OV5640 | `xtensa-esp32s3-espidf` | [环境、参数与烧录](docs/setup/firmware.md) |
| ESP32-C3 装甲板主板 | `riscv32imc-esp-espidf` | [接线、规则与构建](docs/hardware/armor.md) |
已装好图传工具链:构建命令
先按[固件入门](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 写入。
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)。
前端检查与 Windows 主机 Rust 检查
前端命令在 `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、板卡与网络行为。
提交使用 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)
仓库地址
仓库已由 `ESP32S3_vt` 改名为 `simba-rmic-2026`,旧地址会重定向。SSH 地址:
```text
git@git.simba-robotics.com:PRAM/simba-rmic-2026.git
```