9.6 KiB
9.6 KiB
AimBot Web
基于 Vue 3 的机器人远程控制前端,提供自动监控、手动遥控和 PID 调参三个功能页面。
技术栈
| 层 | 技术 |
|---|---|
| 框架 | Vue 3.5 (Composition API, <script setup>) |
| 构建 | Vite 5 + pnpm |
| 路由 | Vue Router 4 (Hash 模式) |
| ROS 通信 | roslibjs → rosbridge WebSocket |
| HTTP | 原生 fetch |
项目结构
src/
├── main.js # 入口,挂载 App + Router
├── App.vue # 根布局:顶部导航 + router-view
├── config.js # 集中配置(地址、话题、控制参数)
├── router/index.js # Hash 路由表
├── composables/
│ └── useRosbridge.js # roslibjs 封装 Hook
└── views/
├── AutoMode.vue # 自动模式页
├── ManualMode.vue # 手动遥控页
└── DebugMode.vue # 调试模式页
架构分层
┌─────────────────────────────────────────────────────────┐
│ View 层 (views/*.vue) │
│ - 页面 UI 与用户交互 │
│ - 调用 composable + config │
├─────────────────────────────────────────────────────────┤
│ Composable 层 (composables/useRosbridge.js) │
│ - 封装 roslibjs 连接 / 发布 / 生命周期 │
│ - 暴露响应式 connected 状态 │
├─────────────────────────────────────────────────────────┤
│ Config 层 (config.js) │
│ - 所有可配置常量集中管理 │
│ - 部署时只需修改此文件 │
├─────────────────────────────────────────────────────────┤
│ Router 层 (router/index.js) │
│ - Hash 路由,/auto → /manual → /debug │
│ - 默认重定向到 /auto │
└─────────────────────────────────────────────────────────┘
路由设计
| 路径 | 页面 | 说明 |
|---|---|---|
#/auto |
AutoMode | 默认页,MJPEG 视频流 |
#/manual |
ManualMode | 键盘遥控 + 视频流 |
#/debug |
DebugMode | PID 参数配置 + 激光开关 |
#/ |
→ 重定向到 #/auto |
选用 Hash 路由 (createWebHashHistory) 是为了避免部署到 Nginx 后直接访问子路径出现 404。
页面详解
1. AutoMode(自动模式)
功能: 显示自动运行过程的实时画面。
数据流:
web_video_server ──MJPEG──► <img src> ──► 浏览器渲染
交互:
- 「切换到当前模式」按钮 →
POST /api/mode/switch { mode: "auto" }→ ROS2 后端切换工作模式
MJPEG 连接管理:
- 组件挂载时
<img>加载 MJPEG 流 onBeforeRouteLeave钩子中清空img.src,确保离开页面时立即释放 TCP 连接- 路由跳转顺序:旧页面断连 → 新页面建连,避免单连接服务端的冲突
2. ManualMode(手动模式)
功能: 键盘遥控机器人底盘和云台,J 键控制激光,同时观看实时画面。
数据流:
键盘事件 (keydown/keyup)
│
├─► pressed Set (WASD/方向键 多键集合)
│ │
│ ▼
│ 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话题
发布数据格式:
{
"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 — 配置项说明
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
激光开关
开发命令
pnpm install # 安装依赖
pnpm dev # 开发服务器 → http://localhost:5173
pnpm build # 生产构建 → dist/
pnpm preview # 预览构建产物