ARTICLE DETAIL

资讯详情

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

附加惯性项BP神经网络让四旋翼姿态控制更稳更准

附加惯性项BP神经网络让四旋翼姿态控制更稳更准 简介针对传统PID控制参数无法在线整定、控制精度不高的问题该研究提出将附加惯性项BP神经网络与PID控制相结合的四旋翼无人机姿态控制方法从无人机自身特性出发通过惯性系数修正和网络参数自整定来提升受扰飞行下的姿态稳定性能。仿真对比表明该方法优于传统PID与常规BP参数自整定PID抗扰性、鲁棒性和动态性能更佳文中还给出了完整的建模过程、参数调整思路和仿真设置分析。资源为PDF格式的完整学术论文压缩包共1个文件大小仅338KB阅读便捷目前已有190人学习属于专业指导类资料。论文发表于《广西师范大学学报自然科学版》涉及PID控制、BP神经网络等知识点适合无人机控制、智能控制及相关交叉领域的研究者与工程技术人员参考。读者可获取将神经网络非线性逼近能力引入PID实时整定的实现思路为后续算法改进或科研设计提供参考。1. 姿态控制里的BP改进附加惯性项为什么值得先复现再判断“基于附加惯性项BP神经网络的四旋翼无人机姿态控制研究”这类题目核心就一句话给经典BP网络的权值更新公式里加一个“惯性项”也叫动量项让它能在四旋翼姿态控制的在线或离线训练场景下更快收敛、更抗震荡。很多做过飞控调参的人都有体会纯PD/PID在姿态环上能用但遇到转动惯量变化、外力干扰时就需要反复试参数几乎靠玄学。而BP神经网络做补偿器又常因为训练不稳定被说成黑匣子。这篇笔记就把这个改进方案的原理、仿真环境、核心代码和踩坑点讲透适合正在做飞控算法验证、学生项目或准备把神经网络落进飞控的工程师和研究者。2. 附加惯性项的本质动量项让BP摆脱局部收敛与锯齿震荡2.1 标准BP在姿态控制闭环里的收敛短板经典BP网络的权值更新公式写成代码是W eta * delta * x其中 eta 是学习率delta 是误差对权值的梯度。这个公式本身没有“速度”的概念每步只按当前梯度方向走。问题在于姿态控制的误差曲面往往有很长的平坦区也存在不少局部极小区。标准BP在平坦区里梯度很小权值更新速度极慢遇到类似沟壑的曲面时更新方向会左右摇摆呈现锯齿状下降。我在实际跑四旋翼仿真时观察到一个现象同一个训练集标准BP训到上千轮Loss还在0.01附近晃而加了动量项的BP在300轮内就压到0.001以下。这个差异放到控制回路里会被放大如果BP是作为前馈补偿器在线工作的它收敛太慢就无法及时补偿突加风扰或吊挂负载带来的力矩突变。如果离线训练标准BP又容易收敛到局部极小区导致网络输出在某一姿态区域特别准、在另一区域彻底偏掉。所以标准BP不是不能用而是在姿态控制这种对实时性和鲁棒性都敏感的场合需要先解决两个问题一是提高收敛速度二是抑制震荡。附加惯性项就是冲着这两个问题去的。2.2 附加惯性项动量因子的公式与物理直觉这里说的附加惯性项在神经网络论文里最常见的叫法是动量项代码写成这样velocity alpha * velocity eta * grad W velocityalpha 是动量因子取值一般在 0.5 到 0.9 之间eta 是学习率velocity 是累积的历史更新量。不难看出这一步等价于对梯度序列做了一次低通滤波让权值更新带有“惯性”不会因为某一步的梯度突变而剧烈转向。物理直觉可以这样理解一个小球在误差曲面上滚不带动量项时它走的每一步都取决于当前坡度遇到局部坑就停住带动量项后小球有了速度累积即使当前梯度为零它也能凭惯性冲过平坦区甚至冲过局部极小点。代价是如果动量因子设得过高小球冲得太狠就可能冲出稳定区域导致权值发散。所以在控制场景里alpha 一般先用 0.5 起步确认Loss下降稳定后再逐步提到 0.8 左右。还有一个容易被忽略的点动量项改变了有效学习率。如果用W alpha * velocity eta * grad这种形式eta 只会影响当前梯度历史量全靠 alpha 衰减。另一种写法会再加1-alpha的缩放工程上建议固定用第一种避免不同论文里的公式混用导致参数不可比。2.3 动量项在四旋翼控制回路里的三种嵌入方式动量项BP在四旋翼姿态控制里怎么嵌入直接影响网络结构和训练方式。我见过并且自己试过的方案主要有三种第一BP网络作为前馈补偿器叠加在PD控制率输出上。这是最稳妥的做法。外环角度环计算期望角速度内环PD输出基础力矩BP网络根据姿态误差和角速度误差输出一个力矩修正量与PD输出相加后送入电机混控。这样做的好处是即使BP训练效果不理想PD仍然能把飞机稳住BP只负责补残差。第二BP网络直接做逆模型控制器输入期望角加速度输出四个电机的油门增量。这种方案理论上响应最快但逆模型对动力学参数误差极其敏感训练数据稍有偏差实机就容易翻车不太建议作为第一个落地方案。第三BP网络在运行中在线调整PID参数。这是增量式PID的自适应变种网络输出Kp、Ki、Kd的修正量。实现起来麻烦在于PID参数和姿态响应之间不是线性关系网络训练时目标函数不好构造。三种方式的对比可以用一张表来说明嵌入方式网络输入网络输出动量项作用适用阶段前馈补偿器角度误差、角速度误差、附加惯性估计值三轴力矩修正量加快在线收敛仿真验证和实物原型逆模型控制器期望角加速度、状态量四电机油门增量辅助拟合非线性逆模型离线训练后的专用场景在线调PID参数误差、误差积分、误差微分Kp/Ki/Kd修正量抑制参数震荡对实时性要求不高的科研验证从我自己的经验看前馈补偿器是最容易复现且不容易“把飞机飞崩”的方案后文的仿真和代码都以此为主线。3. 搭建可复现的仿真框架从姿态模型到BP网络训练闭环3.1 仿真工具选型Python配合Simulink的常见做法做四旋翼姿态控制研究仿真平台一般有三条路纯Simulink、纯Python、Simulink和Python联合。如果是跟着论文复现最省事的组合是Simulink搭六自由度动力学模型用MATLAB自带的神经网络工具箱训练BP再把训练好的权重通过MATLAB Function写入Simulink。这套流程上手快但有一个痛点网络结构一改整个模型要重新导出批量扫动量因子和学习率非常痛苦。我一般倾向用Python做训练和离线仿真用NumPy手写BP和四旋翼刚体动力学。原因有三一是网络结构、动量因子、学习率都可以作为参数传入循环方便做网格搜索二是训练和仿真可以放在同一个pipeline里控制逻辑不会被Simulink的版本兼容问题卡住三是最后要移植到嵌入式环境时NumPy写出来的前向计算逻辑可以直接平移成C语言数组运算。另一个现实考虑是四旋翼动力学模型在Simulink里搭起来虽然直观但如果你要加“附加惯性项”到动力学方程里比如旋翼转动惯量对机体的耦合Simulink里的模块连线反而容易出错。Python里一个状态更新函数就能改完用表格对比更清楚对比项SimulinkPython建模速度快图形化直观中等要写刚体方程网络训练工具箱封装灵活度低可自由改BP公式批量扫参需要脚本控制麻烦for循环即可完成嵌入式移植参考生成的代码偏重逻辑清晰易改写3.2 姿态控制回路建模内环角速度与外环角度的分层四旋翼姿态控制的标准结构是外环角度、内环角速度。外环的输入是期望姿态角输出是期望角速度内环输入是期望角速度和实际角速度的差输出是三个轴的力矩指令。分层的好处是内外环时间尺度拉开后BP补偿器只需要盯住内环的非线性残差不需要直接处理大范围欧拉角变化。动力学方程一般写成机体系下的刚体方程J * omega_dot omega x (J * omega) tau tau_d。这里 J 是转动惯量矩阵omega 是角速度tau 是电机产生的控制力矩tau_d 是外界扰动。很多初学着建模时只写这一条但实际四旋翼还有两个不能丢的环节电机一阶惯性环节和螺旋桨力矩饱和。电机响应可以近似为1 / (tau_m * s 1)tau_m 通常在 0.02 到 0.05 秒之间。如果不加这个延迟BP网络学出来的补偿力矩会比真实执行超前几十毫秒仿真里看不出来实机上就会表现为高频抖动。建模时还需要决定姿态表示方式。仿真范围在正负30度以内可以用欧拉角方便观察如果要做全姿态翻转就必须换四元数。这里有一个很关键的坑欧拉角在90度附近存在奇异后续训练数据里如果包含接近90度的姿态角度微分方程会计算出离谱的角速度这部分数据直接污染训练集。所以我一般把仿真训练数据限定在正负45度以内保证欧拉角远离奇异点。3.3 BP网络结构设计输入层接什么、输出层给谁画BP神经网络结构图时最常见的姿态补偿网络是三层结构输入层、一个隐含层和输出层。以我的前馈补偿器方案为例输入层接六个状态量再加一个附加惯性项特征用公式写就是[e_roll, e_pitch, e_yaw, omega_x, omega_y, omega_z, throttle_weight]。前六个分别是三轴角度误差和三轴角速度第七个是当前油门或总力矩的归一化值用来表征飞行状态。输出层是三轴力矩修正量[delta_tau_x, delta_tau_y, delta_tau_z]。这里要强调的是输出层不要接饱和激活函数。因为力矩修正量需要做线性输出如果接tanh或sigmoid修正量被限制在-1到1之间在大姿态误差下补偿力度不够。隐含层用tanh输出层用线性激活这是姿态控制BP网络的通用做法。隐含层节点数不用贪多。输入7维、输出3维的情况下隐含层8到12个节点就够。节点太多不仅训练时间变长还容易把噪声细节也拟合进去产生过拟合。一个快速验证过拟合的方法训练结束后把网络输出在训练数据分布区间外推一点如果输出剧烈变化说明网络学到了不该学的局部尖峰。3.4 训练数据生成阶跃激励与扫频激励的组合BP训练数据从哪里来是决定方案能否落地的关键。常见做法是在PD控制器闭环下给姿态角施加随机阶跃信号同时记录输入状态和PD控制器的输出。要注意的是这里记录的目标值不是期望姿态角而是“当前PD输出”加上“期望的补偿力矩”的总和这样才能让网络学到残差补偿。我一般会生成两类数据叠加第一类是随机阶跃序列幅度在正负15度到正负30度之间每个阶跃持续1到2秒覆盖低动态范围第二类是扫频激励信号频率从0.1Hz到5Hz用以激发系统的高频响应。两类数据拼接后总样本量在8000到15000条比较够用。太少网络学不到中频段误差特性太多训练占用时间增大但精度提升有限。样本预处理有两个细节。一是每个特征要做零均值归一化尤其是角速度项量纲与角度误差不同不归一化会让隐含层神经元很快饱和。二是要剔除执行器饱和时间段的数据。当电机输出达到饱和时控制力矩与期望不再线性对应BP网络看到这些样本会试图拟合一个不可达的输出训练之后容易出现“仿真里一切正常、真机一推油门就抖”的怪现象。4. 用Python实现附加惯性项BP控制器核心代码与参数说明4.1 带动量项的BP权重更新代码下面这段代码实现了带附加惯性项的BP网络一步训练逻辑用纯NumPy写出便于理解也便于移植import numpy as np def bp_train_one_step(X, y, W1, b1, W2, b2, vW1, vb1, vW2, vb2, eta0.01, alpha0.7): # X: [batch, 7] 输入特征 # y: [batch, 3] 目标力矩修正量 # W1: [7, 10] 输入层到隐含层权重 # b1: [10] 隐含层偏置 # W2: [10, 3] 隐含层到输出层权重 # b2: [3] 输出层偏置 # vW1, vb1, vW2, vb2: 动量项累积值初始化为0 # 前向计算 Z1 np.tanh(X W1 b1) # 隐含层输出 y_hat Z1 W2 b2 # 输出层线性激活 # 反向传播误差 err y - y_hat delta2 err # 输出层梯度 g 1.0 - Z1 ** 2 # tanh 导数 delta1 (delta2 W2.T) * g # 计算各层梯度 gW2 Z1.T delta2 gb2 np.sum(delta2, axis0) gW1 X.T delta1 gb1 np.sum(delta1, axis0) # 附加惯性项作用在这里 vW1 alpha * vW1 eta * gW1 vb1 alpha * vb1 eta * gb1 vW2 alpha * vW2 eta * gW2 vb2 alpha * vb2 eta * gb2 # 更新权重 W1 vW1 b1 vb1 W2 vW2 b2 vb2 loss np.mean(err ** 2) return W1, b1, W2, b2, vW1, vb1, vW2, vb2, loss这段代码里的核心就是五个变量eta、alpha 和四个velocity变量。eta控制当前梯度的步长alpha控制上一轮更新量的保留比例。alpha等于0时代码退化成标准BP这个参数就是标题里说的附加惯性项。使用这段代码时有两点参数建议。第一batch大小不必太大16到32条即可。动量项的实质是给梯度序列做平滑batch太大会让动量项的作用被平均掉。第二训练时如果发现loss出现周期性震荡优先把alpha从0.9降到0.7而不是去动eta。因为eta影响的是单步尺度alpha影响的是速度累积后的超调姿态控制里超调比收敛慢更危险。4.2 附加惯性项参数如何影响姿态响应把动量因子alpha分别设成0、0.5、0.9去跑同一组姿态阶跃仿真可以看到明显的差异。alpha等于0时BP网络训练500轮后的输出仍有高频波动叠加到PD控制器上会让姿态响应曲线出现锯齿alpha等于0.5时曲线明显光滑但大误差时的响应速度提升不显著alpha等于0.9时收敛速度快但在阶跃信号刚开始的0.2秒内补偿力矩会有一段“过冲式”的下降对应到姿态响应上就是轻微的超调。这说明附加惯性项不是越大越好。姿态控制回路本身有PD的阻尼作用BP补偿器引入的动量项如果太重相当于给整个闭环又增加了一个低通环节会让系统相位滞后增大。工程上一个比较稳的组合是eta取0.01alpha取0.75隐含层节点数取10。先固定这两个参数跑通流程再根据自己的飞机模型微调比一开始就追求“最优参数”靠谱得多。另外如果在动力学模型里把旋翼转动惯量也加到J上记得在BP输入层增加一个“附加惯性项估计值”节点。这个节点可以用油门指令或者总升力来近似让网络知道当前飞行状态下惯性模型偏差大致是偏大还是偏小。很多复现者忽略这个输入导致网络在悬停点调得不错一改成大机动就补偿错方向。4.3 控制器与动力学仿真的对拍把BP控制器和四旋翼动力学模型放到同一个仿真循环里每个控制周期的流程是读取当前姿态角和角速度计算期望角度误差输入PD控制器得到基础力矩输入BP网络得到补偿力矩两者求和后经过混控器换算成四个电机油门再经电机一阶延迟得到实际拉力最后更新刚体动力学状态。对拍的时候需要记录两个信号一是误差的均方根值二是补偿力矩占基础力矩的比例。如果补偿力矩长时间超过基础力矩的30%说明BP网络没有被训练在“残差”上而是在尝试完全接管控制律。这种情况下先检查训练数据的label是否正确目标值不应该包含PD的基础输出只包含你希望BP补偿的那部分非线性和扰动。5. 常见问题与避坑5条实操拿得到的经验5.1 动量因子与学习率“打架”导致发散现象训练前期Loss下降很漂亮到后期突然变成NaN或者Loss曲线出现周期性的尖峰。原因alpha设得太大比如0.9同时eta也偏大比如0.1动量项积累的速度量超过梯度约束范围权重更新一步就飞出有效区域。解决先把alpha降到0.5eta降到0.01确认Loss曲线稳定下降后再逐步提高alpha。我一般按每次加0.05的速度调alpha并且观察测试集Loss而不只看训练集。5.2 训练数据不覆盖大姿态导致仿真能飞、真机翻车现象仿真里给30度阶跃能完美跟踪拿到实机做60度大机动时姿态突然反向修正甚至直接翻转。原因训练数据里角速度范围和角度误差范围都被限制在小姿态区间BP网络从没见过大误差输入外推时输出完全不可控。解决训练数据里除了小姿态阶跃至少混入30%的大姿态样本并检查网络输出在大误差区的走势是不是单调递增的。如果不递增说明网络外推失败要补数据重新训练。5.3 欧拉角在90度附近奇异导致角速度反推错现象把训练数据的姿态角范围扩大到接近90度后BP训练Loss异常高且网络输出的补偿力矩在中立点附近出现跳变。原因欧拉角微分变换矩阵在姿态角接近90度时条件数变差用欧拉角差分或反解得到的角速度会出现尖峰。解决把训练数据限制在正负45度以内如果必须做大姿态换四元数表示并在输入特征里使用四元数误差而非欧拉角误差。5.4 执行器饱和与输出层激活函数不匹配现象仿真时BP输出的补偿力矩看起来合理但实际带入混控后电机油门几乎全部顶到上限姿态响应反而变慢。原因输出层若用了tanh激活输出被限制在正负1以内当PD基础力矩已经接近饱和点时BP只能做小幅度修正无法主动限制饱和反之若用线性激活又可能输出过大力矩让执行器长期饱和。解决输出层用线性激活但控制周期最终合流处加饱和限幅模块并在训练时剔除饱和时间段的数据。5.5 随机种子让结果不可复现现象同一套代码和数据每次运行出来的姿态响应曲线都不一样有时超调小有时发散。原因BP网络初始化用的是随机数动量项的累积速度依赖初始化状态后续训练全部被初始权重影响。解决在训练脚本最开始固定随机种子同时把训练好的权重矩阵导出成文件仿真时直接加载不要每跑一次都重新随机初始化。这个看似小问题的坑在论文复现和工程评审时非常关键没有固定种子别人根本没法复现你的结果。6. 从仿真到实物先用这四个验证指标判断方案值不值得继续投入仿真跑通只是第一步真正判断这个方向值不值得从论文走向工程我会用四个验证指标来卡。第一是跟踪带宽。给期望姿态叠加0.1Hz到5Hz的扫频信号对比纯PD和PD加BP补偿后的幅值衰减曲线。如果BP补偿能让你在2Hz附近的幅值衰减减少30%以上说明网络确实补上了动态残差值得继续。第二是稳态误差。在正负30度阶跃下观察稳定后的角度误差BP加PD应该把稳态误差降低到纯PD的50%以下否则说明训练目标构造有问题。第三是鲁棒性。在动力学模型里把转动惯量J整体改变20%看BP补偿后的响应是否仍然稳定。如果一改惯量就发散发抖说明网络只是在死记训练数据。第四是计算开销。把训练好的权重矩阵固定后用目标单片机跑一次前向推理算一下耗时。姿态控制回路一般要求控制周期在2ms以内如果前向推理超过0.5ms就要考虑减少隐含层节点数或做定点化。我自己的教训是有一次调参时把动量因子设到0.95仿真结果漂亮到让人兴奋于是直接上机测试结果推油门后机身就开始持续高频抖动。回头检查才发现训练数据的采样频率和仿真步长不一致动量项积累了一个错误的时延特征。从那天起我养成了一个习惯任何网络改进先做频域验证再看时域曲线最后才碰实物。这个方向本身并不复杂但值得你投入时间去复现它。先跑通仿真再验证频带和鲁棒性最后再谈实机部署每一步都有清晰的验证指标兜底你真正投入后会发现它比纯调PID更接近一种“可控的玄学”希望帮到你。本文还有配套的精品资源点击获取
返回列表