导数:局部线性近似
用显微镜看一条光滑曲线,放大得足够多,它就变成一条直线。这条直线的斜率就是导数。机器人里几乎所有"线性化"都是这一句话:在工作点附近,把复杂的函数换成一条直线,算起来便宜得多,误差也有明确的上界。
1为什么机器人需要它
轮子上的编码器只会告诉你"现在转到了哪个角度"。可控制器要的是转速,规划器要的是加速度。从位置到速度,中间隔着一次求导。
另一件事更普遍:机器人的世界几乎全是非线性的。关节角到末端位置有 \(\sin\)、\(\cos\),相机投影要除以深度。非线性函数很难直接分析,直线却很好对付。导数就是把曲线在一点附近换成直线的方法:EKF 的线性化、逆运动学的每一步迭代、Newton 法、反向传播,全靠它。
这一节只做三件事:看清导数是什么(一条放大后的直线),知道这个近似好到什么程度(误差随距离的平方缩小),再看一个它会咬人的地方(对带噪声的数据求导)。
2直觉:显微镜下的曲线是直线
地球是圆的,可站在操场上它是平的。曲线上任何一点附近都是这样:放得够大,弯曲就看不出来了。放大后看到的那条直线,斜率就是导数 \(f'(x_0)\)。
下面是一台"显微镜"。拖动黄点选位置,拖动滑块放大。先在平滑的曲线上试,再换成 \(|x|\),看看会发生什么。
- 在光滑曲线上放大到 ×200 以上,直到曲线几乎变成直线。
- 切换到 |x|,把黄点拖到尖角 x = 0,放大到 ×50 以上:曲线始终不变直。
"可导"的意思是:放大后能看到一条直线。导数 \(f'(x_0)\) 就是这条直线的斜率,它回答的问题是"输入动一点点,输出会动多少倍"。\(|x|\) 在尖角处没有这条直线,所以不可导。
3动手玩:从割线到切线
放大镜给了直觉,现在把它变成公式。过曲线上两点 A、B 画一条直线,叫割线,斜率是"纵向增量 / 横向增量"。让 B 向 A 靠近,割线就转成切线。右图画出割线斜率随 \(h\)(B 到 A 的水平距离)的变化:\(h\to 0\) 时它趋向的那个数,就是导数。
- 让 |h| 小于 0.01:割线与切线重合,右图上的点贴到虚线上。
- 切到 |x|,把 A 放在 x = 0,分别从左边和右边把 |h| 压到 0.05 以下:两侧斜率不同。
这个直线近似有多准?
在 \(x_0\) 处用切线代替曲线,在距离 \(\delta\) 处的误差是多少?下面拖动 \(\delta\) 看看。右图是误差随 \(|\delta|\) 变化的双对数图:直线的斜率就是"误差随距离的几次方缩小"。
- 在光滑曲线上,找一个位置使得"δ 减半,误差约变成 1/4"(读数栏里的比值接近 4)。
- 切到 |x|,把 x₀ 放在 0:比值变成 2,不再是 4。
导数本身也是一个函数
每个 \(x\) 都对应一个斜率,把所有斜率画出来就得到导函数 \(f'\)。左边拖动黄点,右边的点会沿 \(f'\) 的图像一起走。
- 在 sin 或三次曲线上,把黄点拖到 f′ = 0 的位置(峰或谷)。
4再看数学
提示:把鼠标悬停在公式中带底色的符号上,FIG 2 中对应的线段会被高亮。
定义
函数 \(f\) 在 \(a\) 处的导数是割线斜率当 \(h\to 0\) 时的极限:
极限存在,等价于从左、右两侧趋近得到同一个数。这正是 \(|x|\) 在 0 处失败的原因。
局部线性近似
把上式移项,就是机器人里最常用的一句话:
误差项里最先出现的是 \(\delta^2\):\(\delta\) 缩小为原来的 1/10,误差缩小为 1/100。\(f''\)(导数的导数,描述曲线弯得多厉害)越大,线性近似失效得越快。完整的展开见 2.4 泰勒展开。
放大镜读法:\(f'(a)\) 是放大后那条直线的斜率。放大倍率读法:输入的一点点变化 \(\Delta x\) 被乘以 \(f'(a)\) 变成输出变化 \(\Delta f\approx f'(a)\,\Delta x\)。第二种读法在多元函数里变成"矩阵乘向量",那就是 3.3 节的雅可比。
常用求导规则
| 规则 | 公式 | 来源 |
|---|---|---|
| 线性 | \((c f + g)' = c f' + g'\) | 极限保持加法和数乘 |
| 乘积 | \((f g)' = f' g + f g'\) | 展开 \((f+\Delta f)(g+\Delta g)\),丢掉 \(\Delta f\,\Delta g\) |
| 幂 | \((x^n)' = n x^{n-1}\) | \((x+h)^2 - x^2 = 2xh + h^2\),除以 \(h\) 再令 \(h\to0\) |
| \(\sin,\cos\) | \((\sin x)' = \cos x,\ (\cos x)' = -\sin x\) | 小角度 \(\sin h\approx h\)(2.4) |
| \(e^x,\ \ln x\) | \((e^x)' = e^x,\ (\ln x)' = 1/x\) | 指数函数是"变化率等于自身"的函数 |
| 复合 | \((f\circ g)' = f'(g)\,g'\) | 下一节 |
数值求导:步长不能太大,也不能太小
用计算机估计导数,最直接的是差商。前向差分 \(\frac{f(x+h)-f(x)}{h}\) 的截断误差约为 \(\tfrac12 f''\,h\),中心差分 \(\frac{f(x+h)-f(x-h)}{2h}\) 的误差约为 \(\tfrac16 f'''\,h^2\),所以中心差分更准。但 \(h\) 也不能太小:两个几乎相等的数相减,舍入误差(双精度约 \(10^{-16}\))被 \(1/h\) 放大。因此双精度下前向差分的最佳 \(h\) 约是 \(10^{-8}\),中心差分约是 \(10^{-5}\)。3.3 节有一个可以拖动步长观察这一现象的实验。
5机器人中的它:从编码器估计转速
编码器每转一圈输出 \(N\) 个脉冲,位置只能被量化到 \(q = 2\pi/N\)。要得到转速,最直接的是对位置求差:\(\hat\omega_n = \dfrac{\theta_n-\theta_{n-k}}{k\,\Delta t}\)。
这里有一个两难。窗口 \(k\) 取得小,响应快,但量化误差 \(\sim q/(k\Delta t)\) 被放大;窗口取得大,噪声小了,估计却滞后(约 \(k\Delta t/2\) 秒)。下面是一个真实的权衡:真实角度 \(\theta(t)=2\sin(0.9t)+0.5t\),采样 100 Hz,编码器把它量化后再求差。
- 设窗口 k = 1:估计乱得不能用(RMS 误差大于 0.2 rad/s)。
- 用"因果"模式、分辨率 ≤ 1024,把 RMS 误差压到 0.065 rad/s 以下。你会发现再怎么调也有一个最低点。
电机驱动器常常同时用两种办法:高速时数脉冲(M 法),低速时测相邻脉冲的间隔(T 法)。想要既无滞后又低噪声,办法是把"求导"改成"估计":用位置、加速度模型加传感器噪声模型,做卡尔曼滤波(4.8 节)。不要对原始数据硬求导,这是机器人里最老的教训之一。
6常见误区
它只在工作点附近好用,误差按 \(\delta^2\) 增长。关节角偏离线性化点 30° 时,\(\sin\theta\approx\theta\) 的误差已经有 5%;EKF 里若状态变化太大,线性化会让滤波器发散。
求导是"高通"操作:它放大高频成分,噪声基本都在高频。位置噪声 \(\sigma\) 进了差分后变成 \(\sqrt2\sigma/\Delta t\),采样越快反而越糟。要么平滑后再差分,要么用滤波器。
\(|x|\) 连续,但在尖角不可导。机器人里的尖角很多:接触瞬间的力、\(\max/\min\)、ReLU、限幅、静摩擦。基于梯度的方法碰到它们要小心,必要时用平滑版本或"次梯度"。
\((\sin x)'=\cos x\) 只在 \(x\) 以弧度为单位时成立。若 \(x\) 以度为单位,导数里会多出一个 \(\pi/180\)。代码里统一用弧度,只在输入输出的边界做换算。
7小练习
8延伸阅读
- 3Blue1Brown, Essence of Calculus — 第 2 章(导数的悖论)与第 3 章(求导公式的几何直觉)
- G. Strang, Calculus (MIT OpenCourseWare) — 第 2 章:导数
- K. Lynch & F. Park, Modern Robotics, 附录:速度与线性化
- T. Barfoot, State Estimation for Robotics, Ch. 2 — 线性化与估计