1. 先看全局:位置环、速度环在PX4控制链里的确切位置
1.1 一条命令从“航点”到“电机转速”要过几道关卡
先说结论:PX4的多旋翼控制是一个标准级联结构,从上到下大致是“期望位置 → 位置环 → 期望速度 → 速度环 → 期望加速度 → 姿态环 → 期望角速度 → 角速度环 → 混控器 → 电机转速”。位置环和速度环位于整个控制链路最靠外的两层,它们负责的是“飞去哪、飞多快、以什么加速度改变运动状态”,而姿态环和角速度环负责的是“机体该怎么倾斜、转得多快”,混控器最后才把控制量分给四个(或更多)电机。
如果你在地面站里下发一个航点,飞控并不是直接算“油门多少、倾斜多少”然后飞过去。它先要把航点转换成位置设定点,再把位置偏差变成期望速度,接着把速度偏差变成期望加速度,最后才由姿态控制去执行这个加速度。我见过不少刚接触PX4源码的开发者,一进代码目录就直接去找“油门输出”,结果绕了半天都串不起来。根源就在于没有先在脑子里搭出这条级联路径。
在自动任务模式下,期望位置来自航线脚本或任务规划器;在Position模式下,操纵杆会被映射成速度设定点,位置环更多起修正作用;在自稳模式里,位置环和速度环甚至会直接旁路。无论输入来源怎么变,mc_pos_control模块最终对外输出的统一接口都是“推力矢量”,也就是期望加速度。记住这一点,你就拿到了读源码的第一把钥匙。
1.2 为什么非要拆成两个环,不直接一个PID从位置算推力
新手最容易问的问题就是:位置偏差直接映射到期望加速度不行吗?从控制理论的角度看确实可行,但实际工程里这样做的下场多半是炸鸡,原因有两个。
第一个原因是物理约束。飞行器的最大速度、最大加速度都不是无限的。如果直接从位置算加速度,位置误差一大,输出加速度立刻顶到推力上限,电机进入饱和,飞机变成“油门和姿态乱打”的状态。中间加一个速度环以后,我们可以把期望速度限制在安全范围内(比如MPC_XY_CRUISE),把期望加速度限制在推力范围内(比如MPC_ACC_HOR)。位置环只负责“该往哪飞”,速度环只负责“该推多重”,各管一摊,参数也更容易整定。
第二个原因是模式切换。PX4有手动、高度、位置、任务等一大票模式,不同模式下用户输入可能是速度、角度甚至是角速度。如果所有模式都统一换算成加速度指令,从自稳切到Position模式时,飞控看到的只是速度期望的变化,而不是猛然进入一套全新的控制逻辑。这个“软切换”体验,靠单个大PID是做不出来的。
理解了这两个原因,再去读PositionControl相关源码,你会明显感觉思路顺了:外环输出速度,内环输出加速度,这个划分本身就是工程对物理世界妥协的产物。
2. 位置环:把“位置差”翻译成“飞多快”
2.1 位置环的输入、输出和那条基础比例公式
位置环的输入,在mc_pos_control模块里通常来自三个地方:期望位置(航线、任务、RTL等产生)、当前位置(由EKF等估计器融合输出)、期望速度前馈(航点生成器提供的参考速度)。它要做的事情,就是算出一个合理的期望速度。
核心公式很朴素:
期望速度 = Kp_pos × (期望位置 − 当前位置) + 期望速度前馈
水平方向的Kp_pos对应参数MPC_XY_P,垂直方向对应MPC_Z_P。位置误差越大,期望速度越大;误差为零时,期望速度只保留前馈部分。这里要特别注意,位置环在PX4里基本是纯比例控制,没有积分,微分也几乎不用。
为什么位置环不加积分?因为位置误差的积分会带来明显的过冲和回弹,而且位置环已经是外环,积分积累的错误没有更外层的环节去兜底。真正需要积分去消除常值误差的地方在速度环,位置环只要保证“方向正确、速度受限”就够了。
位置环输出也不是无上限的。水平方向不能超过MPC_XY_CRUISE,这个参数决定了自动模式下的水平巡航速度;垂直方向则受上升、下降最大速度限制。换句话说,就算飞机离目标点十米远,位置环也不会命令它以几十米每秒的速度飙过去,而是会顶到限幅值,以一个安全速度匀速靠近。这条限幅逻辑在排查“飞机为什么飞得像没睡醒”时经常被人忽略。
2.2 航点生成器:位置环前面的“隐形规划师”
如果你只在悬停模式下做小范围移动,位置环看起来确实就是一条比例公式而已。但只要开始跑航线任务,你就会发现飞机并不是“直愣愣地冲向目标点”,而是会提前减速、平滑转弯、甚至在多航点连续切换时走出很柔和的曲线。这个效果来自航点生成器,也常被叫作轨迹生成器。
航点生成器的职责,是把一个位置跳跃变成一条带速度约束的路径。它会根据当前位置、目标位置以及最大速度、最大加速度、最大加加速度这三个限制,生成一组“位置设定点 + 速度设定点”序列。每个控制周期,位置环拿到的不是“最终目标点”,而是这条平滑路径上当前该去的位置和当前该有的速度。这个细节经常被教程一句带过,但恰恰是决定飞行是否“丝滑”的核心。
位置环里的“速度前馈”项,就因为航点生成器的存在才有意义。如果没有前馈,位置环只能靠比例项去“追”位置,靠近目标时速度自然衰减,但响应总有滞后;有了前馈,位置环只需要承担修正偏差的工作,跟踪精度和顺滑度都会明显提升。这就是为什么两台同样机架、同样参数的飞机,一个用航线模式跑起来行云流水,另一个却显得一顿一顿。
相关参数里,MPC_JERK_MAX是最容易被忽略的一个。加加速度描述的是加速度变化快慢,值越小,飞机启动和刹车的过渡越柔和;值太大,飞机会有“弹出去又急停”的感觉。很多人调了半天位置环P,手感还是怪,最后发现是Jerk限制在捣乱。
2.3 位置环P值的手感:按收敛曲线判断,而不是凭感觉
拿水平位置环MPC_XY_P来说,常见初值在0.9上下。这个值的物理含义可以粗略理解为:1米的位置误差,大约会产生1米每秒的期望速度。这个比例关系很直观,也是我判断参数大小最常用的方法。
P值调大,位置收敛更快,但对位置估计噪声和风扰更敏感;P值调小,飞行姿态更平稳,但到达目标点附近会显得“懒洋洋”,半天才停稳。实际调试时,我习惯在Position模式下做小步长阶跃:在地面站里把期望位置挪动0.5米到1米,然后观察位置环输出和实际位置的收敛过程。如果收敛过程中有一次明显超调,说明P偏大;如果收敛慢且稳态误差长时间不消失,说明P偏小,或者该去检查速度环状态。
有一句话我在新手培训时反复强调:位置环调的是“外面那层皮”,真正决定响应手感的是里面那层速度环。所以别对着位置环P猛调,先把速度环的收敛速度调到位,再回来动位置环。这个顺序保证了你能分清“外环过度驱动”和“内环响应不足”两种完全不同的故障特征。
3. 速度环:读取“速度差”,输出“加速度”
3.1 速度环的PID三项在真实飞行中各自是什么角色
速度环的输入是期望速度与实际速度的差,输出是期望加速度。水平方向是一个完整的PID,核心关系可以写成:
期望加速度 = Kp_vel × 速度误差 + Ki_vel × 速度误差积分 + Kd_vel × 速度误差微分
比例项MPC_XY_VEL_P是主力。速度慢了,命令加速度向前;速度快了,命令加速度向后。它和位置环的比例项叠加在一起,构成一个典型的二阶阻尼系统:位置环提供“弹性”,速度环提供“阻尼”,二者配合,飞机才不会像弹簧一样乱跳。这个类比我在代码评审会上经常用:位置环是弹簧,速度环是减震器,缺了减震器的弹簧一定会来回弹。
积分项MPC_XY_VEL_I负责长时偏差。悬停时如果一直有风,或者重心不居中,速度误差不会归零,比例项无法完全消除这个偏差,积分项就在后面慢慢“补账”,直到实际速度等于期望速度。但积分项也是最容易翻车的一项,后边我会专门讲抗饱和的问题。
微分项MPC_XY_VEL_D平时用得最少。因为它要对速度误差求导,而速度估计本身带有噪声,微分项会把噪声放大成加速度抖动,表现出来就是电机声音发涩、机身高频微抖。所以我的建议是:先不开D,等P和I都调完,确认阻尼确实不足,再给一点点。多数机架根本不需要这D项。
3.2 加速度怎么变成机体的“歪头”和“油门”
速度环输出的是期望加速度。这个加速度在PX4里会跟重力加速度合成,变成一个期望推力矢量。为了产生水平方向的加速度,机体必须倾斜;为了保持高度,推力在垂直方向的分量必须刚好抵消重力。一句话总结:水平加速度越大,机体倾斜角越大;总推力越大,油门越大。
这段关系意味着速度环之后还有一个姿态环。姿态环的任务是执行期望倾斜角,角速度环再去执行期望角速度。如果你把速度环参数调得很激进,期望加速度很大,但姿态环增益不够高,机体倾斜跟不上,实际加速度就不会按期望值出现。表现在飞行日志里,就是期望速度收敛很快,实际速度却拖了一条长长的尾巴。
这解释了为什么有些飞机速度环怎么调都“调不猛”。问题可能根本不在速度环,而在姿态环接收端。调参顺序必须由内向外:先确认姿态环能快速精确执行期望姿态,再去动位置和速度这两层外环。内环响应不到位,外环参数再漂亮也是空中楼阁。
3.3 积分抗饱和:速度环里最容易被忽略的安全机制
积分项最容易出问题的地方就是“积分饱和”。我拿一个真实场景说明:飞机在Position模式下被强风吹偏,位置误差瞬间变大,位置环输出的期望速度直接顶到MPC_XY_CRUISE限幅,速度误差也变得很大,于是速度环积分项开始快速累积。等飞机回到目标点附近,位置误差变小、速度误差也变小,但积分项里还留着刚才那一大笔“旧账”,继续输出额外加速度,飞机就会冲过目标再抽回来,形成明显的来回抽动,严重时甚至会“点头”。
PX4源码对积分项做了限幅处理:一旦输出加速度触顶,积分就不再继续增加;整体输出还会限制在MPC_ACC_HOR等加速度上限内。这是一种标准的抗饱和做法,但不同固件版本的实现细节有差异,有的加条件分支,有的做积分冻结,有的干脆重置积分。排查问题时如果发现“速度环好像总在乱发力”,先看限幅逻辑有没有按预期工作。
我带过的不少开发者都踩过同一个坑:速度环I值照抄别人的“神参数”,结果自己一飞就抽风。原因多半不是I数值本身不对,而是飞行条件、机体重量、限幅参数都不一样。我的建议是,I初值给一个很小的量,比如0.1到0.2,先让系统稳定,再根据悬停漂移情况慢慢加,每次幅度不超过50%。
3.4 垂直速度环:跟水平方向有哪些不一样
垂直方向同样有位置环和速度环,结构类似,但有两个差异值得单独说。
第一,垂直方向不需要“倾斜”来实现加速度,它直接改变总推力。所以垂直速度环的输出大部分直接映射为推力指令,响应通常比水平方向更直接、更快。你在日志里对比水平方向和垂直方向的速度跟踪曲线,会发现垂直方向收敛更快、超调更小。
第二,垂直方向的加速度上限不对称。多旋翼的上升推力通常远大于下降能力,所以PX4用MPC_ACC_UP_MAX和MPC_ACC_DOWN_MAX分开限制上升和下沉加速度。下降过快时,电机转得再慢也受气动阻力限制,所以下降速度通常比上升速度低。调参时不要把上下限设成同一个值,也不要觉得“参数越大越灵活”,上限设置不当会让高度控制变得非常生硬。
调垂直速度环的方法和水平方向类似,但高度估计多来自气压计和加速度计融合,气压计受气流影响明显。测试时不要在风机、空调出风口附近进行,否则高度数据跳动会让你误判控制器参数。这一点说起来是常识,但真到了现场,很多人都会被一块跳动的气压计带偏。
4. 参数速查表与一套可复现的调参顺序
4.1 主要参数一览
先放一张速查表,方便后续对照。要注意的是,不同固件版本、不同机架类型的默认值和参数命名可能有差异,以下数值更多是经验参考区间,落地时务必以你自己固件版本的源码注释和地面站参数说明为准。
| 控制层面 | 参数名称 | 作用说明 | 参考建议 |
|---|---|---|---|
| 位置环(水平XY) | MPC_XY_P | 位置偏差到期望速度的增益 | 常见初值0.9左右 |
| 位置环(垂直Z) | MPC_Z_P | 高度偏差到期望垂直速度的增益 | 常见初值1.0附近 |
| 速度环(水平P) | MPC_XY_VEL_P | 速度偏差到期望加速度的增益 | 常见初值3到5,从小往大调 |
| 速度环(水平I) | MPC_XY_VEL_I | 消除水平常值速度偏差 | 建议从0.1到0.3开始 |
| 速度环(水平D) | MPC_XY_VEL_D | 速度误差变化率的阻尼 | 默认很小,多数情况不需要 |
| 速度环(垂直P) | MPC_Z_VEL_P | 垂直速度偏差到推力冗余的增益 | 常见值2到4 |
| 水平速度限制 | MPC_XY_CRUISE | 自动模式水平巡航速度上限 | 根据任务速度需求设置 |
| 水平加速度限制 | MPC_ACC_HOR | 水平期望加速度上限,也决定最大倾斜角 | 常见值6左右 |
| 垂直加速度限制 | MPC_ACC_UP_MAX / MPC_ACC_DOWN_MAX | 上升/下降最大加速度 | 上升值通常大于下降值 |
| 轨迹平滑 | MPC_JERK_MAX | 加加速度上限,影响航线顺滑度 | 需要柔和就调小 |
这张表最右侧一列是经验区间,不是精确默认值。固件升级后参数名都可能变,死记数值没有意义,理解每个参数的作用才重要。你看日志和地面站的参数说明时,心里要有这么一张“功能地图”,而不是盯着数字发愣。
4.2 从自稳到位置模式的完整调参流程
我自己惯用的调参顺序,基本遵循“由内而外、一次只动一个”的原则。按这个顺序走,能最大程度避免“动了位置环结果速度环在振荡”这种认知混乱。
第一步,在自稳模式确认姿态环稳定。解锁后小幅打杆,听电机声、看机身响应。如果姿态环本身就在振荡,后面所有外环都白调。这一步很多教程会跳过,但它是整条链路的基石。
第二步,切到Position模式,先调速度环P。不急着挪位置设定点,就在原地悬停,用手轻轻推一下飞机,观察它回到悬停点的速度和超调。P从小往大加,出现来回抽动就退回约20%。这个阶段你会看到速度环收敛变紧实,但机身不该出现高频抖动。
第三步,调速度环I。悬停时如果发现飞机往某个方向持续漂移,给一点I,观察漂移是否收敛。I大了以后最常见的问题是“回来时过头一点又拉回”,看到这种就说明I过头了。
第四步,调位置环P。在地面站发一个小距离阶跃,比如前后挪1米,看收敛速度。轻微超调可以接受,明显来回绕一圈以上就降P。
第五步,航线大范围测试。在足够空旷的场地飞几段连续航点,观察转弯段落是否平滑。这一步主要调MPC_ACC_HOR和MPC_JERK_MAX,让加减速曲线符合任务手感。
以上每一步都建议用飞行日志记录。落地后拉出期望速度、实际速度、期望加速度、实际加速度曲线对照,比只看现场手感要可靠得多。手感是定性的,曲线是定量的,两者结合才高效。
4.3 定参数时的三条“铁律”
说起来都是老生常谈,但我确实见过太多人在同一个地方摔跤:
第一,一次只动一个参数。别同时改P和I,否则出了问题你根本分不清是哪个参数引起的。哪怕只动一个参数,也要先看一个完整稳定周期的日志再判断。调参最忌讳的就是“一串参数一起改,然后祈祷它能飞”。
第二,改动幅度别太大。每次调整控制在20%以内比较安全。位置环P从0.9直接跳到2.0这种事,结果多半是激烈振荡甚至现场事故。调参是收紧一个区间,不是赌一次运气。
第三,确认当前控制模式。很多参数只在对应的控制模式下生效。你在高度模式里调位置环P,当然看不出任何变化;在自稳模式里调速度环参数,也不会起作用。实验前先在地面站确认当前模式和位置估计状态,省得白忙一场。
5. 从源码角度看过位置环和速度环是怎么跑起来的
5.1 模块入口和核心调用链
PX4里负责位置和速度控制的源码,主要在mc_pos_control模块下。不同版本文件组织略有差异,但核心逻辑基本围绕两个层面展开:一层负责模式管理、任务状态、输入话题接收;另一层是真正的位置/速度控制类,核心的PositionControl类里就是位置环和速度环的迭代计算。
控制周期内,模块会做这几件事:读取当前控制模式,读取期望位置/速度/加速度设定点(来自航线或航点生成器),读取EKF输出的当前位置与速度估计,然后调用PositionControl的更新接口,输出期望推力矢量或期望加速度,最后交给姿态控制器。
如果你自己去看源码,建议从PositionControl的核心更新函数入手。它内部的执行顺序,基本就是“先位置环、后速度环、最后输出推力矢量”。位置环先算出期望速度,把这个期望速度作为速度环的输入,速度环再算出期望加速度。这个顺序和前面讲的级联结构完全一致,代码只是把理论翻译成了可执行步骤。
5.2 源码里藏着哪些容易被忽略的细节
第一处是速度前馈。位置环公式里的前馈项,不是简单等于航点生成器的速度,PX4里还可能有缩放系数。前馈权重设置得当,可以让跟踪误差明显变小;设置过大,又会掩盖位置环本身的修正作用,导致系统对风扰不敏感。看懂这一项,你就能解释为什么同样的参数,别人飞得比你稳。
第二处是限幅逻辑。位置环输出限幅、速度环输出限幅、积分项限幅,这些逻辑在源码里往往分散在不同的子函数中。出问题时,很多“怪现象”其实都是限幅在起作用。比如期望速度被顶到上限,曲线平得跟直线一样;比如积分被冻结,实际速度迟迟追不上期望速度。看日志时如果发现某条曲线异常平直,第一反应应该是找限幅参数。
第三处是模式切换的衔接。PX4在模式切换时会做状态重置或目标值初始化,比如从手动切到Position模式,位置环会先把当前位置作为新目标,避免“先飞到远处再回来”这类突变。这一块在不同版本的实现细节不一样,升级固件后若发现切换行为变化,优先去查这部分逻辑。
5.3 姿态环到底在消费什么
需要再强调一次:姿态环接收的不是“位置”,也不是“速度”,而是一个期望推力矢量。这个推力矢量由期望加速度与重力加速度合成,再被拆解成期望姿态角和期望总推力。
正因为如此,姿态环参数与位置/速度环参数之间存在耦合。速度环给出一个期望倾斜角,姿态环的响应速度决定了这个倾斜角能不能快速到位。一个实用的排查技巧是:当位置环、速度环调了很久都调不好时,把姿态环的响应拉出来,看看是不是“慢半拍”。如果是,先解决内环响应,再回头看外环参数。很多人卡在“速度环振荡”上,最后发现根因是姿态环带宽不足。
6. 实测中的常见问题与排查思路
6.1 位置设定点附近来回抽动
现象:Position模式下,飞机到达目标点后不是稳稳停住,而是在小范围里来回“画小圈”或前后抽动,周期大约一秒左右。
排查:先看日志里的期望速度与实际速度。如果两条曲线呈明显的正弦状,且期望速度始终领先实际速度,基本可以判断是位置环P过大,速度期望被过度放大。解决办法是降MPC_XY_P,观察一到两个周期。若抽动频率接近姿态环带宽,则需要检查姿态环相位裕度,以及前后通道是否串扰。
还有一种情况是限幅在起作用:位置误差大时,速度命令顶到巡航速度上限,速度环跟踪不及时,产生低频回路振荡。这时除了降P,还可以适当降低MPC_XY_CRUISE,让外环不至于总在极限状态下工作。极限状态下任何小扰动都会被放大成振荡,这不是玄学,是控制系统的基本特性。
6.2 悬停漂移和常值位置偏差
现象:飞控明明处于Position模式,飞机却缓慢向一个方向漂,手动修正回来后过一会儿又漂过去。
排查顺序:先确认机体校准,特别是加速度计零偏和水平校准,再看位置估计输出是否稳定,EKF状态是否健康。如果估计本身没问题,再看速度环积分项是否太小。积分项的存在本来就是吸收外界常值干扰的,太小了就吸收不完。
但积分项不是万金油。如果机体本身重心偏斜,或者机架振动导致加速度计数据带偏差,速度环I会给一个与实际需求相反的“补偿”,反而让姿态维持变得奇怪。所以遇到漂移时,先查机械和校准,再动I值。机械问题靠积分硬补,补到最后就是积分饱和,然后触发前面说的振荡现象。
6.3 高频抖动和电机发涩
现象:悬停时电机声音发涩,机身有高频微小抖动,手摸机臂能感到明显振感。
排查:这种抖振频率通常远高于位置环和速度环的带宽,多半来自姿态环的D项偏大,或角速度估计中的噪声被放大。如果日志里角速度曲线有明显毛刺,优先降低姿态环微分增益,而不是去调速度环。位置环和速度环参数在这个频段几乎帮不上忙,反而可能因为输入信号被处理得过于激烈而诱导姿态环进入极限环。
也有人会碰到“油门轻一下重一下”的低频抽动,这个一般和垂直速度环积分有关,或者和电池电压下降后的推力补偿逻辑有关,要分开排查。高频看姿态环,低频看速度环,这是最初步的“频率分层法”。
6.4 改了参数但完全没反应
现象:在地面站里把参数改了,飞行器实际表现没有任何变化。
排查:先确认模式。只有使用了位置环和速度环的模式,这两个模块才会在回路里起作用。其次确认参数名和固件版本是否匹配,不同版本之间参数编号或命名可能调整。再者,检查参数是否真正写入成功,很多情况下飞控重启后才生效。最后一种可能,是你的测试动作根本没有触发这个环节:比如只做原地悬停测试,却想验证航点生成器的平滑效果,自然什么都看不出来。
这个案例特别适合提醒大家:调参前先给自己一分钟,想清楚“我要验证的参数在哪个环节生效、在哪个模式下才参与控制”。这一步省下来,后面能少飞很多冤枉架次。
6.5 载荷和重心变化后,原来的参数忽然失效
有时候同一套参数,换个电池、加个云台,表现就完全不一样。这不是参数记忆出错,而是飞行器模型变化导致外环增益和姿态增益的相对关系变了。载荷加重时,速度环P通常需要适当增加,因为相同加速度对应更大的推力需求;重心偏移时,左右通道的参数可能需要差异化调整,如果差异过大,先考虑配重而不是改参。
这类问题最典型的表现是:同一台飞机,空机调好了,挂上载荷后出现“右偏后抬头”之类的不对称响应。这时候不要怀疑自己的调参能力,先看重心和机臂刚性,再决定是否动参数。结构问题用参数硬顶,顶出来的参数一定畸形。
7. 我个人试飞过程中积累的三个习惯
最后分享几个很零碎但确实管用的习惯,算不上高深理论,实战里帮了我不少忙。
第一个习惯:把每次调参记录写在表格里。包括改动前的值、改动后的值、天气、风速、电池电量、载荷状态、飞控固件版本。没有这些记录,你调了三轮以后就会出现“到底哪版参数最好”的记忆错乱。人的记忆在连续调试时是不可靠的,只有表格不会骗你。
第二个习惯:先用日志说话,再信手感。手感能帮你快速定位方向,但真正决定最终参数的是日志里那几条响应曲线。尤其是速度环和位置环的振荡,只有曲线能告诉你它是1Hz还是5Hz,是饱和振荡还是增益裕度不足。方向对了再微调,效率能高一倍。
第三个习惯:改参数前先备份当前参数文件。地面站都支持参数导入导出,飞行前导出一份,出了异常还能回到上一个稳定点。这个习惯成本极低,收益却是实打实的。真遇到“越调越差”的时刻,你会发现一个能一键回滚的备份文件比什么都宝贵。
调位置环和速度环这件事,说难也难,说简单也简单。难在它是一个从内环到外环、从参数到机械再到传感器融合的链条,任何一环出问题都会在位置响应上表现出各种形态;简单在只要你理解了级联结构,掌握了“由内而外、一次只动一个参数、一切以日志为准”这三个原则,大部分问题都能找到落脚点。
这个系列如果继续往下走,我比较想写的是航点生成器与轨迹控制的实现细节,以及怎么把今天这些调参结论跟具体航线速度剖面匹配起来。希望对正在啃PX4源码、正在飞调参真机的你能有点用。