ARTICLE DETAIL

资讯详情

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

JSBSim中为C172X加装自动驾驶仪:PID参数整定全流程

JSBSim中为C172X加装自动驾驶仪:PID参数整定全流程 玩JSBSim的人多半有过这种经历好不容易把C172X飞上天接下来全是无聊的航向修正。想开自动驾驶结果翻遍模型文件发现这架飞机压根没预置自动驾驶仪。网上搜教程不是讲PID数学模型讲得云里雾里就是某个开源飞控的源码分析没有一篇能直接照抄到C172X上。这篇文章把我自己在JSBSim里给C172X搭自动驾驶仪的完整过程写出来重点落在PID参数往哪里填、初值给多少、怎么调才能不炸机希望能帮你省掉几个熬夜排查的晚上。1. 为什么要在C172X上自己实现自动驾驶仪JSBSim的定制思路1.1 C172X模型自带什么缺什么C172X是JSBSim发行包里最经典的模型之一对应塞斯纳172这类单发活塞螺旋桨飞机。它自带完整的飞行动力学、气动导数、发动机模型和起落架模型你手动操纵它做爬升、下降、转弯、失速这些常规动作都没问题。但打开它的系统文件看一眼就明白了模型里默认的飞控系统只管机械连杆和舵面响应油门也是直接映射按键输入并没有“保持航向”“保持高度”这种闭环控制逻辑。也就是说JSBSim给了你一架“翼型正确、发动机能转、舵面能动”的飞机但没给你一个能替你驾驶的副驾驶。想让它自己飞得自己写控制系统。很多人第一次搜到JSBSim文档时会被“system”“property tree”这些概念吓住其实说白了就是一套管道自动驾驶仪读几个传感器的数值算一算然后把指令发给舵机。管道本身并不神秘神秘的是怎么让数值算得稳、算得准。1.2 JSBSim系统构建的基本概念JSBSim里飞机模型由XML文件描述一架飞机通常有aircraft/c172x/c172x.xml这样的入口文件。这个文件里除了气动参数还会通过system file.../引入额外的控制系统自动驾驶仪就属于这种系统文件。系统文件的基本单位是“通道channel”。一个通道负责一整条信号链从读取属性到做控制律计算再到输出舵面指令。你完全可以把自动驾驶仪拆成几个通道比如“俯仰通道”负责升降舵“滚转通道”负责副翼“油门通道”负责发动机节气门。每个通道内部核心计算单元就是PID控制器。属性树是JSBSim的全局变量空间传感器、控制器、执行器都通过属性交换数据。比如当前俯仰角存在attitude/pitch-angle-deg里空速存在velocities/vc-kts里升降舵指令存在fcs/elevator-cmd-norm里。自动驾驶仪要做的就是定期读这些属性、处理、再写回去。理解了这个模型以后你再看网上那些结构复杂的飞控系统底层逻辑其实都一样。1.3 自动驾驶仪与PID的关系自动飞行听着高级但绝大多数基础自动驾驶功能都可以归约为若干个PID回路。比如你想让飞机平飞、保持5000英尺高度就要有一个“高度误差→俯仰角指令→升降舵响应”的嵌套反馈你想让它航向保持不变就要有一个“航向误差→滚转角指令→副翼响应”的反馈。两个回路的外层是飞行轨迹量内层是姿态量内层姿态控制又是外层的执行基础。所以配置自动驾驶仪的本质就是设计一组PID控制器并把它们串成级联结构。C172X没有现成可用的飞控参数但它有完整的气动响应这反而是好事你可以从零开始手工整定参数亲眼看着一组组数值如何影响飞机动态调完之后你对PID和飞机气动的理解都会上一个台阶。2. PID控制器的原理与JSBSim中的回路设计2.1 三种基本作用的直观比喻PID三个字母对应比例、积分、微分三个作用网上公式一抓一大把不展开推导。我更愿意用开车的例子来解释你开车发现车头偏左了比例作用会提醒你往右打方向偏差越大打越多但只靠比例车身可能会来回摆动最终停不到车道正中间这时积分作用会累积过去这段“跑偏的账”慢慢把方向盘角度补上让车回到正中央微分作用看的是偏差变化趋势发现车头正在快速向左偏时提前收一点方向抑制过冲。放到C172X上也是一回事。假设你要保持5000英尺高度当前高度掉到4950比例项会让升降舵抬头抬头越快越猛微分项感测到高度下降趋势过猛会提前减小抬头动作防止飞机猛地冲过5000积分项则负责消除那个“差几十英尺就是补不平”的稳态误差。三者配合得好飞机就被“钉”在指令高度上配合不好飞机就在目标高度上下画波浪。2.2 姿态内回路与轨迹外回路设计自动驾驶仪之前先分清内回路和外回路。C172X最常用的回路结构是这样的高度误差 - 俯仰角指令 - 俯仰角误差 - 俯仰PID - 升降舵 航向误差 - 滚转角指令 - 滚转角误差 - 滚转PID - 副翼 空速误差 - 油门指令 - 油门PID - 节气门可以看到高度保持并不直接控制升降舵而是先算出一个“需要仰头多少度”的目标再让内回路去执行这个姿态。这样做的好处是内回路可以把飞机姿态稳定得很扎实外回路只管算姿态目标两侧不会互相干扰。JSBSim里定义这样的级联结构不算复杂难点在于理顺属性传递别把内回路的输出接到外回路的输入上。2.3 JSBSim里的属性信号通路在JSBSim的system文件中PID控制器通常会读取一个“误差信号”但也可以直接读取“目标值”和“当前值”然后在系统内部做差。我习惯把误差计算也放进系统文件里用几个summer节点或直接在一个PID节点里用输入属性组合实现。属性命名的规律比较直白飞机状态量基本都在attitude/、position/、velocities/这些前缀下舵面指令在fcs/前缀下。调PID的时候最怕信号断掉你以为PID在干活实际上它读到的误差永远是0或者输出指令被限幅卡死。所以刚开始配置时我建议把传感器原始值、误差值、PID输出值全部通过JSBSim的--output功能写进CSV飞完手动拉曲线看一遍通道通没通、增益合不合理一目了然。3. 手把手配置C172X的自动驾驶仪参数3.1 准备文件在aircraft/c172x目录下创建系统文件假设你的JSBSim安装目录是JSBSimC172X模型就在JSBSim/aircraft/c172x/。先打开c172x.xml在system标签区域里加一行把自动驾驶仪系统挂进去system filec172x_autopilot/然后新建aircraft/c172x/c172x_autopilot.xml。这个文件就是我们的主战场。第一步先别急着填PID参数先把文件框架写好?xml version1.0? system nameC172X Autopilot channel nameap/pitch /channel channel nameap/roll /channel channel nameap/throttle /channel /system我给每个通道起名都带ap/前缀方便后期用命令行实时修改参数。JSBSim里属性和通道名不是必须一致但清晰的命名会让调试轻松很多。3.2 俯仰通道配置姿态保持PID先从最重要的俯仰通道开始。目标很单纯让升降舵根据当前俯仰角和目标俯仰角的误差去调整使飞机保持目标姿态。channel nameap/pitch inputap/error_pitch/input inputattitude/pitch-angle-rad/input pid nameap/pid_pitch kp0.03/kp ki0.001/ki kd0.02/kd limit0.4/limit outputfcs/elevator-cmd-norm/output /pid /channel注意这里我用了弧度作为角度的计算单位避免系数出现无意义的巨大值。fcs/elevator-cmd-norm的取值范围是-1到1所以PID输出必须加上限幅limit0.4意味着升降舵最多只输出40%的偏度防止飞机一下子拉出过载。kp0.03看起来很小但C172的俯仰响应并不算迟钝过大的P会让机头上下抖成一个正弦波。这个通道只做了“俯仰姿态保持”。在实际飞行时你需要给ap/error_pitch提供目标值和误差计算逻辑比如在系统文件里用另一个通道计算“目标俯仰角−当前俯仰角”。最简单的做法是把目标值直接写进属性比如ap/pitch_target_rad然后误差通道做一个减法。3.3 高度通道外回路改内回路实现高度保持仅有俯仰姿态保持还不够因为用户要的是“按一下自动驾驶飞机自己维持在5000英尺”。高度保持需要再加一个外回路用高度误差生成俯仰角指令。这个外回路我建议用一组独立的低增益PID输出作为内回路的ap/pitch_target_radchannel nameap/altitude inputap/alt_error/input pid nameap/pid_altitude kp0.002/kp ki0.0001/ki kd0.005/kd limit0.3/limit outputap/pitch_target_rad/output /pid /channel高度外回路的输出是俯仰角单位是弧度最大0.3弧度大约是17度已经是C172巡航状态下比较陡的仰角了。为什么外回路增益要设置得比内回路小因为高度是一个缓变量5000英尺掉10英尺根本不需要立刻改成大角度爬升。如果外回路P过大飞机就会在目标高度附近反复俯冲-拉起乘客早就晕了。这里有个容易忽略的细节高度保持必须在俯仰保持工作正常的前提下才能叠加上去。调参顺序永远是先稳定内回路再动外回路顺序反了你会看到飞机像喝醉了一样上下乱窜。3.4 滚转/航向通道配置航向保持和高度保持同理外层是航向误差内层是滚转角误差。C172X的副翼效率足够滚转响应很直接所以滚转回路的PID增益可以比俯仰稍稍大一点。channel nameap/roll inputattitude/roll-angle-rad/input pid nameap/pid_roll kp0.05/kp ki0.0005/ki kd0.01/kd limit0.5/limit outputfcs/aileron-cmd-norm/output /pid /channel航向外回路怎么做假设目标航向和当前航向的差值为ap/heading_error_rad外回路PID算出一个目标滚转角channel nameap/heading inputap/heading_error_rad/input pid nameap/pid_heading kp0.02/kp ki0.0/ki kd0.0/kd limit1.0/limit outputap/roll_target_rad/output /pid /channel航向差是个周期量±π跳变的问题需要额外处理好在C172X的自动驾驶在稳定转向时坡度不会太大先把误差限制在±π之间再算角度差就够了。航向通道我先用纯P控制因为I加在这层容易积出过大的坡度指令导致飞机进入连续盘旋反而飞不出一个稳定的航向。3.5 油门通道空速保持PID油门控制不如舵面那么敏感但也很关键。C172X在平飞时油门指令和空速近似线性用PID控制空速输出直接接到fcs/throttle-cmd-normchannel nameap/speed inputvelocities/vc-kts/input pid nameap/pid_speed kp0.02/kp ki0.001/ki kd0.001/kd limit0.5/limit outputfcs/throttle-cmd-norm/output /pid /channel这里的vc-kts是校正空速单位是节。油门的执行没有舵面那么快微分作用几乎不需要所以kd给得很小。I项的作用是消除载荷变化带来的稳态误差比如放了襟翼或者改变了高度油门会自动补上。注意油门指令同样要限幅不能让节气门瞬间从20%打到100%那样发动机响应跟不上反而会让空速波动。3.6 初始参数设定表新手最容易上来就乱填参数我的建议是先按下面这个表设置初始值再根据实飞曲线调整通道kpkikdlimit输出目标俯仰姿态0.030.0010.020.4升降舵指令高度0.0020.00010.0050.3 (rad)目标俯仰角滚转姿态0.050.00050.010.5副翼指令航向0.02001.0 (rad)目标滚转角空速0.020.0010.0010.5油门指令这些值不是“最终答案”但能保证你的C172X至少在自动驾驶接通的瞬间不会发疯。接下来需要用仿真数据说话。4. 仿真调参与实测分析4.1 测试环境设置我习惯先让C172X在无风、标准大气条件下飞到3000英尺表速90节稳定平飞后再接通自动驾驶。手动操纵交给JSBSim的脚本控制比如写一个简单的启动脚本或者直接开FlightGear连上JSBSim用遥控器把飞机稳住然后打开自动驾驶。接通自动驾驶的瞬间是最容易暴露问题的时刻。如果参数乱给飞机会明显“抖”一下甚至直接进入失速螺旋。所以我会先把自动驾驶系统的控制目标设为当前状态比如目标高度就是当前高度目标航向就是当前航向这样误差为零PID输出很小飞机不会突然响应。确认系统平稳后再一点点改变目标高度或航向观察响应。4.2 典型PID问题与处理思路调试中最常见的三类现象对应三个不同的问题飞机在目标值上下高频振荡周期很短通常是P过大或D过小。把P砍掉一半再试如果还抖适当增大D。飞机慢慢悠悠飘向目标但永远有差距比如目标高度5000它稳定在4990不下来这说明I缺失或太小需要加大积分项。飞机冲过目标后又冲回来振幅越来越大这往往是因为D只压住了高频抖动但I作用过强导致低频“点头”振荡。先把I调小观察一下。这里有一个很多人忽视的点KSBSim里PID采样频率会影响参数。JSBSim默认的仿真帧率是120Hz但系统通道的执行频率可能更低。如果你设置了较大的积分项但发现飞机响应有奇怪的滞后先去确认系统文件里的执行频率再回头调参。4.3 我的手调步骤先P、再D、后I我调C172X自动驾驶仪的顺序是固定的先让内回路处于纯P控制把系统稳定住再加D抑制振荡最后加I消除稳态误差。第一步把所有ki设成0kd设成0只留下一个合理的kp。接通自动驾驶看飞机能不能跟着目标跑一小段。这时候飞机通常会有一个固定的跟踪误差但这不重要只要不振荡就行。第二步逐渐增加kd把姿态变化率反馈引入你会看到飞机接近目标时的“冲劲”被压下来姿态变化变得柔和。第三步再加入ki处理那个残留误差。以俯仰通道为例我一开始kp0.03飞机能抬头但离目标姿态差一度左右然后我把kd从0加到0.01再慢慢加到0.02发现超调明显变少最后把ki从0加到0.001那0.5度的误差被消化掉了。整个过程大约花了一个多小时比我想象中快因为C172X的气动很规矩不像那些高机动战斗机模型那么难伺候。4.4 一组可用的参考参数经过几轮测试我最终在C172X上跑通的一组参数如下俯仰姿态kp0.032, ki0.0012, kd0.018, limit0.4 高度外环kp0.002, ki0.00015, kd0.004, limit0.3 滚转姿态kp0.045, ki0.0006, kd0.008, limit0.5 航向外环kp0.015, ki0.0, kd0.0, limit1.0 空速保持kp0.02, ki0.001, kd0.0, limit0.5这套参数在表速90节、高度3000英尺附近表现得相当平稳。接通自动驾驶后即使我手动给飞机加了一个10英尺/秒的垂直阵风扰动它也能在10秒内恢复目标高度航向偏差保持在2度以内。5. 踩坑记录与扩展方向5.1 属性路径名称写错会导致PID静默失效我最开始调的时候犯过一个特别愚蠢的错误把velocities/vc-kts拼成了velocity/vc-kts少了一个s。JSBSim不会在启动时报“属性不存在”它只会默默给你一个NaN或0。结果就是空速PID一直在处理一个无效输入油门抽风一样地来回打飞机速度忽快忽慢。排查方法很简单运行时输出所有属性搜一下你用的路径看有没有拼错或者故意在系统文件里把PID输出直接接到一个固定值再去看舵面有没有动作。先确认信号链通再调参数能省一半时间。5.2 舵面限幅与PID输出限幅C172X的舵面行程有限elevator-cmd-norm超出±1就会被物理约束截断。如果PID的limit设置得太大输出经常打到限幅器上积分项会继续积累出现“积分饱和”。典型表现是飞机明明已经拉平了升降舵还死死顶着上限让飞机一直低头或抬头。我建议每个PID都设置一个合理的输出限幅并且积分环节也要做限幅。在JSBSim的PID节点里limit本身就是对最终输出限幅的这能在一定程度上缓解积分饱和但我还是习惯手动把每个通道的积分项限制在一个小范围内比如俯仰通道的ki积分累计不超过0.05弧度。5.3 参数鲁棒性与飞行包线你在3000英尺、90节调出来的参数换到1万英尺、120节可能会变得非常奇怪。C172X的气动会随马赫数和迎角变化但自动驾驶仪参数一般不会自动适应所有状态。如果你只是在地形跟踪或起落航线里用一组参数够用想让它飞得更无所顾忌就得考虑在不同空速段切换PID增益。JSBSim支持在一定条件下动态修改属性最简单的做法是用一个逻辑通道根据空速选择不同的PID参数组或者用script在仿真过程中更新ap/pid_*_kp这些属性。我在实际项目中就用过类似方法F16模型上还有更复杂的增益调度但C172X这种慢速小飞机分段取两组参数基本就够了。5.4 后续扩展思路自动驾驶仪调稳之后再往上走就是真正的“自动飞行”了。你可以加一个VOR导航通道读入飞机相对某个台的角度把它转成目标航向指令也可以加一个简单的航点追踪让飞机依次飞过经纬度点。原理都绕不开PID和坐标误差计算只是输入属性更复杂了一些。我个人特别推荐先把“高度自动保持航向自动保持空速自动保持”这三个基础功能跑顺再加入自动下降、自动进近这类高级功能。基础功能就像学游泳时的换气和蹬腿没协调好之前别急着学蝴蝶腿否则越练越乱。最后给个实在的建议配置自动驾驶仪别急着追求完美曲线先让它平飞再谈转弯和爬升。我见过不少朋友一上来就调航向结果俯仰都没稳定怎么调都乱飞。从最基础的俯仰保持开始你离“放手飞”就不远了。等你在C172X上把这一整套PID参数跑明白再去碰其他机型或者自己的固定翼无人机会发现原理都是同一个参数只是表象。
返回列表