十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

四旋翼无人机模糊控制仿真:从姿态建模到Simulink调参

四旋翼无人机模糊控制仿真:从姿态建模到Simulink调参 简介面向无人机控制与智能控制研究的一套Matlab四旋翼无人机模糊控制仿真资源包可帮助学习者与工程师完成飞行姿态、位置、速度等参数的控制器设计、仿真测试与算法验证。资源共包含13个文件以m脚本为主11个辅以1张示意/截图和1段avi仿真视频整体大小仅1.77MB。m文件覆盖四旋翼动力学建模、模糊控制器实现、仿真启动与轨迹生成等关键模块清晰展示了从系统建模、模糊规则制定到解模糊化的完整流程适合在Matlab/Simulink环境中快速复现和调参。由于四旋翼在真实飞行中常受风力、载荷变化等干扰其中实现的模糊控制方案具有较强的鲁棒性可通过修改隶属函数与规则库直观观察不同控制策略对飞行稳定性的影响。对于正在学习智能控制、准备无人机相关课程设计或毕业设计的学生而言这也是一份低成本的实验参考无需真实飞行即可验证控制算法。目前已有124人学习浏览适合具备一定Matlab基础、正在研究无人机智能控制算法的读者。1. 四旋翼无人机模糊控制仿真先把姿态拿稳再谈飞得好四旋翼无人机的飞控里姿态环几乎决定了整机能不能飞。很多团队第一版都用PID调起来也快但一旦换了机架、改了电机和桨叶PID参数经常要重新整定一轮。模糊控制的价值在于它把“误差大时用力打、误差小时轻轻修”的操作经验写进规则表对模型参数变化不敏感。这个题目对应的完整链条是建立四旋翼姿态模型在MATLAB里设计模糊控制器再通过Simulink闭环仿真验证控制效果。适合刚接触飞控算法、想把模糊控制落到仿真里的工程师也适合做课程设计时需要一个能跑通、能改参数、能解释清楚的仿真框架的人。接下来的内容按建模、控制器设计、仿真接线、发散排查的顺序展开最后给一个不依赖模糊工具箱的纯M语言验证方案。2. 四旋翼动力学建模仿真先要有被控对象模糊控制器再聪明也要有个对象来“推”。建模型的粗细程度取决于你要验证什么如果只看姿态控制逻辑完全可以把四旋翼处理成力矩驱动的刚体不需要涉及复杂的空气动力学细节。2.1 从电机转速到升力和反扭矩X构型的力与力矩四旋翼最常见的布局是X构型四个电机分布在机体对角线方向。每个电机旋转产生的升力与转速平方成正比反扭矩也与转速平方成正比T_i b * Ω_i^2 Q_i d * Ω_i^2其中b是升力系数d是反扭矩系数Ω_i是第i个电机的转速。X构型下滚转力矩由左右电机差速产生俯仰力矩由前后电机差速产生偏航力矩则来自对角线电机反扭矩的差。写成控制分配关系就是% 电机顺序1前左2前右3后左4后右 % U1: 总升力, U2: 滚转力矩, U3: 俯仰力矩, U4: 偏航力矩 % l: 电机到机体中心的力臂长度 U1 b * (w1^2 w2^2 w3^2 w4^2); U2 l * b * (w2^2 - w4^2); % 左右差速产生滚转 U3 l * b * (w1^2 - w3^2); % 前后差速产生俯仰 U4 d * (-w1^2 w2^2 - w3^2 w4^2); % 对角差速产生偏航这段代码的作用是把四个电机转速映射成四个控制量。仿真里通常反过来用控制器算出U1到U4再通过这个矩阵把U解算到每个电机的转速或者直接把U作为模型的力矩输入。力臂l和系数b、d是模型参数后面调仿真发散时这三个值的数量级对不对很关键。2.2 姿态角加速度从哪来欧拉方程与简化模型有了力矩姿态角加速度由转动惯量决定。忽略陀螺力矩和空气阻尼姿态动力学可以简化成三个独立的二阶积分环节d(phi_dot)/dt U2 / Jxx d(theta_dot)/dt U3 / Jyy d(psi_dot)/dt U4 / Jzz这里Jxx、Jyy、Jzz是三轴转动惯量。简化模型丢掉了一些耦合项但对验证模糊控制逻辑完全够用。真正飞起来时陀螺力矩会带来耦合不过那是后续加入角速度环补偿的事不要在第一步仿真里把模型搞得太重。实际项目中我一般先跑这个简化模型确认控制器没问题再逐步加回耦合项。2.3 在MATLAB脚本里建一个可以直接仿真的姿态模型函数这个模型可以写成MATLAB函数方便Simulink用Interpreted MATLAB Function或MATLAB Function模块调用也可以在脚本里用ode45直接跑开环验证function dydt quad_attitude(t, y, U, J) % 状态 y [phi, theta, psi, phi_dot, theta_dot, psi_dot] % 输入 U [U1, U2, U3, U4]本例只使用 U2~U4 phi y(1); theta y(2); psi y(3); p y(4); % 滚转角速度 q y(5); % 俯仰角速度 r y(6); % 偏航角速度 dydt zeros(6,1); dydt(1) p (q*sin(phi) r*cos(phi))*tan(theta); dydt(2) q*cos(phi) - r*sin(phi); dydt(3) (q*sin(phi) r*cos(phi))/cos(theta); dydt(4) U(2)/J(1); dydt(5) U(3)/J(2); dydt(6) U(4)/J(3); enddydt(1)~dydt(3)是欧拉角运动学关系dydt(4)~dydt(6)是角加速度方程。注意当俯仰角接近90度时tan(theta)会发散仿真中如果出现角度跑到奇异点附近要先检查是不是控制器输出过大而不是急着改求解器。用ode45(quad_attitude, [0 5], [0;0;0;0;0;0], [], [0,1,0,0], J)加一个滚转力矩阶跃就可以验证模型对不对。3. 模糊控制器设计误差、误差变化率与7×7规则表模型准备好之后下一步是把模糊控制器设计出来。模糊控制器的设计自由度看起来很高——隶属度函数形状、论域范围、规则表、推理方法都可以改但真正决定控制品质的其实是两件事输入输出变量的定义和规则表的语义是否正确。3.1 为什么姿态环普遍选二维模糊控制器姿态控制是典型的快速随动问题控制器需要同时响应“当前偏差”和“偏差变化的趋势”。二维模糊控制器以误差e和误差变化率ec作为输入结构上等价于一个非线性PD控制器。它的优势在于增益不再是一个固定数而是根据工作点在线变化误差大时输出接近饱和误差小时输出变得平缓。为什么不直接把积分项也做进模糊规则里积分的作用是消除稳态误差但在姿态控制中稳态误差主要来自重力力矩和电机静差这些可以被内回路的积分作用或者模糊PID混合结构吃掉。纯二维模糊控制器的稳态性能偏弱这一点在仿真里很容易看到阶跃响应可能有持续的残差。解决办法在第5章讲模糊PID混合时展开先按二维结构把规则表建好。3.2 输入输出定义先约定误差符号别让规则表自相矛盾规则表里填的语言值符号取决于你对误差的定义方式。我这里统一采用e ref - measured % 期望角度减去实际角度 ec d(e)/dt % 误差变化率输出du是控制量的修正值与电机油门增量同号。采用这个定义时e为负表示“当前角度低于目标”控制器需要输出正的修正力矩把飞机拉回来。规则表里的所有符号都按负反馈逻辑填充抄作业时不要随意改符号否则飞机会越调越发散。3.3 隶属度函数和7×7规则表怎么填输入变量e和ec的论域都设为[-6, 6]每个变量分成7个语言值负大(NB)、负中(NM)、负小(NS)、零(ZO)、正小(PS)、正中(PM)、正大(PB)。隶属度函数用三角形相邻函数之间重叠0.5左右这是最常用的配置既保证平滑过渡又不至于让隶属度饱和。输出du的论域也是[-6, 6]同样7个语言值。规则表是模糊控制器的核心按“同号增强、异号减弱”的原则填写e \ ecNBNMNSZOPSPMPBNBNBNBNBNBNMZOZONMNBNBNBNMNSZOZONSNMNMNMNSZOPSPSZONMNSNSZOPSPSPMPSNSNSZOPSPMPMPMPMZOZOPSPMPBPBPBPBZOZOPMPBPBPBPB规律的物理含义是当e和ec同号时误差正在增大输出要加大力度当e和ec异号时误差在回落输出要适当减小避免过头。表格的反对角线附近输出接近ZO这个区域对应系统已经接近稳态控制动作要轻。3.4 用Fuzzy Logic Designer建FIS图形界面和脚本两套操作在MATLAB命令窗口输入fuzzyLogicDesigner可以打开图形界面按变量、隶属度函数、规则三个面板依次配置。这种方式直观适合第一次建控制器时看隶属度函数的形状和规则覆盖情况。但如果是批量实验或者要复现结果我倾向于用脚本建fis newfis(attitude_fuzzy, mamdani); % 输入1误差e论域[-6 6] fis addvar(fis, input, e, [-6 6]); fis addmf(fis, input, 1, NB, trimf, [-8 -6 -4]); fis addmf(fis, input, 1, NM, trimf, [-6 -4 -2]); fis addmf(fis, input, 1, NS, trimf, [-4 -2 0]); fis addmf(fis, input, 1, ZO, trimf, [-2 0 2]); fis addmf(fis, input, 1, PS, trimf, [0 2 4]); fis addmf(fis, input, 1, PM, trimf, [2 4 6]); fis addmf(fis, input, 1, PB, trimf, [4 6 8]); % 输入2误差变化率ec论域[-6 6] fis addvar(fis, input, ec, [-6 6]); % 按同样方式添加ec各隶属度函数命名与e一致 % 输出du fis addvar(fis, output, du, [-6 6]); % 按同样方式添加du各隶属度函数 ruleList [1 1 1 1 1; 4 4 4 1 1; 7 7 7 1 1]; % 每行格式[e的MF索引, ec的MF索引, 输出的MF索引, 权重, 连接词] % 连接词取1表示AND2表示OR fis addrule(fis, ruleList); writefis(fis, attitude_fuzzy);这段代码里的ruleList只是3条示例规则用于说明格式。完整规则表有49条用上面的7×7表逐行填进去即可。writefis生成的.fis文件可以保存也可以直接在Simulink的Fuzzy Logic Controller模块里读取。注意trimf的三个参数是三角形左端点、顶点、右端点相邻函数重叠关系的调整就在这里做。3.5 量化因子和比例因子模糊控制器真正要调的参数FIS内部论域固定是[-6,6]但实际角度误差的单位是弧度或度误差变化率的数值范围也完全不同。量化因子把真实量纲映射到模糊论域比例因子把模糊输出映射回真实控制量e_scaled e * Ke % Ke 6 / e_max ec_scaled ec * Kec % Kec 6 / ec_max u_real du * Ku % Ku u_max / 6初值怎么给取决于你的模型量级。角度以弧度为单位时最大误差0.5 rad那么Ke取12左右角速度误差变化率最大约2 rad/sKec取3左右电机油门修正量最大0.2Ku取0.033。这三个参数是仿真发散时最先排查的对象第5章会具体展开。4. Simulink仿真搭建把FIS接进闭环的最小结构控制器设计完成后进入仿真验证环节。Simulink里搭一个最小闭环只需要六个模块重点是理解信号流向而不是堆模块数量。4.1 最小闭环模块清单与连接顺序模块参数设置作用StepFinal value设为0.5Step time设为0给滚转角一个0.5 rad的阶跃目标Sum符号设为 -计算误差 e ref - measuredFuzzy Logic Controller调用工作区内的fis对象计算模糊输出Gain设为Ku比例因子把论域值还原成真实控制量Saturation上下限设为实际油门限幅防止控制量超出执行机构能力Scope / To Workspace记录时间与角度响应用于性能分析连接顺序是Step输出接到Sum正端模型输出接到Sum负端Sum输出同时进入Fuzzy Logic Controller模块和一路微分环节误差变化率。模糊控制器模块默认只接受一个向量输入所以需要把e和ec用Mux合成一个二维向量模块内部会自动按FIS定义的输入顺序读取。4.2 FIS怎么装进Simulinkreadfis与工作区变量Fuzzy Logic Controller模块运行时从MATLAB工作区读取变量。最稳妥的做法是在模型初始化脚本或命令窗口里先执行fis readfis(attitude_fuzzy);然后在模块参数对话框里把“FIS file or name”填成工作区变量名fis。这里有个常见坑如果改了FIS文件但没有重新执行readfisSimulink里跑的仍然是旧的控制器。参数扫描前务必先刷新工作区变量。另一种做法是直接在模块参数里填.fis文件路径Simulink每次仿真开始都会重新加载代价是启动稍慢。4.3 求解器与仿真步长避开仿真发散的第一道门槛模糊控制器本质上是非线性环节包含查表、取极值、重心法计算这些运算不会改变连续性但会让系统对步长敏感。姿态模型的时间常数通常在0.1到0.5秒量级角速度环更快因此仿真步长要压到1毫秒以下才保险。配置现象建议变步长ode45触发时刻附近步长骤减仿真变慢只用于开环模型检查固定步长ode4步长0.01s高频动态被步长滤掉可能表现虚假稳定偏大不推荐固定步长ode4步长0.001s结果平滑速度和精度平衡推荐起点固定步长ode3步长0.0005s更稳但更慢发散排查时使用求解器设置路径是“仿真”→“模型配置参数”→“求解器”类型选“固定步长”求解器选ode4四阶龙格库塔。步长先设0.001跑通后再尝试放大到0.002观察响应是否仍然一致。模糊控制器运行时间很短真正的计算瓶颈在模型的高频动态所以步长不是越大越好。4.4 阶跃响应与性能指标提取闭环跑通后用To Workspace模块把角度和误差存到工作区然后写脚本提取性能指标% 假设 out.phi 是滚转角序列out.t 是时间序列 idx find(out.t 5, 1); % 稳态段从5秒开始 steady out.phi(end); % 超调量 overshoot (max(out.phi) - steady) / steady * 100; % 上升时间从10%到90%稳态值 y10 steady * 0.1; y90 steady * 0.9; t10 out.t(find(out.phi y10, 1)); t90 out.t(find(out.phi y90, 1)); rise_time t90 - t10; fprintf(超调量: %.2f%%, 上升时间: %.3f s\n, overshoot, rise_time);这段脚本的作用是把Scope里肉眼看的曲线变成数值。find函数找到第一次越过阈值的时间点t90-t10就是上升时间。超调量大于30%时优先减小Ku而不是改规则表上升时间过慢时优先增大Ke和Kec。下一章会讲这些调整的顺序和边界。5. 发散与震荡排错先查模型再调Ke最后改规则仿真发散是模糊控制调试里出现频率最高的问题。现象通常有两种曲线直接飞到NaN或者输出剧烈震荡发散。很多人第一反应是改规则表实际上大多数发散与规则无关。5.1 仿真发散的高频原因与排查顺序优先级原因现象验证方法修正1模型本身开环不稳定或参数量级错误不加控制器就发散去掉Fuzzy模块给模型一个固定力矩输入检查J、b、d的单位和数值2量化因子过大角度小幅震荡且越来越剧烈把Ke、Kec缩小到1/10再跑按e_max、ec_max重新计算3控制量未限幅输出饱和后角度快速翻转查看控制量曲线是否超限加Saturation设真实油门范围4步长过大曲线在特定相位跳变把步长从0.001改到0.0001换ode4固定步长5单位不一致同一套参数换模型后完全失控检查角度单位是弧度还是度统一到弧度制这里要特别强调第2条。模糊控制器的规则表只在论域内有意义当e超出最大论域时最外侧隶属度函数饱和控制器处于“开环”状态——无论误差怎么加大输出都不再变化。此时整个闭环相当于一个固定增益系统很容易发散。量化因子的取值以“让e和ec的峰值落在论域的60%到90%区间”为基准不是越大越好。排查顺序我个人习惯是先在Simulink里禁用Fuzzy模块改成直接给模型一个常数力矩确认模型本身响应正常再恢复模糊控制器把Ke、Kec设成很小值跑一次确认闭环稳定最后逐步加大量化因子到正常范围。如果小增益下发散问题一定在模型或接线不是规则表。5.2 从纯模糊到模糊PID混合纯二维模糊控制的稳态误差问题在仿真里表现为阶跃响应最终停在目标角度旁边一个固定偏移上。消除它最直接的做法是模糊PID混合外层模糊控制器负责输出PID增益修正量内层PID负责实际控制执行。具体接线方式是误差e同时进入模糊控制器和PID控制器模糊控制器的输出不再是控制量而是Kp、Ki、Kd三个增益的修正系数。模糊输出论域设为[0,1]乘以基准增益后得到最终PID参数。这样保留模糊控制的非线性适应能力又借助PID的积分项消除稳态误差。Simulink里用三个Fuzzy Logic Controller模块分别输出三个增益修正系数或者用一个三输出FIS。5.3 用sim()脚本批量扫描Ke和Kec手动在Simulink里改参数再点运行效率太低。把控制器参数放到工作区变量用脚本循环调用sim函数可以实现批量参数扫描Ke_list [8 12 16 20]; Kec_list [2 3 4 5]; results []; for i 1:length(Ke_list) for j 1:length(Kec_list) Ke Ke_list(i); Kec Kec_list(j); % Simulink模型名称为quad_sim输入输出用工作区变量传递 simOut sim(quad_sim, StopTime, 10); phi simOut.phi.Data; t simOut.phi.Time; steady phi(end); overshoot (max(phi) - steady) / steady * 100; results(end1, :) [Ke, Kec, overshoot]; %#okSAGROW end endsim函数第一个参数是模型名模型内所有Gain模块的增益都直接引用工作区变量Ke、Kec每次循环赋值后重新仿真即可。结果矩阵的第三列是超调量按超调量最小、上升时间次优的顺序筛选就是一组可用的起始参数。这套脚本也可以扩展到扫描Ku和规则表缩放系数。6. 把FIS固化成纯M函数不依赖模糊工具箱也能跑仿真有的MATLAB许可证不带Fuzzy Logic Toolbox或者需要在其他语言环境复现仿真结果这时把FIS逻辑改写成纯M语言函数就很有用。下面是一个最小可用的Mamdani推理实现。6.1 手写Mamdani推理的最小实现function u fuzzy_pd(e, ec, Ke, Kec, Ku) % 简化版二维模糊控制器使用3个语言值N, ZO, P % 输入偏差e与偏差变化率ec经过量化后进入规则表 x1 max(0, 1 - abs(e*Ke - (-3))/3); % 三角形隶属度 N x2 max(0, 1 - abs(e*Ke - 0)/3); % ZO x3 max(0, 1 - abs(e*Ke - 3)/3); % P % ec同理得到 y1,y2,y3共3个隶属度 % 规则表e(N,ZO,P) x ec(N,ZO,P) - 输出(N,ZO,P) % 规则含义误差负且误差变化率负 - 输出负反向校正 rule_out [1 1 2; 1 2 2; 2 2 3; 2 3 3; 3 3 3]; % 1N, 2ZO, 3P u_fuzzy 0; w_sum 0; for i 1:3 for j 1:3 w min( [x1 x2 x3](i), [y1 y2 y3](j) ); % AND out_val rule_out(i,j); u_fuzzy u_fuzzy w * (out_val - 2); % 映射到[-1,1] w_sum w_sum w; end end if w_sum 0 u u_fuzzy / w_sum * Ku; % 重心法去模糊化 else u 0; end end这个函数省去了隶属度函数库的通用计算直接在循环里完成推理和去模糊化。rule_out是3×3规则表数值1、2、3分别对应负、零、正三个语言值。min函数实现模糊AND运算重心法用加权平均替代积分对小规模规则表精度足够。实际使用前用同一组e和ec分别调用evalfis和fuzzy_pd对比输出曲线形状是否一致。6.2 手写函数与Simulink模型联调把fuzzy_pd函数放进MATLAB Function模块就可以在不加载FIS文件的情况下运行闭环仿真。验证通过后这段纯M函数可以直接翻译成C代码嵌入到实际的飞控固件里。至此从模型到控制器再到仿真验证的完整链路已经打通剩下的工作就是按第5章的参数扫描脚本把Ke、Kec、Ku三个系数针对具体机型的模型参数再扫一遍。本文还有配套的精品资源点击获取
返回列表