4、多项式轨迹表示:多项式函数、最小加加速度轨迹、最小加加加速度轨迹、边界条件设定

各位同学,今天我们来聊聊轨迹优化里最基础、也最核心的一块——多项式轨迹表示。

说实话,我刚入行那会儿,觉得轨迹规划不就是画条曲线嘛,随便搞个三次多项式就完事了。后来在项目里吃过亏,才明白这里面的门道有多深。你想想看,机器人动起来,如果轨迹不平滑,轻则抖动,重则撞机。所以,选对多项式形式、设对边界条件,是后面所有优化的地基。

4.1 为什么是多项式?

多项式函数在轨迹规划里这么受欢迎,说白了就三个原因:

  • 计算简单:求导、求积分都是线性操作,闭式解好算
  • 连续性好:多项式是无限可微的,天然保证平滑
  • 边界可控:通过系数调整,可以精确满足起点和终点的位置、速度、加速度

我个人习惯把多项式轨迹比作「搭积木」。你给定起点和终点的状态(位置、速度、加速度等),多项式就是那个刚好能把这些点串起来的平滑曲线。积木块数越多(多项式阶数越高),你能控制的细节就越多。

4.2 多项式函数的基本形式

一个 n 次多项式长这样:

p(t) = c₀ + c₁·t + c₂·t² + ... + cₙ·tⁿ

其中 t 是时间,c₀ 到 cₙ 是待求的系数。我们通常把时间归一化到 [0, T] 区间,T 是轨迹的总时长。

它的各阶导数就是:

速度:     v(t) = c₁ + 2c₂·t + 3c₃·t² + ... + n·cₙ·tⁿ⁻¹
加速度:   a(t) = 2c₂ + 6c₃·t + ... + n·(n-1)·cₙ·tⁿ⁻²
加加速度: j(t) = 6c₃ + ... + n·(n-1)·(n-2)·cₙ·tⁿ⁻³

嗯,这里要注意:加加速度(Jerk)是加速度的变化率,它直接决定了机器人运动时的冲击感。我在做协作机器人项目时,如果 Jerk 太大,末端执行器上的工件就会晃动,甚至掉落。所以后来我特别关注 Jerk 的约束。

4.3 最小加加速度轨迹(Minimum Jerk Trajectory)

什么叫「最小加加速度」?就是让 Jerk 在整个运动过程中尽可能小。为什么要这么做?因为 Jerk 小,意味着加速度变化平缓,运动就柔和,对机械结构的冲击也小。

数学上,我们最小化这个代价函数:

J = ∫₀ᵀ (j(t))² dt

对于一段从起点到终点的轨迹,如果我们只约束位置、速度、加速度(共 6 个边界条件),那么一个 5 次多项式就能搞定。为什么是 5 次?因为 6 个未知系数对应 6 个方程,刚好有唯一解。

我记得有一次做码垛机器人的轨迹优化,客户要求末端轨迹必须平滑到「感觉不到换向」。我试了三次多项式,结果加速度在起点和终点有跳变,机器人启动时「咯噔」一下。换成五次多项式后,加速度连续了,但 Jerk 还是有点大。最后用了七次多项式,才把 Jerk 也约束住。

核心结论:约束到速度 → 三次多项式;约束到加速度 → 五次多项式;约束到加加速度 → 七次多项式。

4.4 最小加加加速度轨迹(Minimum Snap Trajectory)

加加加速度(Snap)是 Jerk 的导数,也就是位置的四阶导数。最小化 Snap 有什么用?它能让 Jerk 的变化也平缓,进一步减少高频振动。

代价函数变成:

J = ∫₀ᵀ (s(t))² dt

如果你要同时约束位置、速度、加速度、加加速度(共 8 个边界条件),那就需要 7 次多项式。我在做无人机航迹规划时,就特别喜欢用最小 Snap 轨迹。因为无人机对高频振动特别敏感,Snap 一大,飞控就容易震荡。

我的经验:对于地面移动机器人,最小 Jerk 通常就够了。对于高精度或高速场景(如无人机、机械臂高速抓取),建议上最小 Snap。

4.5 边界条件设定

边界条件就是轨迹在起点和终点必须满足的状态。常见的设定方式有:

边界条件 物理含义 典型值
p(0) = p₀, p(T) = p₁ 起点和终点位置 关节角度或笛卡尔坐标
v(0) = v₀, v(T) = v₁ 起点和终点速度 通常为 0(静止到静止)
a(0) = a₀, a(T) = a₁ 起点和终点加速度 通常为 0
j(0) = j₀, j(T) = j₁ 起点和终点加加速度 通常为 0(可选)

我曾经犯过一个错误:在做多段轨迹拼接时,只保证了位置和速度连续,忘了加速度连续。结果轨迹在拼接点处加速度突变,机器人直接抖了一下。从那以后,我给自己定了个规矩:至少保证加速度连续,除非你明确知道不需要。

避坑指南:我曾经在一条生产线上遇到过,边界条件设得太「完美」——位置、速度、加速度、Jerk 全约束了,结果多项式系数变得非常大,轨迹在中间段出现了剧烈的过冲。后来我放宽了 Jerk 的边界条件,让它在起点和终点自由,反而轨迹更平滑。所以,不是约束越多越好,要根据实际物理限制来取舍。

4.6 知识体系总览

下面这张图是我自己整理的,把本章的核心逻辑串起来了:

多项式轨迹表示知识体系 多项式函数 p(t)=c₀+c₁t+...+cₙtⁿ 最小加加速度 Minimize ∫j²dt 最小加加加速度 Minimize ∫s²dt 5次多项式(6个约束) 7次多项式(8个约束) 边界条件:位置、速度、加速度、加加速度 实际应用:机械臂、无人机、移动机器人

从这张图可以看得很清楚:从多项式函数出发,根据你的优化目标(最小 Jerk 还是最小 Snap),选择对应的多项式阶数,然后设定好边界条件,最后落地到实际应用中。每一步都有明确的物理含义和数学对应。

4.7 代码实战:求解五次多项式系数

光说不练假把式。下面我给出一段 Python 代码,演示如何求解五次多项式的系数。这段代码我在好几个项目里复用过了,很稳定。

import numpy as np

def quintic_poly_coeffs(p0, p1, v0, v1, a0, a1, T):
    """
    求解五次多项式系数
    边界条件:位置、速度、加速度在起点和终点
    T: 总时间
    返回:c0~c5 共6个系数
    """
    # 构建约束矩阵
    A = np.array([
        [1, 0,   0,     0,       0,        0],
        [0, 1,   0,     0,       0,        0],
        [0, 0,   2,     0,       0,        0],
        [1, T,  T**2,  T**3,    T**4,     T**5],
        [0, 1,   2*T,   3*T**2,  4*T**3,   5*T**4],
        [0, 0,   2,     6*T,    12*T**2,  20*T**3]
    ])
    
    b = np.array([p0, v0, a0, p1, v1, a1])
    
    # 解线性方程组
    coeffs = np.linalg.solve(A, b)
    return coeffs

# 示例:从静止到静止,移动1米,用时2秒
p0, p1 = 0.0, 1.0
v0, v1 = 0.0, 0.0
a0, a1 = 0.0, 0.0
T = 2.0

c = quintic_poly_coeffs(p0, p1, v0, v1, a0, a1, T)
print("五次多项式系数:", c)

这段代码的核心就是构建一个 6x6 的矩阵 A,把边界条件写成线性方程组,然后求解。你想想看,如果我要加 Jerk 约束,矩阵就变成 8x8,系数变成 7 次多项式。道理是一样的,只是矩阵大了一圈。

小技巧:在实际工程中,我建议把时间 T 归一化到 [0,1] 区间再求解,这样可以避免矩阵条件数过大导致数值不稳定。等系数算出来之后,再通过缩放变换回实际时间。

好了,关于多项式轨迹表示,我就讲这么多。记住一句话:选对阶数、设好边界、算对系数,你的轨迹就成功了一半。剩下的,就是根据实际约束去优化了。

可可精品资料库