反向实现设备 WebSocket 控制协议,提供单次命令与常驻长连接两种模式。
核心内容:
- robot-ctl.py 单次命令客户端,纯标准库无依赖
- robot-daemon.py 常驻守护进程,维持唯一长连接,
解决断开丢尾帧导致的速度残留
- rc.sh 向守护进程注入动作,内置 stable=1 硬锁
- docs/PROTOCOL.md 协议逆向与踩坑记录
- tests/fake-robot-ws.js 离线验证用假设备
实测标定 (50% 速度):
- 前进/后退 ~8 cm/s
- 左转/右转 ~35 deg/s
已知限制:
- 设备为 Arduino WebSocketsServer,纯单向,不回传状态
- 仅摇杆与跳跃有效,linear/angular/方向键无效
- 网页与脚本不可同时连接,会互相覆盖帧
158 lines
4.1 KiB
Markdown
158 lines
4.1 KiB
Markdown
# WL-PRO 轮组机器人遥控
|
||
|
||
用脚本驱动 WL-PRO 轮组机器人,绕开网页界面。
|
||
|
||
**版本**:1.0
|
||
|
||
---
|
||
|
||
## 这是什么
|
||
|
||
WL-PRO 的网页遥控页(`http://<device>/`)通过 WebSocket 向设备端口 **81** 发 JSON 帧。
|
||
本项目直接复现这个协议,让你能从命令行、脚本或自动化流程里控制机器人。
|
||
|
||
包含两种工作模式:
|
||
|
||
| 模式 | 文件 | 适用 |
|
||
|---|---|---|
|
||
| 单次命令 | `robot-ctl.py` | 局域网直连、一次性动作 |
|
||
| 常驻守护 | `robot-daemon.py` + `rc.sh` | 远程 / 需要持续保持连接 |
|
||
|
||
**远程场景请用常驻模式**,原因见 [docs/PROTOCOL.md](docs/PROTOCOL.md) 的「为什么必须常驻」。
|
||
|
||
---
|
||
|
||
## 快速开始
|
||
|
||
### 局域网直连(最简单)
|
||
|
||
```bash
|
||
python3 robot-ctl.py --host 192.168.4.1 joy 0 50 1000
|
||
```
|
||
|
||
### 远程常驻(推荐)
|
||
|
||
```bash
|
||
# 1. 启动守护进程(保持唯一长连接)
|
||
setsid nohup python3 robot-daemon.py --host <公网IP> --port <映射端口> \
|
||
> daemon.log 2>&1 < /dev/null &
|
||
echo $! > daemon.pid
|
||
|
||
# 2. 下发动作
|
||
bash rc.sh go 50 1000 # 前进 1 秒
|
||
bash rc.sh jump # 跳一下
|
||
bash rc.sh stop # 立即停
|
||
```
|
||
|
||
---
|
||
|
||
## 协议要点
|
||
|
||
设备只接受**摇杆**和**跳跃**,其他字段无效(实测)。
|
||
|
||
每帧完整 JSON:
|
||
|
||
```json
|
||
{
|
||
"dir": "stop", "mode": "basic", "roll": 0, "height": 38,
|
||
"linear": 0, "angular": 0, "stable": 1,
|
||
"joy_x": 0, "joy_y": 50
|
||
}
|
||
```
|
||
|
||
| 字段 | 范围 | 说明 |
|
||
|---|---|---|
|
||
| `joy_y` | -100 ~ 100 | 正=前进,负=后退 |
|
||
| `joy_x` | -100 ~ 100 | 正=右转,负=左转 |
|
||
| `dir` | `stop` / `jump` | 只有 `jump` 有效 |
|
||
| `stable` | 0 / 1 | 主动保持平衡,**必须保持 1** |
|
||
| `height` | 32 ~ 85 | 站高 mm |
|
||
| `roll` | -30 ~ 30 | 设备侧无效,固定 0 |
|
||
| `linear` / `angular` | — | 设备侧无效,固定 0 |
|
||
|
||
---
|
||
|
||
## 实测标定值(50% 速度)
|
||
|
||
设备响应**非线性**,以下仅在 `joy` 绝对值 50 附近有效。
|
||
|
||
| 动作 | 参数 | 实测 |
|
||
|---|---|---|
|
||
| 前进 / 后退 | `joy_y = ±50` | **≈ 8 cm/s** |
|
||
| 左转 / 右转 | `joy_x = ±50` | **≈ 35 °/s** |
|
||
| 跳跃 | `dir: jump` | 点动 300ms |
|
||
|
||
**距离换算**
|
||
|
||
| 目标 | 时长 |
|
||
|---|---|
|
||
| 5 cm | 600 ms |
|
||
| 10 cm | 1200 ms |
|
||
| 20 cm | 2500 ms |
|
||
| 30 cm | 3800 ms |
|
||
| 50 cm | 6000 ms |
|
||
|
||
**角度换算**
|
||
|
||
| 目标 | 时长 |
|
||
|---|---|
|
||
| 15° | 430 ms |
|
||
| 35° | 1000 ms |
|
||
| 45° | 1300 ms |
|
||
| 90° | 2600 ms |
|
||
| 180° | 5100 ms(建议分两段) |
|
||
|
||
> 速度低于约 50% 时推进力不足,机器人基本不动。超过 80% 明显更快但更难控。
|
||
> 单次动作超过 3 秒,轮子打滑和地面不平会让误差累积,长距离建议分段执行并中途校正。
|
||
|
||
---
|
||
|
||
## 安全约束
|
||
|
||
本项目内置以下硬约束,防止误操作:
|
||
|
||
1. **`stable` 恒为 1** —— 主动保持平衡不可通过脚本关闭
|
||
2. **`height` 恒为 38 / `roll` 恒为 0** —— 动作帧不会意外改变姿态
|
||
3. **动作帧自动补停止帧** —— 到期立即归零
|
||
|
||
第 1 条在 `rc.sh` 里有显式拒绝分支:
|
||
|
||
```bash
|
||
$ bash rc.sh stable 0
|
||
[rc] 拒绝:主动保持平衡不允许关闭(用户明确指令)。
|
||
```
|
||
|
||
---
|
||
|
||
## 文件说明
|
||
|
||
| 文件 | 作用 |
|
||
|---|---|
|
||
| `robot-ctl.py` | 单次命令客户端,纯标准库,无依赖 |
|
||
| `robot-daemon.py` | 常驻守护进程,维持唯一长连接 |
|
||
| `rc.sh` | 向守护进程注入动作(写状态文件) |
|
||
| `docs/PROTOCOL.md` | 协议逆向细节与踩坑记录 |
|
||
| `docs/device-page.html` | 设备原始网页快照(协议参考) |
|
||
| `tests/fake-robot-ws.js` | 假设备,用于离线验证帧格式 |
|
||
|
||
---
|
||
|
||
## 依赖
|
||
|
||
- Python 3.7+(`robot-ctl.py` / `robot-daemon.py` 仅用标准库)
|
||
- Node.js 18+(仅 `tests/fake-robot-ws.js` 需要,需 `ws` 包)
|
||
|
||
---
|
||
|
||
## 已知限制
|
||
|
||
1. **设备不回传状态** —— 固件是 Arduino WebSocketsServer,纯单向,无法确认动作是否生效,只能靠肉眼观察
|
||
2. **同一时刻只能一个客户端** —— 网页和脚本同时连会互相覆盖指令
|
||
3. **无位置反馈** —— 不能闭环控制,长距离移动会累积误差
|
||
|
||
---
|
||
|
||
## 许可
|
||
|
||
MIT,见 [LICENSE](LICENSE)。
|