docs: 修正 README.md 中与实际代码不一致的描述
This commit is contained in:
@@ -1,27 +1,36 @@
|
|||||||
# AimBot Web
|
# Vision-Web — AimBot Web 控制前端
|
||||||
|
|
||||||
基于 Vue 3 的机器人远程控制前端,提供自动监控、手动遥控和 PID 调参三个功能页面。
|
基于 Vue 3 的机器人远程控制前端,提供实时视频监控、手动键盘遥控和在线 PID 调参三个功能页面。
|
||||||
|
|
||||||
## 技术栈
|
## 技术栈
|
||||||
|
|
||||||
| 层 | 技术 |
|
| 层 | 技术 |
|
||||||
|----|------|
|
|----|------|
|
||||||
| 框架 | Vue 3.5 (Composition API, `<script setup>`) |
|
| 框架 | Vue 3.4 (Composition API, `<script setup>`) |
|
||||||
| 构建 | Vite 5 + pnpm |
|
| 构建 | Vite 5 + pnpm |
|
||||||
| 路由 | Vue Router 4 (Hash 模式) |
|
| 路由 | Vue Router 4 (Hash 模式) |
|
||||||
| ROS 通信 | roslibjs → rosbridge WebSocket |
|
| ROS 通信 | roslibjs → rosbridge WebSocket |
|
||||||
| HTTP | 原生 fetch |
|
| HTTP | 原生 fetch |
|
||||||
|
| 视频流 | MJPEG (web_video_server 提供 HTTP 流) |
|
||||||
|
|
||||||
## 项目结构
|
## 页面
|
||||||
|
|
||||||
|
| 路由 | 页面 | 说明 |
|
||||||
|
|------|------|------|
|
||||||
|
| `#/auto` | AutoMode | MJPEG 视频流,一键切换为自动模式 |
|
||||||
|
| `#/manual` | ManualMode | 键盘遥控底盘 (WASD) 和云台 (方向键),J 键控制激光 |
|
||||||
|
| `#/debug` | DebugMode | 在线 PID 参数调节,激光开关,模式切换 |
|
||||||
|
|
||||||
|
## 目录结构
|
||||||
|
|
||||||
```
|
```
|
||||||
src/
|
src/
|
||||||
├── main.js # 入口,挂载 App + Router
|
├── main.js # 入口,挂载 App + Router
|
||||||
├── App.vue # 根布局:顶部导航 + router-view
|
├── App.vue # 根布局:顶部导航 + router-view
|
||||||
├── config.js # 集中配置(地址、话题、控制参数)
|
├── config.js # 集中配置(地址、话题、控制参数、API 端点)
|
||||||
├── router/index.js # Hash 路由表
|
├── router/index.js # Hash 路由表
|
||||||
├── composables/
|
├── composables/
|
||||||
│ └── useRosbridge.js # roslibjs 封装 Hook
|
│ └── useRosbridge.js # roslibjs 封装 Composable
|
||||||
└── views/
|
└── views/
|
||||||
├── AutoMode.vue # 自动模式页
|
├── AutoMode.vue # 自动模式页
|
||||||
├── ManualMode.vue # 手动遥控页
|
├── ManualMode.vue # 手动遥控页
|
||||||
@@ -31,201 +40,102 @@ src/
|
|||||||
## 架构分层
|
## 架构分层
|
||||||
|
|
||||||
```
|
```
|
||||||
┌─────────────────────────────────────────────────────────┐
|
View 层 (views/*.vue)
|
||||||
│ View 层 (views/*.vue) │
|
- 页面 UI 与用户交互
|
||||||
│ - 页面 UI 与用户交互 │
|
- 调用 useRosbridge + config + fetch
|
||||||
│ - 调用 composable + config │
|
Composable 层 (composables/useRosbridge.js)
|
||||||
├─────────────────────────────────────────────────────────┤
|
- 封装 roslibjs 连接/发布/生命周期
|
||||||
│ Composable 层 (composables/useRosbridge.js) │
|
- 暴露响应式 connected 状态
|
||||||
│ - 封装 roslibjs 连接 / 发布 / 生命周期 │
|
- 组件卸载时自动断开 WebSocket
|
||||||
│ - 暴露响应式 connected 状态 │
|
Config 层 (config.js)
|
||||||
├─────────────────────────────────────────────────────────┤
|
- 所有可配置常量集中管理
|
||||||
│ Config 层 (config.js) │
|
- 部署时只需修改此文件中的 IP 地址
|
||||||
│ - 所有可配置常量集中管理 │
|
Router 层 (router/index.js)
|
||||||
│ - 部署时只需修改此文件 │
|
- Hash 路由 /auto → /manual → /debug → 重定向到 /auto
|
||||||
├─────────────────────────────────────────────────────────┤
|
|
||||||
│ Router 层 (router/index.js) │
|
|
||||||
│ - Hash 路由,/auto → /manual → /debug │
|
|
||||||
│ - 默认重定向到 /auto │
|
|
||||||
└─────────────────────────────────────────────────────────┘
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## 路由设计
|
## config.js 配置项
|
||||||
|
|
||||||
| 路径 | 页面 | 说明 |
|
| 常量 | 默认值 | 说明 |
|
||||||
|------|------|------|
|
|------|--------|------|
|
||||||
| `#/auto` | AutoMode | 默认页,MJPEG 视频流 |
|
| `HTTP_API_BASE` | `http://192.168.0.11` | HTTP API 基础地址 |
|
||||||
| `#/manual` | ManualMode | 键盘遥控 + 视频流 |
|
| `ROSBRIDGE_URL` | `ws://192.168.0.11:9090` | rosbridge WebSocket |
|
||||||
| `#/debug` | DebugMode | PID 参数配置 + 激光开关 |
|
| `MJPEG_AUTO_URL` | `...?topic=/vision/result_image&mode=auto` | 自动模式视频流 |
|
||||||
| `#/` | → 重定向到 `#/auto` | |
|
| `MJPEG_MANUAL_URL` | `...?topic=/vision/result_image&mode=manual` | 手动模式视频流 |
|
||||||
|
| `MJPEG_DEBUG_URL` | `...?topic=/vision/debug_image&mode=debug` | 调试模式视频流 |
|
||||||
|
| `CMD_WHEEL_TOPIC` | `/cmd_chassis` | 底盘轮速话题 |
|
||||||
|
| `CMD_GIMBAL_TOPIC` | `/cmd_gimbal` | 云台角速度话题 |
|
||||||
|
| `BASE_SPEED` | 10 | 线速度值 |
|
||||||
|
| `YAW_VELOCITY` | 5.0 | 角速度值 (度/秒) |
|
||||||
|
| `GIMBAL_PITCH_DEG_S` | 10 | 云台俯仰速率 (度/秒) |
|
||||||
|
| `GIMBAL_YAW_DEG_S` | 10 | 云台偏航速率 (度/秒) |
|
||||||
|
|
||||||
选用 Hash 路由 (`createWebHashHistory`) 是为了避免部署到 Nginx 后直接访问子路径出现 404。
|
## 页面功能
|
||||||
|
|
||||||
## 页面详解
|
### AutoMode(自动模式)
|
||||||
|
|
||||||
### 1. AutoMode(自动模式)
|
- MJPEG 实时视频流显示
|
||||||
|
- 两个按钮将云台和底盘切换为自动模式
|
||||||
|
- 离开页面时自动断开 MJPEG 连接 (img.src = "")
|
||||||
|
|
||||||
**功能:** 显示自动运行过程的实时画面。
|
### ManualMode(手动模式)
|
||||||
|
|
||||||
**数据流:**
|
键盘遥控,支持多键同时按下:
|
||||||
|
|
||||||
```
|
```
|
||||||
web_video_server ──MJPEG──► <img src> ──► 浏览器渲染
|
W/S — 前进/后退 (线速度 ±BASE_SPEED)
|
||||||
|
A/D — 左转/右转 (角速度 ±YAW_VELOCITY)
|
||||||
|
↑/↓ — 云台俯仰 (角速度 ±GIMBAL_PITCH_DEG_S 度/秒)
|
||||||
|
←/→ — 云台偏航 (角速度 ±GIMBAL_YAW_DEG_S 度/秒)
|
||||||
|
J — 激光开关 (e.repeat 防重发)
|
||||||
```
|
```
|
||||||
|
|
||||||
**交互:**
|
发布策略:
|
||||||
- 「切换到当前模式」按钮 → `POST /api/mode/switch { mode: "auto" }` → ROS2 后端切换工作模式
|
- requestAnimationFrame 循环,仅在速度值变化时通过 rosbridge 发布
|
||||||
|
- 无按键时自动停止循环,不发送消息
|
||||||
|
- `/cmd_chassis` 发布 `Float32MultiArray([linear, angular])`
|
||||||
|
- `/cmd_gimbal` 发布 `Twist` (angular.y=pitch, angular.z=yaw)
|
||||||
|
|
||||||
**MJPEG 连接管理:**
|
底盘差速解算由 ROS2 后端节点负责,前端直接发送线速度和角速度。
|
||||||
- 组件挂载时 `<img>` 加载 MJPEG 流
|
|
||||||
- `onBeforeRouteLeave` 钩子中清空 `img.src`,确保离开页面时立即释放 TCP 连接
|
|
||||||
- 路由跳转顺序:旧页面断连 → 新页面建连,避免单连接服务端的冲突
|
|
||||||
|
|
||||||
### 2. ManualMode(手动模式)
|
### DebugMode(调试模式)
|
||||||
|
|
||||||
**功能:** 键盘遥控机器人底盘和云台,J 键控制激光,同时观看实时画面。
|
在线 PID 参数调节:
|
||||||
|
|
||||||
**数据流:**
|
- **云台 PID (4 组 × Kp/Ki/Kd):** 视觉环 Yaw/Pitch, 角度环 Yaw/Pitch
|
||||||
|
- **底盘 PID (3 组 × Kp/Ki/Kd):** 速度环, 角度环, 位置环
|
||||||
|
- 挂载时自动通过 HTTP GET 加载当前 PID 配置
|
||||||
|
- 「保存配置」按钮通过 HTTP POST 将参数写入后端并下发至 MCU
|
||||||
|
- 激光开关按钮和模式切换按钮
|
||||||
|
- rosbridge 连接状态指示器
|
||||||
|
|
||||||
|
## HTTP API
|
||||||
|
|
||||||
|
| 接口 | 方法 | 说明 | 调用位置 |
|
||||||
|
|------|------|------|----------|
|
||||||
|
| `/api/gimbal/mode/switch` | POST | 云台模式切换 | 所有页面 |
|
||||||
|
| `/api/chassis/mode/switch` | POST | 底盘模式切换 | 所有页面 |
|
||||||
|
| `/api/laser` | POST | 激光开关 | ManualMode J 键, DebugMode 按钮 |
|
||||||
|
| `/api/gimbal/pidconfig` | GET/POST | 云台 PID 读写 | DebugMode |
|
||||||
|
| `/api/chassis/pidconfig` | GET/POST | 底盘 PID 读写 | DebugMode |
|
||||||
|
|
||||||
|
## ROS 话题 (rosbridge 发布)
|
||||||
|
|
||||||
|
| 话题 | 类型 | 数据 | 使用位置 |
|
||||||
|
|------|------|------|----------|
|
||||||
|
| `/cmd_chassis` | `Float32MultiArray` | `[linear, angular]` | ManualMode |
|
||||||
|
| `/cmd_gimbal` | `geometry_msgs/Twist` | `angular.y=pitch, angular.z=yaw` | ManualMode |
|
||||||
|
|
||||||
|
## 通信架构
|
||||||
|
|
||||||
```
|
```
|
||||||
键盘事件 (keydown/keyup)
|
Vue3 前端
|
||||||
│
|
├── fetch → Nginx :80 → /api/* → web_node :8080 → ROS2 话题
|
||||||
├─► pressed Set (WASD/方向键 多键集合)
|
├── roslibjs → rosbridge :9090 → ROS2 话题 (/cmd_chassis, /cmd_gimbal)
|
||||||
│ │
|
└── <img> → web_video_server :8081 → MJPEG 流
|
||||||
│ ▼
|
|
||||||
│ computeVelocities() ◄── config.js
|
|
||||||
│ │
|
|
||||||
│ ├─► { left, right } ──► /cmd_wheel (值变化时发送)
|
|
||||||
│ └─► { pitch, yaw } ──► /cmd_gimbal (值变化时发送)
|
|
||||||
│ │
|
|
||||||
│ ▼
|
|
||||||
│ rosbridge ──► ROS2 节点
|
|
||||||
│
|
|
||||||
└─► J 键 (!e.repeat)
|
|
||||||
│
|
|
||||||
▼
|
|
||||||
POST /api/laser { action: "on"|"off" } ──► ROS2 HTTP 服务
|
|
||||||
```
|
```
|
||||||
|
|
||||||
**键盘映射策略:**
|
## 开发
|
||||||
|
|
||||||
```
|
|
||||||
W (+线速度) ↑ (+pitch 度/秒)
|
|
||||||
A (+角速度) D (-角速度) ← (+yaw 度/秒) → (-yaw 度/秒)
|
|
||||||
S (-线速度) ↓ (-pitch 度/秒)
|
|
||||||
|
|
||||||
底盘 (差速驱动) 云台 (角度速率)
|
|
||||||
J 激光 开/关
|
|
||||||
```
|
|
||||||
|
|
||||||
- **多键同时按下**:W+A 同时按 = 前进 + 左转,自动合成左右轮速
|
|
||||||
- **同轴冲突**:W+S 同时按 → 相互抵消,线速度为 0
|
|
||||||
- **值变化才发布**:比较当前速度与上次发布值,无变化则跳过,避免无效 rosbridge 消息
|
|
||||||
- **自动启停**:首个按键按下启动 `requestAnimationFrame` 循环,所有按键松开启自动停止(publish 值不变的帧直接跳过)
|
|
||||||
- **J 键防重复**:`e.repeat` 过滤,长按 J 不会反复切换激光
|
|
||||||
|
|
||||||
**差速运动学转换:**
|
|
||||||
|
|
||||||
```
|
|
||||||
left_speed = linear - angular × (wheel_separation / 2)
|
|
||||||
right_speed = linear + angular × (wheel_separation / 2)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 3. DebugMode(调试模式)
|
|
||||||
|
|
||||||
**功能:** PID 参数在线调参,激光开关,模式切换。
|
|
||||||
|
|
||||||
**交互:**
|
|
||||||
- 顶部三个按钮可切换任意模式
|
|
||||||
- **激光开关按钮**:「激光: ON/OFF」点击切换,`POST /api/laser { action: "on"|"off" }`
|
|
||||||
- 12 个数字输入框分 4 组:
|
|
||||||
- 视觉环 Yaw 电机:Kp / Ki / Kd
|
|
||||||
- 视觉环 Pitch 电机:Kp / Ki / Kd
|
|
||||||
- 角度环 Yaw 电机:Kp / Ki / Kd
|
|
||||||
- 角度环 Pitch 电机:Kp / Ki / Kd
|
|
||||||
- 「发布参数」按钮 → rosbridge 发布 JSON 到 `/pid_config` 话题
|
|
||||||
|
|
||||||
**发布数据格式:**
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"visual_yaw": { "kp": 1.0, "ki": 0.1, "kd": 0.01 },
|
|
||||||
"visual_pitch": { "kp": 1.0, "ki": 0.1, "kd": 0.01 },
|
|
||||||
"angle_yaw": { "kp": 2.0, "ki": 0.2, "kd": 0.02 },
|
|
||||||
"angle_pitch": { "kp": 2.0, "ki": 0.2, "kd": 0.02 }
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## useRosbridge — 核心 Composable
|
|
||||||
|
|
||||||
```
|
|
||||||
useRosbridge()
|
|
||||||
│
|
|
||||||
├─ connect(url) → 建立 WebSocket,绑定 connection/close/error 事件
|
|
||||||
├─ disconnect() → 手动断开
|
|
||||||
├─ publish(topic, type, data) → 发布消息(自动缓存 Topic 对象)
|
|
||||||
├─ connected (ref) → 响应式连接状态
|
|
||||||
│
|
|
||||||
└─ onUnmounted() → 组件销毁时自动断开
|
|
||||||
```
|
|
||||||
|
|
||||||
- 每次调用 `useRosbridge()` 创建独立的 ros 实例
|
|
||||||
- Topic 对象按 `"topic:messageType"` 缓存,避免重复创建
|
|
||||||
- 组件卸载 (`onUnmounted`) 自动关闭 WebSocket,无需手动清理
|
|
||||||
|
|
||||||
## config.js — 配置项说明
|
|
||||||
|
|
||||||
```js
|
|
||||||
HTTP_API_BASE // HTTP API 基础地址
|
|
||||||
ROSBRIDGE_URL // rosbridge WebSocket,格式 ws://host:9090
|
|
||||||
MJPEG_AUTO_URL // 自动模式 MJPEG 流地址
|
|
||||||
MJPEG_MANUAL_URL // 手动模式 MJPEG 流地址
|
|
||||||
CMD_WHEEL_TOPIC // 底盘轮速话题名
|
|
||||||
CMD_GIMBAL_TOPIC // 云台角速度话题名
|
|
||||||
PID_CONFIG_TOPIC // PID 参数话题名
|
|
||||||
MAX_LINEAR // 最大线速度 (m/s)
|
|
||||||
MAX_ANGULAR // 最大角速度 (rad/s)
|
|
||||||
WHEEL_SEPARATION // 底盘轮距 (m)
|
|
||||||
GIMBAL_PITCH_DEG_S // 云台 pitch 角度速率 (度/秒)
|
|
||||||
GIMBAL_YAW_DEG_S // 云台 yaw 角度速率 (度/秒)
|
|
||||||
```
|
|
||||||
|
|
||||||
## HTTP API 接口一览
|
|
||||||
|
|
||||||
| 接口 | 方法 | 请求体 | 说明 | 触发位置 |
|
|
||||||
|------|------|--------|------|----------|
|
|
||||||
| `/api/mode/switch` | POST | `{"mode": "auto"\|"manual"\|"debug"}` | 切换工作模式 | Auto/Manual/Debug 页面按钮 |
|
|
||||||
| `/api/laser` | POST | `{"action": "on"\|"off"}` | 激光开关 | Manual J 键, Debug 按钮 |
|
|
||||||
|
|
||||||
## 通信架构总览
|
|
||||||
|
|
||||||
```
|
|
||||||
┌─────────────────────────────────────────────────────────┐
|
|
||||||
│ Vue3 前端 │
|
|
||||||
│ │
|
|
||||||
│ AutoMode.vue ────► fetch POST /api/mode/switch │
|
|
||||||
│ ────► <img src="/stream?topic=..."> │
|
|
||||||
│ ManualMode.vue ─► roslibjs ws://host:9090 │
|
|
||||||
│ ──► <img src="/stream?topic=..."> │
|
|
||||||
│ ──► fetch POST /api/laser (J 键) │
|
|
||||||
│ DebugMode.vue ──► roslibjs ws://host:9090 │
|
|
||||||
│ ───► fetch POST /api/mode/switch │
|
|
||||||
│ ───► fetch POST /api/laser (按钮) │
|
|
||||||
└──────────┬──────────────┬───────────────────────────────┘
|
|
||||||
│ HTTP │ WebSocket + MJPEG
|
|
||||||
▼ ▼
|
|
||||||
┌─────────┐ ┌──────────────┐
|
|
||||||
│ Nginx │ │ rosbridge │
|
|
||||||
│ 反代 │ │ web_video │
|
|
||||||
└────┬────┘ │ _server │
|
|
||||||
│ └──────┬───────┘
|
|
||||||
▼ ▼
|
|
||||||
ROS2 HTTP ROS2 话题
|
|
||||||
模式切换 底盘 / 云台 / PID
|
|
||||||
激光开关
|
|
||||||
```
|
|
||||||
|
|
||||||
## 开发命令
|
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm install # 安装依赖
|
pnpm install # 安装依赖
|
||||||
@@ -233,3 +143,5 @@ pnpm dev # 开发服务器 → http://localhost:5173
|
|||||||
pnpm build # 生产构建 → dist/
|
pnpm build # 生产构建 → dist/
|
||||||
pnpm preview # 预览构建产物
|
pnpm preview # 预览构建产物
|
||||||
```
|
```
|
||||||
|
|
||||||
|
部署时将 `dist/` 目录部署至 Nginx 静态文件路径 (`/var/www/aimbot/`)。
|
||||||
|
|||||||
Reference in New Issue
Block a user