File size: 6,060 Bytes
50cd0bb
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# Tello 的飞控到底是怎么被控制的

写这份东西的起因:4–5 秒 SSVEP 判决锁定之后,无人机要 1–2 秒才动,而且**连 `takeoff` 也延迟、延迟还很稳定**。
要判断这 1–2 秒能不能消掉,必须先搞清楚指令进了无人机之后走的是什么路径。

SDK 与参考实现下载在 `third_party/`(已 gitignore,DJI 的 PDF 不可再分发):

```
third_party/tello_sdk_docs/   Tello_SDK_1.0 / 1.3 / 2.0 / 3.0 PDF + 官方 Tello3.py
third_party/DJITelloPy/       文本 SDK 的 Python 封装 (MIT)
third_party/TelloPy/          逆向出来的原生二进制协议 (hanyazou, 2018)
```

**第一个发现:DJI 根本没有提供"SDK 库"。** 官方 `Tello3.py` 只有 70 行 —— 一个 UDP socket、一个接收线程、一个 `input()` 循环。
就这样。所谓 Tello SDK 就是**一份文本协议规范**,没有任何飞控抽象层。

---

## 三层结构

```
┌─ Layer 2  文本 SDK shim(跑在固件里)
│    command / takeoff / land / forward 30 / cw 90 / rc a b c d / stop
│    ↑ UDP 8889 文本,这是我们唯一能碰到的接口
├─ Layer 1  原生二进制协议(DJI 官方 App 说的话)
│    STICK_CMD 0x0050 + TAKEOFF 0x0054 / LAND 0x0055 / FLIP 0x005c
│    THROW_AND_GO 0x005d / PALM_LAND 0x005e / BOUNCE 0x1053
│    ATT_LIMIT 0x1058 / SET_ALT_LIMIT 0x0058
└─ Layer 0  飞控(闭源)
     姿态环 → 速度环 → 位置环 → 4 个电机
     传感器:IMU + 气压计 + 下视光流 VPS + ToF
```

## Layer 1:飞控的输入其实只是"四个摇杆"

`third_party/TelloPy/tellopy/_internal/tello.py:495` —— 原生协议里的飞行控制指令长这样:

```python
axis1 = int(1024 + 660.0 * self.right_x) & 0x7ff   # roll
axis2 = int(1024 + 660.0 * self.right_y) & 0x7ff   # pitch
axis3 = int(1024 + 660.0 * self.left_y)  & 0x7ff   # throttle
axis4 = int(1024 + 660.0 * self.left_x)  & 0x7ff   # yaw
axis5 = int(self.fast_mode) & 0x01                 # 运动模式 1 bit
packed = axis1 | (axis2 << 11) | (axis3 << 22) | (axis4 << 33) | (axis5 << 44)
```

四个 11 bit 轴 + 1 bit,打包进 6 字节,加时间戳和 CRC,**在接收循环里持续不断地发**
(`tello.py:755`,每收到一个遥测包就回发一次摇杆包;官方 App 据报是每 50 ms 一次)。

**关键结论:原生协议里没有"移动 30 厘米"这种指令。** 离散指令只有起飞、降落、翻滚、抛飞、掌降、弹跳。
其余一切飞行动作都是摇杆量。**飞控是一个连续设定点系统,不是一个指令队列。**

## Layer 2:`forward 30` 是固件自己造出来的

SDK 3.0 文档给了决定性的证词。它对 `rc a b c d` 的描述是:

> Set the **lever force** values for the four channels of the **remote control**
> a: roll, b: pitch, c: throttle, d: yaw ——  Possible Response: **No response**

"遥控器四个通道的杆量" + "无响应" —— 这就是 Layer 1 的摇杆包,**直通,没有任何额外闭环**。

而 `forward 30` 呢?飞控里没有这个原语,所以固件里的 shim 必须**自己合成一次机动**:

1. 把 pitch 杆推上去(斜坡)
2. 用 VPS 光流 + IMU 积分位移,判断 30 cm 走完了没有
3. 刹车、回中
4. 等位置环重新锁定
5. **然后才回 `ok`**

这一条把之前观察到的所有现象全解释了:

| 现象 | 原因 |
|---|---|
| `ok` 要等动作做完才回 | 它是"机动完成"的信号,不是"收到" |
| 没有指令队列 | shim 是一个单机动状态机,不是队列 |
| 最小 20 cm | 再短了 VPS 位移估计闭不了环 |
| `stop` "works at any time" | 它是这个状态机的 abort |
| 一次移动 1–2 秒 | 斜坡 + 积分 + 刹车 + 重新锁定的总和 |

`takeoff` 走的是另一条完全不同的路:直接映射到原生 `TAKEOFF_CMD 0x0054`,触发固件里固定的
解锁 → 电机爬升 → IMU/VPS 自检 → 爬到约 1 m 的时序。

## 所以那个稳定的 1–2 秒仍然不在无人机里

这次读完 SDK 反而把结论钉得更死了:**`takeoff` 和 `forward 30` 在无人机内部除了 UDP 文本解析器之外没有任何共享代码。**
一个是固件固定时序,一个是 VPS 闭环机动 —— 两者的固有耗时没有理由相等。

**一个对两条指令都相同、而且稳定的延迟,只能来自它们共同的上游,也就是主机软件。**
诊断方法见 `src/control/latency_probe.py``src/control/latency_test.py`## 可以拿来用的东西

**① 在线控制只用 `rc`。** 维护一个设定点,20 Hz 持续发 `rc a b c d`,判决一变就改设定点,
保持 T 毫秒后归零。延迟 = 一跳 UDP + 一个飞控周期 ≈ 30–70 ms,而不是 1–2 秒。
顺带当 keepalive(Tello 长时间收不到指令会自己降落)。

**② 两个只在原生协议里、文本 SDK 完全没暴露的调节量:**

- `ATT_LIMIT_CMD = 0x1058` —— 姿态(最大倾角)限制。**倾角上限就是加速度上限**,直接决定它多快能动起来。`TelloPy.set_att_limit()`
- 摇杆包里的 `fast_mode` bit —— 运动模式,抬高速度/姿态限幅

想榨响应速度就得走 TelloPy 那条二进制路,文本 SDK 里没有这两个旋钮。

**③ 编码里一个有意思的细节:** 轴是 11 bit(0–2047,中位 1024),但 App 只用 `±660`,
也就是只用了可用行程的 65%。协议层面还有余量 —— 但**飞控会不会接受 >660 的杆量我没验证过**,可能被限幅。别当成结论。

**④ SDK 3.0 新增的 `motoron` / `motoroff`(预转电机)可以省掉起飞时的电机启动时间,
但 SDK 3.0 是 Tello EDU / RoboMaster TT 的**,标准版 Tello 大概会回 `error`。
可以试一条 —— 注意 `motoron` 会真的把桨转起来。

---

参考:[Tello SDK 2.0](https://dl-cdn.ryzerobotics.com/downloads/Tello/Tello%20SDK%202.0%20User%20Guide.pdf) ·
[Tello SDK 3.0](https://dl.djicdn.com/downloads/RoboMaster+TT/Tello_SDK_3.0_User_Guide_en.pdf) ·
[DJITelloPy](https://github.com/damiafuentes/DJITelloPy) ·
[TelloPy](https://github.com/hanyazou/TelloPy) ·
[tellopilots 低层协议 wiki](https://tellopilots.com/wiki/protocol/)