
第一次给自己组的四旋翼解锁起飞油门刚推过中点机身就触电一样高频抖动。那股振动顺着机架传到手上我下意识把油门收到底等飞机停下来电机还在发出尖锐的颤音。当时满脑子只有一个念头ROS环境跑通了、飞控通信正常、遥控器也能对上为什么这台无人机就是不听话后来才明白真正决定飞机能不能稳稳悬停的是PID调参。这篇笔记就是我给这台四旋翼做PID调参的完整记录包括实验平台怎么搭、级联PID内外环怎么理解、每个参数改了之后飞机会有什么反应以及我实测中踩过的各种坑。如果你也卡在“起飞就抖”或者“悬停乱飘”这一步这篇文章应该能帮你少走不少弯路。1. 为什么默认参数飞不起来从一次失败的试飞说起1.1 我的实验平台与软件栈先把平台交代清楚因为后面所有参数讨论都得挂靠在具体硬件上。我这台是自组的四旋翼机架F450级别轴距450mm左右起飞重量大概1.6kg。飞控用的Pixhawk 6C固件刷的PX4机载电脑是Jetson Orin Nano上面跑Ubuntu和ROS 2飞控和机载电脑之间用Mavros通信。很多朋友有个误区以为刷完固件、接好GPS、在地面站里校准完传感器飞机就能直接飞了。实际上固件里的默认PID参数只是保证飞机在“出厂测试平台”上勉强能飞不同机架重量、电机响应速度、桨叶尺寸都会让最优参数明显偏移。我的F450第一次解锁起飞默认参数下悬停大概是这样的roll和pitch方向持续小幅振荡高度勉强维持但姿态角波动一度超过五度。这个状态别说航拍稍微来点风就可能翻。1.2 调参前的准备工作调参最忌讳直接上手改参数然后起飞试。我在动手之前把三件事准备齐了后面排查问题时发现每件都省了大量时间。第一是仿真环境。先用Gazebo配合PX4 SITL仿真把基本流程跑通仿真里能安全地试各种极端参数比如把P拉到振荡看飞机的反应模式。仿真和真机有差距但是它帮你建立“参数变化导致什么现象”的直觉这个直觉很重要。第二是日志系统。PX4飞控本身会把完整的姿态、角速度、电机输出记录到SD卡ROS端我同时用ros2 bag记录了Mavros转发的所有话题。第三是地面站和可视化工具。我习惯QGroundControl看实时姿态曲线配套rqt_plot看ROS话题曲线两者可以对照。调参过程中每次试飞旁边都要有人帮忙观察机架姿态我一个人操作的时候只做小幅参数调整不做危险的大幅机动。2. 级联PID内环角速度与外环角度到底谁先管谁2.1 两个环路的分工与串级原因刚开始学PID的时候我也觉得奇怪无人机姿态控制为什么不能用单个PID直接拿目标角度当输入、当前角度当反馈一组参数搞定答案是单环控制在四旋翼这种强耦合、反应快的系统上根本不够用。角度环负责“我想倾斜多少度”角速度环负责“倾斜过程应该多快、多稳”。外环输出的是内环的期望值内环输出的是电机转速指令。这样设计的原因要从动力学角度看。四旋翼产生转动的是电机转速差带来的力矩力矩直接改变的是角速度角速度积分才是角度。控制链路里真正离执行器近的是角速度环它响应快能第一时间抑制扰动角度环在它的外层用相对慢的速度去纠正累积的角度偏差。如果没有内环直接控制角速度外环PID给再大的增益电机也很难快速跟上整机就会表现出迟钝和振荡。所谓级联就是外环的输出作为内环的期望输入。角度环期望姿态和当前姿态的偏差通过P控制器换算成期望角速度然后角速度环再把期望角速度和当前角速度的偏差通过另一个PID换算成电机补偿量。内环打底外环修正各管一段。2.2 Kp、Ki、Kd在姿态环里的物理意义这几个参数听上去抽象放到飞机上其实很好理解。Kp比例项是最直接的“纠错力度”。飞机向右倾斜了它给出一个向左修正的力矩。Kp越大修正越猛但是过大的Kp会让系统反应过头形成振荡。想象一下你骑自行车看到方向偏了猛打龙头结果又会向另一个方向偏往复横跳。Kd微分项是“阻尼”。它根据角速度的变化来刹车抑制机体快速旋转的趋势。Kd越大对姿态变化率的反应越强飞机越“黏”在你想要的角度上。但Kd过大会引入噪声放大因为微分对高频信号极其敏感陀螺仪有一点噪声就会被放大成电机抖动。Ki积分项是“长期纠错”。遇到持续风扰、重心偏移或者机架安装不水平这些固定误差时P和D只能不断抵抗但消不掉稳态误差Ki会累积历史偏差并逐渐给出一个持续修正量。不过四旋翼姿态控制里大部分场景我不太依赖过大Ki因为过大的积分累积很容易造成超调甚至引发低频振荡。PX4默认姿态环的I值就很小够用即可。2.3 内外环时间尺度分离与离散化实现无人机调参有个很重要的直觉内外环的时间尺度必须分开。外环角度环响应慢内环角速度环响应快两者相差通常在5到10倍。在角速度环已经稳定的基础上外环才能安心地把姿态拉回期望值。如果内环响应慢吞吞外环一给目标角速度它跟不上两个环就会互相“打架”表现出来就是整机低频振荡而且很难靠调整单一环路的参数治好。聊到实现细节顺便说一下飞控代码里PID计算的周期并不一样。PX4里角速度环的控制器频率通常是250Hz到1000Hz这个量级角度环可以稍微慢一点。ROS端通过Mavros获取姿态数据做上层控制时频率会更低。这就是为什么我在ROS里写的一些上层控制算法控制周期都尽量卡在50Hz以下不是算法不够快而是外环本身没必要那么快。离散化实现上飞控里普遍用的是位置式PID的差分方程也有不少底层控制器用增量式PID来平滑输出。px4的mc_att_control就是典型的串级结构先算角度环P输出作为角速度环的期望角速度环再用PID得到三轴力矩期望。理解这个结构之后查阅官方文档或者看源码就不会迷路。3. 调参主流程先把内环调稳再让外环收敛3.1 第一步只留P把内环拉出振荡我在仿真里热身之后真机调参从角速度内环开始。先讲方法把外环暂时保持默认或者直接给一个很小的值内环的Kp从0开始慢慢加同时观察飞机对遥控姿态指令的响应。具体做法是每次增加一个较小的步进比如0.005到0.01然后试飞悬停给一个姿态阶跃指令盯住QGC或者rqt_plot里的姿态曲线。关键技巧是你要找到那个让角速度开始出现等幅振荡的Kp临界值。这个过程不是让你精确记录临界点而是让你建立“这个机架在这个重量下角速度环到底能承受多大增益”的感知。找到临界值之后把它退回到60%到70%作为内环Kp的工作点。比如我的F450在内环Kp接近某个值时俯仰和滚转方向出现了肉眼可见的高频小幅抖动退回约40%之后角速度响应明显干脆不再有多余回振。这个“拉出振荡再退回来”的做法本质上是在确定系统带宽的边界让它工作在稳定裕度足够的基础上。很多教程直接给参数让你抄其实危险就在这里不同机架的临界点差很远盲目套参数轻则飞起来手感诡异重则直接翻车。3.2 第二步D压住高频振动Kp工作点确定后接下来加Kd。我把内环Kd从一个很小的值开始缓慢增加观察两个指标高频振动有没有被抑制以及遥控打杆之后飞机能不能快速停稳。过小的Kd会让人感觉飞机“刹不住”给一个阶跃指令之后要晃两下才稳定下来过大的Kd则会把陀螺仪的高频噪声放大成电机抖动这时候机身会发出那种细密的“咝咝”声。我第一次加Kd时就从较小值提到较大值结果电机轻微发烫这才意识到阻尼给多了。后来退回一半机身声音立刻清爽了。这里有个容易忽略的点Kd对测量噪声极度敏感所以调Kd之前最好确认IMU数据没有被机械振动污染。如果机架的电机轴承有磨损或者桨叶有变形陀螺仪噪声本身就是异常的这时候你加多少Kd都没用反而越调越乱。后面第5章我想专门展开这个问题。3.3 第三步外环P与整机响应的收敛内环稳定之后开始调整外环角度环。外环的Kp逻辑和内环类似也是从较小值开始观察飞机对姿态指令的跟踪响应以及悬停时姿态角的波动幅度。真正考验外环调试的是给一个姿态阶跃指令比如切到定高模式后给一个前倾指令看roll或者pitch角度能不能快速达到期望值有没有明显超调。外环P太小飞机反应迟钝打杆之后要等一会儿才动外环P过大会出现过冲机身先过头再拉回来形成一次或多次振荡。我的做法是逐步增加外环P直到阶跃响应出现微弱超调然后往回收直到超调量控制在约5%以内。实测下来这套方法非常直接能达到姿态角在目标值上几乎一次收敛的效果。3.4 I值的微调与稳态误差内环和外环都稳定后才最后检查I值。我在PX4比例系数工作点附近观察悬停时的姿态角误差如果飞机在无风环境下能保持水平说明稳态误差本身不大I值用默认值就够了。如果出现持续偏向某一侧的情况可以考虑适当增加I值但要同时观察是否有低频的周期性起伏。曾经有一次整机始终向左偏我以为是外环I不够加了之后发现好转但开始出现缓慢的来回“呼吸”运动。后来排查发现其实是机架重心偏左导致的问题根本不该用PID去填这个坑。I在四旋翼姿态控制里更像是最后一道防线前提是硬件安装本身没有系统性偏差。4. 参数在代码里怎么落ROS、PX4与在线调参工具4.1 从飞控地面站改参数到ROS参数服务器调参过程中参数修改主要有两条路径一条是PX4飞控内部参数比如MC_ROLLRATE_P这类角速度环参数通过QGroundControl的参数界面修改后写入飞控另一条是机载电脑上ROS节点的参数比如外环位置控制器或者上层控制算法的PID存放在ROS参数服务器里。熟悉这条双路径很重要。很多人只盯住飞控PID忽略了ROS层还有一个控制器在起作用。以Mavros为例当你在机载电脑上编写一个位置控制节点把期望姿态发给飞控时你的节点内部如果也有PID那它和飞控本身的姿态PID就构成了另一层级联。我在最初调试时ROS层一个位姿PID的Kp设置过高导致发给飞控的角速度期望频繁跳变飞机表现出的症状和飞控内环Kp过大几乎一样不检查ROS节点的话很容易误判。4.2 在线调参rqt_reconfigure与mavros每次改参数都重新编译重启太浪费时间ROS生态里有两个手段可以大幅提高效率。第一个是dynamic_reconfigure机制配合rqt_reconfigure图形界面可以在节点运行过程中修改参数而无需重启。我在编写外环控制节点时把PID系数全部注册为动态参数这样飞机悬停的时候我在地面站里拖一个滑动条就能实时改变增益效果立竿见影。第二个是mavros自带的服务也可以更方便地修改PX4参数。例如直接调用mavros的param服务可以读取和设置飞控参数这在脚本化的自动调参流程里很实用。不过要提醒一句在线调参虽然方便也必须留好安全后路。我在rc脚本里加了一组“安全参数”按键一旦发现飞机状态不对立刻把参数还原到上一组稳定值同时切回手动模式。4.3 自研飞控里的PID代码结构示例如果你不是用现成飞控而是自己写飞控代码跑在STM32或者Linux单板上PID实现本身并不复杂。我在自研控制器的简化版本里内环角速度PID和外环角度PID的代码结构大致如下// 内环角速度环 float rate_pid_update(float target_rate, float current_rate, float dt) { float error target_rate - current_rate; integral error * dt; integral constrain(integral, -integral_max, integral_max); float derivative (current_rate - last_rate) / dt; last_rate current_rate; return Kp * error Ki * integral Kd * derivative; }// 外环角度环输出作为内环期望角速度 float angle_p_controller(float target_angle, float current_angle) { return angle_kp * (target_angle - current_angle); }这里有两个工程化细节想特别说明。第一微分项我建议直接用角速度反馈来代替姿态角度的差分因为姿态角度差分一方面噪声大另一方面外环的输出本质上是期望角速度用角速度反馈做内环就已经隐含了“对变化率”的阻尼效果。第二积分限幅必须给否则姿态长时间受单侧风扰时积分项会持续累积到饱和风停了飞机反而猛冲这就是积分饱和。飞控代码里角速度环的积分限幅通常写得比较紧就是不想让积分项接管控制权。ROS端调试时我习惯把控制频率、参数版本、目标角度这些信息都发布成诊断话题。这样每次试飞之后回放ros2 bag能清楚地看到哪个时刻用了哪一组参数不会出现“刚才那组参数到底是多少”的糊涂账。5. 实测踩坑记录抖动、超调、坠机问题往往不在PID本身5.1 外环振荡往往是内环响应太慢有一次外环Kp只加了一点点飞机就开始持续左右摇摆频率大概一秒一次看起来非常像外环过强导致的不稳定。我一开始按惯性思维去降外环P结果试了好几组效果都不明显。后来记录角速度指令和实际角速度曲线发现问题不在外环。内环跟踪期望角速度时有明显滞后外环发送一个期望角速度后内环需要较长时间才能达到而且还有点过冲。这时候外环看到角度没到位就会继续加大指令结果越追越猛形成低频振荡。把内环的Kp和Kd重新校准让角速度响应跟上之后外环P甚至不需要动振荡就消失了。这个案例是我在调参过程中最值得记录的一次认知升级级联系统里外环的表现很大程度上取决于内环的能力边界遇到外环振荡先看内环跟踪质量这比盲目动外环参数高效得多。5.2 Ki过大带来的低频漂移还有一次我为了消除一个轻微的角度偏差把外环I值调大了一倍结果飞机开始出现一种很缓慢的“呼吸式”飘移周期三四秒高度和姿态都像在打太极。当时差点怀疑是气压计或者IMU出了问题。分析日志后发现是积分项在给修正量时“过量”了。外环I累积一段时间的偏差给出的修正量让飞机越过目标然后偏差反方向积累I又开始反向修正形成低频振荡。这种振荡用P和D很难压住因为频率太低微分项感知不到足够的角速度变化。解决办法就是降低I甚至恢复默认然后用机架配平轻微调整重心去向。5.3 机械振动干扰先看日志再调参数调PID之前务必先确认有一个纯净的信号源。我在一次调参时发现机臂稍微加油门就出现高频振动而且不管怎么调内环Kd都无法彻底消除。后来看PX4的日志发现陀螺仪高频噪声明显比其他时间段高出一截再检查电机和桨叶发现两个电机轴承涩涩的还有一支桨叶边缘有细小的缺损。更换桨叶和电机座之后同样的PID参数下飞机异常安静。这个坑给我的教训非常大PID调的是控制系统的参数如果传感器输入本身被污染再好的参数也救不回来。建议每轮调参之前用日志和FFT看一下陀螺仪噪声频谱如果高频段有明显的峰值大概率是机械问题而不是控制问题。5.4 一次超调坠机教训是参数只能一次改一个最后讲一次真实的坠机虽然电机和机架没什么损伤但至今回想还肉疼。那是某次我在内环已经稳定的情况下外环P和D同时调大想一步到位提升响应速度。结果起飞后飞机猛然抬头约30度然后狠狠砸回地面。复盘时发现我同时改了三个参数无法判断到底是哪个动作导致超调。更糟糕的是当时的日志记录没有按顺序标注哪些参数在哪一次飞行中生效回放时只能大概推测。从那以后我给自己定了一条铁律每次只改一个参数改完必须飞行测试并记录编号确认没有异常再改下一个。这条规矩让后面所有调试变得稳定排查问题也快得多。6. 怎么判断参数算调好了量化验收与参数固化6.1 量化验收阶跃响应与悬停波动调参不能只靠“手感”。我给自己定了一套简单的量化验收标准每次改完参数试飞后把结果记录到表格里方便对比。核心看三个指标一是阶跃响应超调量通过给一个姿态指令并观察角度曲线超调量尽量控制在5%到10%以内二是稳定时间从打杆到姿态稳定2到3秒内算合理三是悬停姿态波动GPS悬停或定高悬停时roll和pitch角度的标准差在1度以内算合格0.3度以内算优秀。6.2 不同用途的调参侧重参数是否“好”取决于用途。航拍机追求平稳顺滑姿态反应可以慢一些参数偏保守穿越机追求跟手和机动性参数可以激进很多但要接受一定的高频细节抖动。我给这台F450的定位是室内外通用平台所以调参目标偏向“稳定优先”不做暴力机动。顺手提一嘴Gazebo仿真里调出来的参数和真机差别很大因为仿真里面的电机模型、转动惯量和传感器噪声跟现实都不一样。仿真只适合预演现象和练习方法千万别把仿真参数直接搬到真机上。6.3 把调参结果固化进启动流程参数确定下来之后需要保存。PX4那边参数改完同步到飞控参数文件后续重启不会丢。ROS这边的控制参数我在launch文件里统一加载并用git管理配置文件每次修改都留commit。这样即使换一台新机载电脑也能快速恢复整套环境。好的调参结果不是一次性的随着飞机用途变化比如挂载相机、电池型号改变最优参数也会漂移定期重新检查还是必要的。具体每次试飞编号和参数表的整理方式我用一个文本文件维护飞机编号、日期、内环Kp、内环Kd、外环Kp、外环Ki、现象描述、下次调整建议。这个文件看起来简单实际帮了大忙尤其是隔了很久再回看某次试飞记录时不用靠模糊记忆去猜当时改了什么。这篇学习笔记写到这里我最大的感受是PID调参更像是培养对平台的感觉而不是背参数。只要建立起“改一个参数、看一条曲线、判断反应方向”的循环每个人都能把不听话的飞机调成自己想要的飞行姿态。