ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Ardupilot姿态控制调参实战:从串级PID到MAVLink工具链

Ardupilot姿态控制调参实战:从串级PID到MAVLink工具链 很多搞飞控的朋友做完了传感器校准、电调油门行程校准、解锁自检之后往往会卡在同一道坎上——飞机第一次离地就天旋地转或者明明能飞但手感稀碎悬停时像喝醉了酒。其实这些问题的根源基本都在同一个地方Ardupilot的姿态控制没调明白。作为《Ardupilot姿态控制详解》系列的完结篇这篇不打算再重复前几篇讲过的传感器融合原理、电机动力模型、滤波器选型这些“地基”我们直接把最核心的那部分补上姿态控制这个闭环到底怎么运转、代码层面它干了什么事、以及你手里那些管理工具和编程接口Python、Dart该怎么用它干活。适合正在调参的飞手、做二次开发的软件工程师以及刚入坑无人机但对“飞机为什么能站稳”充满好奇的新手。1. 姿态控制是怎么一环扣一环的上一代飞控或者说初学阶段大家对姿态控制的理解往往停留在“PID调一下就行”。但实际上去翻Ardupilot的源码、看日志曲线你会发现姿态控制从来不是一个单一PID它是一整套串级闭环里面有三个绕不开的概念期望姿态、机体角速度、以及电机的推力分配。1.1 先分清几个“姿态”概念很多新手在接触姿态控制时第一件事就是被欧拉角、四元数、机体轴角速度搞晕。这里我建议你用一个朴素的心智模型去记姿态就是飞机“相对于地面的朝向”角速度就是飞机“绕自己三个轴的转动快慢”。Ardupilot内部几乎全程用四元数来表示姿态原因很实际欧拉角在接近90°俯仰时会出万向锁导致数值跳变而且四元数做姿态插值和旋转串联运算比欧拉角方便得多。但在对外接口比如MAVLink的ATTITUDE消息里它又会把姿态转成欧拉角给你看。所以你会看到roll、pitch、yaw三个角度和rollspeed、pitchspeed、yawspeed三个角速度同时出现。控制上就用两套量角度量期望横滚角、期望俯仰角、期望偏航角这是外环的输入输出对象角速度量机体绕X、Y、Z轴的旋转速度单位rad/s这是内环的直接控制对象。说个容易踩的坑角速度符号方向和角度的符号方向在Ardupilot里是约定一致的都是右手定则。也就是绕X轴向右滚转为正绕Y轴抬头为正绕Z轴逆时针偏航为正。要是你自己写代码做控制律符号搞反了那飞机一定是炸鸡收场。1.2 串级控制角度外环与角速度内环的结构Ardupilot的姿态控制采用典型的串级PID结构。外环是角度控制器输入是期望角度和当前角度输出是期望角速度内环是角速度控制器输入是外环给出的期望角速度和当前角速度陀螺仪测量的角速度输出是期望力矩最后通过混控器mixer转化为每个电机的PWM指令。为什么会用两层而不是直接把期望角度丢给PID去推电机原因很简单直接用角度误差去输出电机指令等效于一个P控制器去控制一个其实是二阶系统的东西增益小了反应慢增益大了就震荡。串级的好处是内环可以先把角速度这个“中间量”快速稳住外环只需要调度“转到什么角速度”即可。用大白话说外环决定“你要多快转过去”内环保证“你确实按这个速度转”。在Ardupilot参数里这层结构体现在前缀上ATC_ANG_RLL_P、ATC_ANG_PIT_P、ATC_ANG_YAW_P外环角度P增益ATC_RAT_RLL_P/I/D、ATC_RAT_PIT_P/I/D、ATC_RAT_YAW_P/I/D内环角速度PID。注意外环只有P没有I和D。这是Ardupilot官方推荐的经典配合。角度误差不存在稳态误差问题——因为只要角度有偏差外环就会产生期望角速度继续纠偏所以积分项放在外环是多余且有害的反而会引入超调和缓震。角度环的D更是没必要因为角度本身是由姿态解算积分出来的求导放大噪声纯属自讨苦吃。2. 深入Ardupilot的姿态控制实现前一节讲了闭环骨架这一节我们把骨架里的“器官”逐个解剖。Ardupilot这套姿态控制算法经过十几年的迭代已经非常成熟但它的实现方式并不是教科书里那种随手写个PID就完事的里面有不少细节值得展开。2.1 从期望姿态到期望角速度外环在算什么外环的输入来自遥控器输入或自主飞行逻辑比如航线任务、定高模式里的位置控制器通常表达为期望的横滚角、俯仰角、偏航角。Ardupilot在计算时会先把期望姿态和当前姿态都转为四元数计算其误差四元数然后从这个误差中分解出机体坐标系下的角度误差。角度误差在外环经过比例控制分别乘上ATC_ANG_RLL_P、ATC_ANG_PIT_P、ATC_ANG_YAW_P这三个参数就得到了期望角速度。以横滚轴为例数学上就是期望滚转角速度 (期望横滚角 - 当前横滚角) × ATC_ANG_RLL_P简单、直接、没有任何花哨的东西。但Ardupilot还会做一些限制期望角速度不能超过ATC_RATE_RLL_MAX、ATC_RATE_PIT_MAX、ATC_RATE_YAW_MAX这个参数在老版本里叫ATC_RATE_YAW_MAX新版本拆成了几个限制参数姿态角本身也会被限幅比如ATC_ANG_LIM_TC用来平滑摇杆输入让期望角度平滑变化避免杆量猛地打满导致姿态突跳。ATC_ANG_LIM_TC这个参数很容易被忽略但它管着“摇杆打过去之后期望姿态追得多快”。调小立即使手感更跟手调大则飞机更柔和。实际调试时如果觉得飞机“跟手但容易过冲”或者“稳但反应慢”往往不需要动PID调这个时间常数就能解决问题。2.2 角速度环PID每个参数到底在干啥内环角速度PID是姿态控制的重中之重。网上流传的“P管力度、I管消除静差、D管阻尼”这句口诀放在这里确实没错但真要落到参数上还是有很多细节值得深挖。先说P项。期望角速度和当前角速度之间的误差乘上ATC_RAT_RLL_P对应横滚轴就成了P项输出它决定飞机“抵抗外力扰动”的刚度。P太低飞机受到阵风就会歪P太高飞机会出现高频的嗡嗡声甚至持续震荡这种震荡频率通常在几赫兹以上从日志里看角速度曲线就像锯齿一样。再说I项。角速度环的I项用来消除恒定的干扰力矩比如重心偏移、电机拉力不一致、机身不对称等导致的持续偏转。I项的问题是积分饱和——当飞机持续被施加一个由外环产生的角速度误差指令时如果I项累计得太多一旦外界扰动消失它还会继续输出好几秒的偏转力矩表现出来就是飞机“缓了一下又突然歪一下”。解决办法是把I项的积分输出限制住Ardupilot里专门有ATC_RAT_RLL_IMAX这个参数控制横滚轴的积分限幅默认是0.333调小一点能让飞机在风吹时恢复得更利落。最后说D项。角速度环的D项对陀螺仪噪声极其敏感它本质上是“角加速度抑制”。D项高了飞机会在快速机动后干净利落地停下来但调太高就会出现陀螺仪噪声被放大之后的dirty震动整机发麻、电机发烫。Ardupilot里D项还可以再加一个D滤波器也就是ATC_RAT_RLL_D_FILTER参数默认25Hz用来把陀螺仪高频噪声挡在前端。这个参数如果不是特别清楚自己在干嘛建议保持默认。偏航轴和横滚俯仰轴有个重要区别偏航轴的转动惯量小、响应快而且偏航力矩主要靠电机反扭力差产生所以偏航轴的P和D通常比横滚俯仰明显低。新手上路容易犯的错是把三轴P设成一样的结果偏航轴疯狂抖头。2.3 代码层面去哪儿看Ardupilot的姿态控制代码在Copter固件里主要由AC_AttitudeControl类负责源码文件路径大致在libraries/AC_AttitudeControl/AC_AttitudeControl.cpp和ArduCopter/Attitude.cpp。很多朋友想“看源码学飞控”我个人建议先别从头一行一句读因为代码里混了大量传感器失效保护、限幅、模式切换分支直接读完会很劝退。更好的方式是带着问题去搜关键函数名比如你搜attitude_controller_run_quat就能看到姿态控制器的主入口搜rate_controller_run就能看到内环PID计算的地方。对着代码再回头看日志曲线理解速度会快很多。3. 配套工具与实操读数据、发航点、调参姿态控制讲得再多最终还是要落到工具链和实操上。这部分我会覆盖三个热词里提到的点用哪个管理工具管理Ardupilot、用Python怎么读取Ardupilot的姿态数据、以及用Dart通过MAVLink给Ardupilot发送航点。这些都是实际项目里高频出现的真需求。3.1 管理工具选型Mission Planner、QGroundControl、MAVProxy怎么选Ardupilot的管理工具生态很丰富但大家最常见的就三个Mission Planner、QGroundControl、MAVProxy。Mission Planner是Windows平台上的“老大哥”功能最全尤其适合做参数调优、日志分析、传感器校准。姿态控制调参时我特别推荐它的“Flight Data”界面能同时看Pitch/Roll的期望值、实际值、角速度误差还能拉出PID贡献曲线。新版本里它甚至提供了一个自动调参的“Tune”按钮虽然我不建议对新手全自动跑但用来做参数初筛非常高效。QGroundControl是跨平台地面站macOS和Linux用户的福音。它的航点规划和任务上传做得漂亮MAVLink可视化也清晰但单独的PID分析工具不如Mission Planner丰富。如果你是纯Ubuntu开发环境QGC是首选。MAVProxy则完全是命令行工具对工程师更友好。它最核心的价值是可以在嵌入式环境里用python扩展而且资源占用极低。如果你需要在地面站里跑自定义脚本去批量读取参数、批量发指令MAVProxy pymavlink的组合比图形化地面站灵活得多。选型建议Windows用户直接上Mission PlannermacOS/Linux桌面用户上QGroundControl做自动化测试或二次开发的MAVProxy pymavlink是生产力工具。3.2 Python读取Ardupilot姿态数据pymavlink实战Python读取Ardupilot姿态数据最常用的库是pymavlink。它本质上是一个MAVLink协议解析库负责把串口、UDP、TCP上的二进制MAVLink消息转成可读的Python对象。第一步安装pip install pymavlink第二步建立连接。常见的有两种连接方式USB串口直连和UDP局域网连接。串口连接适合地面站和飞控用USB线连的场景UDP连接适合数传或者模拟器SITL。模拟器调试时通常用的是UDPfrom pymavlink import mavutil # 串口连接示例Linux下通常是/dev/ttyUSB0Windows下是COM口 # master mavutil.mavlink_connection(/dev/ttyUSB0, baud115200) # UDP连接预设端口SITL默认是14550 master mavutil.mavlink_connection(udp:127.0.0.1:14550) master.wait_heartbeat() print(已连接飞控心跳正常)第三步订阅姿态消息。姿态数据对应的MAVLink消息名是ATTITUDE里面包含roll、pitch、yaw、rollspeed、pitchspeed、yawspeed六个核心字段。读取方式有两种阻塞式读取适合脚本里按顺序处理一条条消息msg master.recv_match(typeATTITUDE, blockingTrue) print(froll: {msg.roll:.3f} rad, pitch: {msg.pitch:.3f} rad, yaw: {msg.yaw:.3f} rad)事件循环式读取适合长时间监听、随时抓取最新姿态while True: msg master.recv_match(typeATTITUDE, blockingTrue) if msg: # 注意ATTITUDE消息里的欧拉角单位是弧度 roll_deg int(msg.roll * 57.2958) pitch_deg int(msg.pitch * 57.2958) yaw_deg int(msg.yaw * 57.2958) print(froll: {roll_deg}°, pitch: {pitch_deg}°, yaw: {yaw_deg}°)一个非常容易踩的坑ATTITUDE消息的欧拉角单位是弧度不是角度。如果你直接拿数值去当角度看会发现roll是0.03左右而不是1.7度左右搞得自己一头雾水。做日志分析的时候统一转成角度制再操作。如果要做姿态控制调参分析除了实时读取更推荐直接读Ardupilot的bin日志dataflash log。用pymavlink的mavlogdump.py脚本可以很方便地把.bin转成.csv或者可读文本再结合Excel或者Python的pandas去画期望角速度、实际角速度、P/I/D各项贡献的曲线。3.3 Dart通过MAVLink发送航点给Ardupilot的完整流程Dart这个语言在飞控生态里出现得不算多但做跨平台App、桌面工具、甚至机器人控制面板时它确实是一个好选择。Dart发航点给Ardupilot本质上就是通过串口或网络连接发送MAVLink的航点相关消息。Ardupilot这边完全不知道对面是C、Python还是Dart它只认MAVLink协议。第一步准备一个可用的MavLink库。Dart生态里有一个维护得比较好的dart_mavlink库也可以直接用protocol生成器从mavlink.xml生成Dart代码。这个步骤如果你不熟悉可以去pub.dev搜索mavlink找一个旧但能用的包通常都支持v1.0协议。第二步建立连接。Dart端通常用UDP连接到运行着SITL的电脑上或者通过串口串口库比如serial_port连真机。这里给一个UDP连接的示意写法import dart:io; // 连接到SITL的UDP端口 var socket await RawDatagramSocket.bind(InternetAddress.anyIPv4, 0); socket.connect(InternetAddress(127.0.0.1), 14550);第三步发送航点消息。标准流程其实分几步发送MISSION_COUNT消息告诉飞控“我要上传N个航点”等待飞控回MISSION_REQUEST每收到一个请求就发送对应的MISSION_ITEM_INT消息里面包含航点序号、经纬度、高度、航点类型MAV_CMD_NAV_WAYPOINT全部发完后飞控会回复MISSION_ACK表示任务接收完成。以向Ardupilot上传一个简单的“起飞到指定点”航点为例核心是要构MAVLink消息。在dart_mavlink这类库里MISSION_ITEM_INT的消息体通常长这样var item MavlinkMissionItemInt( seq: 0, frame: MavFrame.mavFrameGlobalRelativeAlt, command: MavCmd.mavCmdNavWaypoint, current: 0, autocontinue: 1, param1: 0, // 停留时间秒 param2: 20, // 接受半径米 param3: 0, // 通过航点半径米 param4: 0, // 偏航角 x: 47.397742, // 纬度 y: 8.545594, // 经度 z: 100.0, // 高度米 );真正让Ardupilot开始执行还需要切换飞行模式到AUTO/GUIDED然后发送MAV_CMD_MISSION_START消息。直接用MAVLink的SET_MODE消息切换模式是最稳妥的方式Ardupilot这边要设置自定义模式编号为AUTO在Copter里AUTO对应模式序号是3。这个流程里最常见的坑有三个航点序号必须从0开始而且MISSION_COUNT里的总数要和实际发送的消息数量完全一致多了少了都会卡在等待请求状态坐标系一定要用MAV_FRAME_GLOBAL_RELATIVE_ALT相对高度否则飞控会按绝对高度去执行你把高度设成100米要是当地海拔正好是100米可能没事但要是在高原飞飞控会直接起飞拉升到几百米如果飞控没收到任务先检查循环里有没有处理好MISSION_REQUEST消息Ardupilot是一边收一边校验每收一个就要立即回一个不能批量发送。3.4 姿态调参标准流程与参数速查说完了读取和航点再回到姿态控制最核心的事情——调参。这里给出一个我自己实测下来比较稳的流程。先确认基础条件飞机重心居中、电机编号和方向正确、螺旋桨规格一致、加速度计和陀螺仪校准完成、遥控器通道和模式设置正确。这个前提没满足参数怎么调都是白搭。第一步把内环PID全部恢复到一个安全的保守基准值。对于一台常见的250级别四轴或大疆F450级别四轴可以从Ardupilot自带的参数文件里选一个相近机型的默认参数或者用官方推荐的默认值起步。一般来说ATC_RAT_RLL_P和ATC_RAT_PIT_P可以先给0.135左右I给0.18左右D给0.003左右偏航轴的P给0.18I给0.015D给0.004。轴距更大、更重的飞机P值反而要适当调小因为转动惯量大。第二步先调内环P。让飞机解锁油门推到一个中等悬停位置给一个小幅横滚或俯仰阶跃指令用手轻推杆然后回中观察飞机是否震荡。如果震荡把P降低20%再试。如果响应很软、像“发面团”把P提高20%。反复试到“打杆后快速响应但没有高频震荡”这个状态为止。第三步加I。手动把飞机在一个方向掰一下看它是否慢慢回中。如果不回中增加I如果回中后产生低频率的“来回晃”就是I过高降低I。正常情况下姿态控制的I值不需要很大因为外环已经在持续消除角度误差。第四步加D。把飞机快速从一个姿态打到另一个姿态然后回中观察能不能干脆利落停住。如果会“过冲”一下再回来说明D不足如果电机发出尖锐鸣叫、机身发麻说明D过大。D项的调整幅度要非常小一次±0.001因为陀螺仪噪声很容易被D放大。完整的参数速查表放在这里方便调参时对照参数名称作用参考范围250~550级四轴调大效果调小效果ATC_ANG_RLL_P / ATC_ANG_PIT_P外环角度P4.5 ~ 6.5更跟手、更激进更柔和、更适合新手ATC_ANG_YAW_P外环偏航角度P4.0 ~ 5.5偏航响应更快偏航发虚ATC_RAT_RLL_P / ATC_RAT_PIT_P内环横滚俯仰P0.12 ~ 0.18抵抗扰动更强抗风变差ATC_RAT_RLL_I / ATC_RAT_PIT_I内环横滚俯仰I0.15 ~ 0.25消除恒定偏差更快恢复力变弱ATC_RAT_RLL_D / ATC_RAT_PIT_D内环横滚俯仰D0.002 ~ 0.006快速制动、抗过冲更容易过冲ATC_RAT_YAW_P内环偏航P0.15 ~ 0.22机头锁定力更强锁头发软ATC_ACCEL_MAX最大角加速度限制8000 ~ 45000 deg/s²机动更猛机动更柔和调参时一定要养成记日志的习惯。每一轮调整前用Mission Planner输一个特定的“tag”在Flight Data里标注品名这样后面翻日志时一眼就知道当前曲线对应哪一组参数。别偷懒这个习惯能帮你少走非常多弯路。4. 常见问题与排查技巧实录姿态控制调参这条路上几乎每个人都踩过差不多的坑。我把这些年遇到的高频问题整理一下属实都是“过来人”经验很多人不看日志瞎调一晚上最后发现就是个几百年没人注意的小参数。4.1 高频自激震荡现象飞机解锁后在空中或者地面就能听到高频的“嗡嗡”声甚至电机抖动肉眼可见油门稍微拉高就会剧烈晃动。排查思路直接看日志里的角速度曲线。如果角速度曲线呈现高频10Hz以上正弦状波动通常意味着内环P偏高或者D偏高。先降P再降D一般一次调整幅度不超过20%降完重新试飞。另一个隐藏原因是陀螺仪滤波器设置不当INS_GYRO_FILTER默认值是20Hz如果你用了一个噪声特别大的飞控板可以尝试降到10Hz但如果P和D本身已经到了合理区间滤波扛不住不是因为调参而是硬件噪声太大得考虑换减震泡沫垫。4.2 悬停漂移严重现象飞机在无风条件下悬停姿势一直在缓慢漂移往某个方向一直偏需要不断手动修正。排查思路优先检查传感器校准。加速度计水平偏了一点姿态估计就会一直有误差飞控为了姿态回中会把飞机往“错误”的方向推。重新做一次6面校准然后用遥控杆把飞机保持水平悬停看日志里roll/pitch是否接近0。如果加速度计已经校准了那就是I项的问题——看看飞机是不是偏向电机转速高的一侧如果是增大对应轴的I值。还有一种被忽略的情况电机和螺旋桨本身不对称比如有一个电机有点退磁拉力下降这属于硬件问题需要更换电机而不是盲目调参数。4.3 偏航轴“摇头”或“锁不紧”现象飞机悬停时机头左右摇或者偏航后无法精确停住甚至出现低频震荡。排查思路偏航轴和横滚俯仰完全不同它的转动惯量小、响应快过大的P或者过大的D都极易引发振荡。首先确认偏航轴的P不要比横滚轴高太多然后检查偏航轴的D是否过大。还有一点特别容易被忽视偏航轴角速度环的I项如果设得过大会导致偏航响应“软”也就是机头转过去之后又慢慢弹回来。可以把ATC_RAT_YAW_IMAX调低一些。如果电机排布是X型偏航力矩靠的是四个电机的差速电机响应跟不上偏航指令也会出现摇头这时候可以检查一下电机电调的响应时间尽量选响应快的电调。4.4 快速打杆后过冲现象快速把横滚杆打到底再松手飞机不是立刻停住而是顺着方向多转了10°左右才回来。排查思路这是D项不足的典型表现。外环和P项已经把飞机“加速”到位但缺了阻尼飞机停不住。先增加横滚/俯仰的D值每次增加0.0005左右直到快速打杆后能干净利落停住。如果D已经加到0.006以上还是过冲回头看看ATC_ANG_LIM_TC是不是设得太小因为外环反应过激会把一个很大的期望角速度灌给内环内环再激进也容易过冲。这个情况下降一点外环角度响应反而能改善手感。4.5 检查清单速查表问题现象优先检查项次要检查项高频震荡内环PID过高尤其D项INS_GYRO_FILTER过低减震垫问题悬停漂移加速度计校准偏差I项不足、重心偏移偏航摇头偏航P/D过高电调响应慢、ATC_RAT_YAW_IMAX过大打杆过冲内环D不足ATC_ANG_LIM_TC过小、外环P过高响应迟缓内环P不足外环角度P不足、角加速度限幅过小电机发烫D项过大导致高频调节电调频率过低、电机损坏这里必须再强调一遍调试姿态控制最忌讳“想当然”。不要凭感觉拧参数一定要用日志辅助分析。Mission Planner的Flight Data界面把pil和期望值曲线叠加在一起看一眼就能判断误差是角度误差还是角速度误差。如果角度偷差一段时间持续说明外环有系统性问题如果角度几乎一致但角速度震荡内环问题跑不掉。日志是你和失控之间唯一的真相。根据我个人这么多年的调机经验姿态控制调参其实有60%的时间是在排除硬件和传感器问题只有40%的时间在真正碰PID。很多人一上来就调参数结果调了两天发现是螺旋桨一个装反了、电机一个堵转白白浪费精力。先把硬件、重心、校准这些工作做实再动手调PID你会发现所谓的“姿态控制难点”其实没有传说中那么玄乎。最后再分享一个小技巧调参之前把Mission Planner里的“Pilot Tune”调参工具用起来它会自动帮你做一次往返扫掠然后给出一组推荐PID。虽说不一定完全贴合你的手感偏好但拿来做初始值和合理性验证很靠谱。省下的时间够你多炸两架模拟器了。
返回列表