本文目标:让完全没有机器学习或数值优化背景的读者,从零开始理解”可微仿真”相关的核心名词。

无人机仿真就是用计算机模拟无人机的飞行——给定一组参数(质量、推力系数等),计算机算出无人机怎么飞。


一、从一道最简单的数学题说起

想象你要解一个问题:

找一个数 xx,使得 x2=9x^2 = 9

很简单,x=3x = 3x=3x = -3,心算就行。

现在换个问题:

找一个数 xx,使得 x32x2+5x17=0x^3 - 2x^2 + 5x - 17 = 0

你还能心算吗?不能了。你需要试:

  • x=2x = 288+1017=78 - 8 + 10 - 17 = -7(太小了)
  • x=3x = 32718+1517=727 - 18 + 15 - 17 = 7(太大了)

介于 2233 之间。

再试 x=2.5x = 2.515.62512.5+12.517=1.37515.625 - 12.5 + 12.5 - 17 = -1.375(还是小了点)

再试 x=2.6x = 2.6…… 这就是手动调参

而”可微”给了你一个捷径:它告诉你,如果你在 x=2.5x=2.5 时答案是 1.375-1.375下一步该往哪个方向走、走多快,而不需要一遍遍地瞎试。

“梯度”就是方向标 + 步长尺

梯度的几何意义:有方向


二、什么叫”可微”?—— 为什么这个性质这么重要

2.1 直观概念

一句话:一个函数如果”可微”,意思是它的输出对输入的变化是平滑的——你稍微动一下输入,输出也会稍微动一下,而且你知道输出会往哪个方向动。

类比:开汽车的方向盘。

  • 💡 可微 = 方向盘是线性连接的。你往右打 1 度,车轮转 1 度,方向平滑改变。你知道”多打一点方向,车就多转一点”。
  • 💀 不可微 = 方向盘是坏的。你拧半天没反应,突然拧到一个角度,车猛甩过去。你不知道”拧多少会转多少”。

2.2 数学定义(公式版,但附白话翻译)

定义

如果函数 y=f(x)y = f(x) 在点 x0x_0 处有导数 f(x0)f'(x_0),则称 ffx0x_0 处可微。

导数的定义为:

f(x0)=limh0f(x0+h)f(x0)h f'(x_0) = \lim_{h \to 0} \frac{f(x_0 + h) - f(x_0)}{h}

白话翻译

xx 变一点点(hh 是一个极小的变化),看 yy 变化了多少。如果 yy 的变化量和 hh 的比值趋近于一个固定的数,那这个数就是导数。导数越大,输入的小变化对输出的影响就越大。

2.3 历史

“可微”和”导数”的概念由牛顿(1643-1727)和莱布尼茨(1646-1716)在 17 世纪末独立创立,是微积分的核心。牛顿用它描述天体运动(月亮绕地球转的速度),莱布尼茨发明了今天我们还在用的微分符号 dydx\frac{dy}{dx}

2.4 为什么要关心”可微”

在仿真中”可微”的区别

1
2
3
4
5
6
7
8
9
传统仿真(不可微):
输入:C_T = 0.11 → 仿真 → 输出:飞行轨迹(一个长长的数字列表)
你只能看结果,想知道 C_T 应该改到多少?
→ 改一次重新跑一次,改一次重新跑一次

可微仿真:
输入:C_T = 0.11 → 可微仿真 → 输出:飞行轨迹 + 梯度
这个梯度告诉你:C_T 增加 0.01,轨迹在第 3 秒的位置会偏右 0.5 米
→ 一次计算就知道该往哪调

核心差别:传统仿真是一维的(输入→输出),可微仿真在输出结果的同时,还告诉你了各输入参数对输出结果的影响程度。

传统仿真 vs 可微仿真对比图


三、梯度:不是魔法,就是一个方向箭头

3.1 概念

梯度是一个向量,它指出”往哪个方向调整参数,能让结果改变得最快”。

3.2 定义

对于一个有多个输入、一个输出的函数 f(x1,x2,...,xn)f(x_1, x_2, ..., x_n),梯度记为:

f=(fx1,fx2,...,fxn) \nabla f = \left( \frac{\partial f}{\partial x_1}, \frac{\partial f}{\partial x_2}, ..., \frac{\partial f}{\partial x_n} \right)

其中 fx1\frac{\partial f}{\partial x_1} 叫”偏导数”,意思是”只改变 x1x_1 这一个参数,其他参数固定,看 ff 怎么变”。

3.3 历史

“梯度”一词来自19世纪数学家麦克斯韦(1831-1879)在电磁场理论中的工作。后来被用于优化问题——柯西(1789-1857)在1847年提出了”最速下降法”,就是用梯度来找函数的最小值。

3.4 手算例子

假设你的函数是 f(x,y)=x2+y2f(x, y) = x^2 + y^2,在点 (1,2)(1, 2) 处求梯度:

fx=2x=2×1=2 \frac{\partial f}{\partial x} = 2x = 2 \times 1 = 2 fy=2y=2×2=4 \frac{\partial f}{\partial y} = 2y = 2 \times 2 = 4 f(1,2)=(2,4) \nabla f(1, 2) = (2, 4)

什么意思?在 (1,2)(1, 2) 这个点,沿着 (2,4)(2, 4) 的方向走,函数值上升最快。反过来,沿着 (2,4)(-2, -4) 的方向走,函数值下降最快。

3.5 在仿真中的应用

回到你的无人机场景:

1
2
3
4
可微仿真给出梯度:

∂(脱靶量)/∂(N) = 2.3 → N 增大,脱靶量增大(变差)
∂(脱靶量)/∂(C_T) = -0.8 → C_T 增大,脱靶量减小(变好)

告诉你一个好消息和一个坏消息。你不关心正负号的来龙去脉,你只需要知道哪个参数往哪个方向调。 这就是梯度做的事。


四、损失函数:就是”差距”的量化

4.1 概念

损失函数衡量”仿真结果和期望结果之间的差距”

  • 损失函数值 = 0 → 完美,仿真和期望完全一致
  • 损失函数值 = 500 → 差得很远

4.2 定义

最常用的损失函数是均方误差(Mean Squared Error, MSE)

L=1ni=1n(y仿真,iy真实,i)2 L = \frac{1}{n} \sum_{i=1}^{n} (y_{\text{仿真}, i} - y_{\text{真实}, i})^2

其中 y仿真,iy_{\text{仿真}, i} 是仿真第 ii 个时间步的值,y真实,iy_{\text{真实}, i} 是真实飞行第 ii 个时间步的值。

4.3 历史

损失函数的概念可以追溯到高斯(1777-1855)和勒让德(1752-1833)在19世纪初发展的最小二乘法——他们用它来根据天文观测数据推算行星轨道。现代机器学习中,”损失函数”成为训练所有模型的核心工具,是反向传播算法(1986年,Rumelhart、Hinton、Williams)的基础。

4.4 手算例子

你有一段真实飞行的轨迹记录:

1
2
真实位置:  0m, 1m, 2m, 3m, 4m  (1秒一个点)
仿真位置: 0m, 1.1m, 2.2m, 3.5m, 4.8m

计算损失:

1
2
3
4
5
第1秒:(1 - 1.1)² = 0.01
第2秒:(2 - 2.2)² = 0.04
第3秒:(3 - 3.5)² = 0.25
第4秒:(4 - 4.8)² = 0.64
平均:(0.01 + 0.04 + 0.25 + 0.64) / 4 = 0.235

损失 = 0.235。这个数字告诉你:你的仿真器和真实飞行偏差挺大的(平均位置偏差约 0.2350.48\sqrt{0.235} \approx 0.48 米)。

你的目标就是让这个损失值降到 0——也就是”最小化损失函数”。

4.5 在你的项目中的意义

场景 损失函数衡量什么 目标
参数辨识 仿真轨迹 vs ULog 实飞轨迹 找到让损失最小的 C_T、C_D
制导律整定 拦截脱靶量(距离目标最近时有多远) 找到让脱靶量最小的 PN 增益 N
域随机化 在最差参数组合下的脱靶量 找到即使参数偏差大也能拦截的参数

五、梯度下降:自动调参的核心引擎

5.1 概念

梯度下降就是:沿着梯度的反方向(因为梯度指向上升最快的方向,我们要下降)一步一步调整参数,使损失函数越来越小。

5.2 定义

参数更新公式:

x=xηf(x) x_{\text{新}} = x_{\text{旧}} - \eta \cdot \nabla f(x_{\text{旧}})

其中 η\eta(读作”eta”)叫学习率,就是”每一步走多大”。

5.3 手算例子

还是之前的函数 f(x)=x2f(x) = x^2,在 x=3x=3 处:

  • 梯度:f(3)=2×3=6f'(3) = 2 \times 3 = 6
  • 学习率 η=0.1\eta = 0.1

更新:

x=30.1×6=30.6=2.4 x_{\text{新}} = 3 - 0.1 \times 6 = 3 - 0.6 = 2.4

等价于:

  • 第 1 步:32.43 \rightarrow 2.4
  • 第 2 步:2.41.922.4 \rightarrow 1.92
  • 第 3 步:1.921.5361.92 \rightarrow 1.536
  • ……
  • 最终趋近于 0(最小值)

和手动调参的对比

梯度下降的步进过程

方法 操作 示例
手动调参 猜→试→再看结果→再猜 调 C_T:0.11→0.12(不行)→0.10→0.09(不行)→0.13(好像行了?)
梯度下降 自动算方向,一次到位 梯度说:C_T 应增大 0.003 → 一次收敛

手动调参每次改完要重新跑一遍仿真(几分钟甚至几小时)。梯度下降告诉你方向,一次计算就够了。


六、域随机化:不猜了,直接让参数变起来

6.1 概念

既然你不知道真实的物理参数是多少,那别猜一个值,而是让参数在一定范围内随机变化

6.2 定义

域随机化将动力学参数 pp 视为随机变量,而不是固定值:

pU(pmin,pmax) p \sim U(p_{\text{min}}, p_{\text{max}})

即每个参数在最小值到最大值之间均匀随机取值

6.3 历史

域随机化在 2017 年由 OpenAI 的团队在论文《Generalizing from Simulation to Real World with Domain Randomization》(arXiv:1710.06457)中系统提出。他们发现,只要在仿真中把参数随机范围设置得足够宽,仿真中训练的模型可以直接用在真实机器人上,不需要任何微调。后来被广泛应用于无人机、机械臂、自动驾驶等领域的 Sim-to-Real 迁移。

6.4 手算例子

域随机化:单值 vs 范围

传统参数辨识:

1
你认为 C_T = 0.11 → 只使用这个值 → 真机是 0.13 → 失控

域随机化:

1
2
3
4
5
6
7
8
C_T 随机范围 [0.08, 0.16]
"仿真 1": C_T = 0.09
"仿真 2": C_T = 0.14
"仿真 3": C_T = 0.11
"仿真 4": C_T = 0.15
...
每次仿真都随机。
结果你的制导算法在 C_T=0.08~0.16 中都能成功拦截。

真机上的 C_T 只要落在这个范围内,算法就自然有效。

6.5 在模块化制导中的应用

对于典型的高速无人机截击仿真场景:

1
2
3
4
5
6
7
8
9
不用改 PN/EPN 的公式,只需在确定 N(导航增益)时:

for i in range(1000): # 1000次随机仿真
C_T = random(0.08, 0.16)
C_D = random(0.01, 0.03)
I_xx = random(0.005, 0.015)
跑仿真,记录拦截是否成功

选择:在最大偏差下也能稳定拦截的 N 值 → 这就是域随机化帮你找到的"鲁棒参数"

七、端到端:把整个流程变成一个黑箱

7.1 概念

端到端就是:放弃”感知模块→规划模块→控制模块”的分步设计,改为输入传感器数据,直接输出电机指令

7.2 与传统模块化的对比

1
2
3
4
5
6
7
8
9
10
11
传统模块化(你现在的方式):

相机 → 目标检测 → 目标跟踪 → 制导律(PN) → 姿态控制(PID) → 电机

要调试 4-5 个模块接口,每层都会丢失信息

端到端:

相机 → [ 一个巨大的神经网络 ] → 电机

从头到尾是一个整体,通过一次训练得到

7.3 历史

“端到端”在自动驾驶领域的里程碑是 NVIDIA 的 DAVE-2 系统(2016 年,Bojarski 等人),用单个神经网络直接从摄像头图像输出方向盘角度。在四旋翼领域,2026 年上海交大的 E2E-Fly(arXiv:2604.12916)首次实现了从仿真训练到真机飞行的零样本迁移。可微仿真是实现这一目标的关键——因为只有可微,梯度才能从最终的电机指令一路反向传播到神经网络的每个参数。

7.4 端到端 vs 非端到端(对你的意义)

你现在用 PN/EPN 制导 + PID 控制,属于”非端到端”方案。这不代表它不好——恰恰相反,它有明确的物理可解释性和可靠性。

端到端适合的是:

  • 感知环节太复杂,传统方法搞不定(比如视觉避障)
  • 传统模块之间信息损耗严重

而你的截击仿真场景:目标位置已知(雷达/外部传感),制导有成熟公式,非端到端是正确选择。

关键洞察:可微仿真对非端到端方案的价值不在于”替换制导律”,而在于更高效地确定制导律参数

传统模块化 vs 端到端


八、这些概念如何连起来?

8.1 一张图看完整流程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
你有的:ULog 真实飞行数据

你改的:C_T, C_D, I_xx, N(参数)

可微仿真:把你的 6DOF 引擎改成"可微"版本

输出:仿真轨迹 + 梯度

损失函数:对比仿真轨迹和真实轨迹

梯度下降:顺着梯度反向走,自动更新参数
↓ 重复几轮
损失趋近于 0 → 仿真像真实飞行了!

再加上域随机化:
在参数范围里随机取值,找"不挑环境"的参数组合

8.2 和你已有工作的关系

你已经在做的 可微仿真带来的改进
参辨识模块的 ULog 参数辨识 从遗传算法(1000 代)→ 梯度下降(50 步),速度快 20 倍
手动调 PN 增益 N 梯度直接告诉你 N 该增加还是减少
6DOF 拦截测试 域随机化帮你找到”参数偏差 30% 也能命中”的鲁棒参数

8.3 不改变的部分

  • 你的 PN/EPN 制导算法不变
  • 你的 PID 增益不变
  • 你的部署代码(飞控参数)不变
  • 你的物理理解不变

改变的只是”参数怎么算出来的”。


九、核心公式速查卡

公式 含义 在本文中的角色
f(x0)=limh0f(x0+h)f(x0)hf'(x_0) = \lim_{h \to 0} \frac{f(x_0+h)-f(x_0)}{h} 导数定义 可微的基础
f=(fx1,...,fxn)\nabla f = (\frac{\partial f}{\partial x_1}, ..., \frac{\partial f}{\partial x_n}) 梯度 = 所有偏导数的向量 告诉你怎么调参数
L=1n(ysimyreal)2L = \frac{1}{n}\sum (y_{\text{sim}} - y_{\text{real}})^2 均方误差损失函数 量化”差距”
xnew=xoldηfx_{\text{new}} = x_{\text{old}} - \eta \nabla f 梯度下降更新公式 自动调参引擎
pU(pmin,pmax)p \sim U(p_{\text{min}}, p_{\text{max}}) 域随机化 不猜一个值,让参数随机变

十、总结

  1. 可微 = 输入的小变化会导致输出平滑变化,你知道变化的”方向”
  2. 梯度 = 告诉你每个参数对结果有多大影响、往哪调
  3. 损失函数 = 一个数字,衡量仿真和真实的差距,0 表示完美
  4. 梯度下降 = 沿着梯度反方向一步步走,自动把损失降到最小
  5. 域随机化 = 不猜精确值,让参数在范围里随机跳,找”不挑环境”的解
  6. 端到端 = 输入原始数据(如摄像头画面),直接输出控制指令,跳过中间模块

这些概念并不是端到端学习的专利。它们本质上是一种”带方向感的计算”。对传统制导算法来说,它们提供的价值是更高效、更系统化的参数整定——让手动的”猜→试→再猜”变成自动化的”计算→更新→收敛”。


参考文献

  1. Bojarski, M., et al. (2016). End to End Learning for Self-Driving Cars. arXiv:1604.07316.
  2. OpenAI. (2017). Domain Randomization for Transferring Deep Neural Networks from Simulation to the Real World. arXiv:1710.06457.
  3. Tobin, J., et al. (2017). Domain Randomization for Transferring Deep Neural Networks from Simulation to the Real World. IEEE/RSJ IROS 2017.
  4. Rumelhart, D. E., Hinton, G. E., & Williams, R. J. (1986). Learning representations by back-propagating errors. Nature, 323(6088), 533-536.
  5. Howell, T. A., et al. (2022). Dojo: A Differentiable Physics Engine for Robotics. arXiv:2203.00806.
  6. E2E-Fly (arXiv:2604.12916) — 端到端四旋翼自主飞行系统。