網(wǎng)絡(luò)補(bǔ)償?shù)臒o(wú)人機(jī)姿態(tài)自適應(yīng)控制仿真)
簡(jiǎn)介針對(duì)四旋翼無(wú)人機(jī)姿態(tài)控制中模型不完整、參數(shù)不確定和外界擾動(dòng)等難題這份 PDF 論文提出了一種基于 RBF 神經(jīng)網(wǎng)絡(luò)的無(wú)人機(jī)姿態(tài)自適應(yīng)控制方法。內(nèi)容從四旋翼動(dòng)力學(xué)建模入手詳細(xì)闡述了利用 RBF 神經(jīng)網(wǎng)絡(luò)在線學(xué)習(xí)模型不確定項(xiàng)與外界擾動(dòng)的原理并基于反步法設(shè)計(jì)包含反饋控制和神經(jīng)網(wǎng)絡(luò)控制的自適應(yīng)控制器同時(shí)給出了網(wǎng)絡(luò)權(quán)值自適應(yīng)律利用李雅普諾夫方法對(duì)閉環(huán)系統(tǒng)穩(wěn)定性進(jìn)行了嚴(yán)格證明。文中還提供了仿真結(jié)果分析展示了在較大擾動(dòng)情況下誤差快速收斂、系統(tǒng)具備較好魯棒性和自適應(yīng)性的控制效果可供相關(guān)課題直接參考。資源為單文件 PDF大小約 3.65MB適合自動(dòng)化、控制工程及無(wú)人機(jī)方向的研究生和工程師學(xué)習(xí)使用已有 269 人學(xué)習(xí)下載。 無(wú)人機(jī)飛得好不好說(shuō)到底就是一個(gè)字調(diào)。但調(diào)PID這件事做過(guò)飛控的人都知道有多折磨。尤其到了姿態(tài)環(huán)P值給大了抖D值給小了飄懸停剛穩(wěn)住風(fēng)一吹又開始蕩。我前前后后調(diào)過(guò)好幾架四旋翼從純手調(diào)到自動(dòng)調(diào)參工具都試過(guò)始終繞不開一個(gè)問(wèn)題控制器參數(shù)是固定的但無(wú)人機(jī)在空中遇到的環(huán)境、載重、重心變化卻是隨時(shí)在變的。所以當(dāng)我決定把神經(jīng)網(wǎng)絡(luò)引入姿態(tài)控制時(shí)思路很簡(jiǎn)單——與其花幾個(gè)晚上反復(fù)試湊增益不如讓控制器自己學(xué)會(huì)補(bǔ)償那些說(shuō)不清、算不準(zhǔn)的非線性擾動(dòng)。這篇文章就記錄了我用MATLAB/Simulink做“基于神經(jīng)網(wǎng)絡(luò)的無(wú)人機(jī)姿態(tài)自適應(yīng)控制仿真”的完整過(guò)程包括數(shù)學(xué)模型、控制器結(jié)構(gòu)、代碼實(shí)現(xiàn)和踩坑實(shí)錄。不管是正在做畢業(yè)設(shè)計(jì)的自動(dòng)化學(xué)生還是想給飛控加點(diǎn)智能算法的愛好者都可以直接參考這套框架。1. 為什么傳統(tǒng)PID在無(wú)人機(jī)姿態(tài)控制上不夠用1.1 四旋翼姿態(tài)控制到底難在哪先說(shuō)清楚被控對(duì)象。四旋翼是一個(gè)典型的欠驅(qū)動(dòng)、強(qiáng)耦合、非線性系統(tǒng)四個(gè)電機(jī)的轉(zhuǎn)速變化同時(shí)影響滾轉(zhuǎn)、俯仰、偏航和總升力任何一個(gè)通道的動(dòng)作都會(huì)牽扯到另外幾個(gè)通道。實(shí)際飛行中氣動(dòng)阻尼、陀螺力矩、旋翼尾流擾動(dòng)都在實(shí)時(shí)變化而且變化的規(guī)律很難精確建模。更麻煩的是不確定性。比如我用的機(jī)架是仿F450結(jié)構(gòu)裝上電池、相機(jī)、云臺(tái)之后質(zhì)量和轉(zhuǎn)動(dòng)慣量已經(jīng)和出廠參數(shù)不一樣了。換一塊更重的電池重心哪怕偏移幾毫米懸停時(shí)就需要一個(gè)恒定的姿態(tài)偏置來(lái)補(bǔ)償。這種情況下一組固定增益的姿態(tài)PID是難以同時(shí)滿足“動(dòng)態(tài)響應(yīng)快”和“穩(wěn)態(tài)不震蕩”這兩個(gè)要求的。1.2 傳統(tǒng)控制的三個(gè)死穴第一個(gè)死穴是模型依賴。LQR、反步法、滑??刂贫夹枰鄬?duì)精確的模型參數(shù)但這些參數(shù)在實(shí)際飛行中變化很大。第二個(gè)死穴是固定增益。PID三個(gè)增益一整定好就不再變遇到大風(fēng)、掛載投擲這類突變工況要么反應(yīng)太慢要么超調(diào)振蕩。第三個(gè)死穴是難以處理強(qiáng)非線性。四旋翼的動(dòng)力學(xué)本身包含三角函數(shù)、耦合項(xiàng)、執(zhí)行器飽和傳統(tǒng)的線性化方法在小角度假設(shè)下勉強(qiáng)可用一旦做敏捷機(jī)動(dòng)就原形畢露。1.3 神經(jīng)網(wǎng)絡(luò)在這里扮演什么角色神經(jīng)網(wǎng)絡(luò)在姿態(tài)控制里的定位不是完全替代PID而是做一個(gè)“在線補(bǔ)償器”。核心思路是基礎(chǔ)控制仍由PID或PD完成保證系統(tǒng)穩(wěn)定神經(jīng)網(wǎng)絡(luò)則負(fù)責(zé)估計(jì)系統(tǒng)的未建模動(dòng)態(tài)、參數(shù)攝動(dòng)和外部擾動(dòng)并把補(bǔ)償量疊加上去。這樣既保留經(jīng)典控制的可靠性又獲得自適應(yīng)能力。我選用的是RBF徑向基函數(shù)網(wǎng)絡(luò)原因是它結(jié)構(gòu)簡(jiǎn)單、局部逼近能力強(qiáng)、在線計(jì)算量小非常適合部署在飛控這種算力受限的嵌入式環(huán)境里。相比需要大量數(shù)據(jù)離線訓(xùn)練的深度網(wǎng)絡(luò)RBF網(wǎng)絡(luò)可以在仿真過(guò)程中實(shí)時(shí)更新權(quán)值真正做到“邊飛邊學(xué)”。2. 被控對(duì)象建模四旋翼的數(shù)學(xué)模型和參數(shù)設(shè)置2.1 坐標(biāo)系和歐拉角約定仿真第一步是建立無(wú)人機(jī)的數(shù)學(xué)模型。我采用最常見的“機(jī)體坐標(biāo)系B 地面坐標(biāo)系E”雙坐標(biāo)系方案地面坐標(biāo)系用來(lái)描述位置和姿態(tài)參考方向機(jī)體坐標(biāo)系固定在機(jī)身上隨無(wú)人機(jī)一起運(yùn)動(dòng)。兩者之間的轉(zhuǎn)換通過(guò)ZYX順序的歐拉角實(shí)現(xiàn)——先偏航y(tǒng)aw繞Z軸再俯仰pitch繞Y軸最后滾轉(zhuǎn)roll繞X軸。姿態(tài)角的角速度關(guān)系和很多人理解的不太一樣歐拉角的導(dǎo)數(shù)并不直接等于機(jī)體角速度。真正的運(yùn)動(dòng)學(xué)方程是roll_dot p sin(roll)*tan(pitch)*q cos(roll)*tan(pitch)*r pitch_dot cos(roll)*q - sin(roll)*r yaw_dot sin(roll)/cos(pitch)*q cos(roll)/cos(pitch)*r這里 p、q、r 是機(jī)體坐標(biāo)系下的三軸角速度。我在仿真里沒(méi)有做小角度近似而是用完整的非線性方程為的就是讓控制器在大姿態(tài)角下也能被驗(yàn)證。2.2 剛體動(dòng)力學(xué)方程姿態(tài)動(dòng)力學(xué)方程用牛頓-歐拉法推導(dǎo)核心是機(jī)體坐標(biāo)系下的力矩平衡I * omega_dot -omega × (I * omega) M_prop M_dist展開后就是三個(gè)軸的角加速度方程p_dot ( (Iy-Iz)*q*r Mx ) / Ix q_dot ( (Iz-Ix)*p*r My ) / Iy r_dot ( (Ix-Iy)*p*q Mz ) / Iz其中 Mx、My、Mz 是作用在機(jī)體上的總力矩包括電機(jī)轉(zhuǎn)速差產(chǎn)生的控制力矩和氣動(dòng)阻力矩。-omega × (I*omega) 這一項(xiàng)就是陀螺力矩很多初學(xué)者會(huì)忽略它但在快速偏航或翻滾時(shí)它的影響非常明顯——如果控制器沒(méi)有足夠的魯棒性這個(gè)交叉耦合項(xiàng)會(huì)讓姿態(tài)響應(yīng)出現(xiàn)肉眼可見的“串?dāng)_”。2.3 模型參數(shù)怎么設(shè)置我仿真里用的參數(shù)參考了一臺(tái)1.5kg級(jí)四旋翼的實(shí)測(cè)值參數(shù)數(shù)值說(shuō)明質(zhì)量 m1.5 kg含電池負(fù)載滾轉(zhuǎn)慣量 Ix0.012 kg·m2繞X軸俯仰慣量 Iy0.012 kg·m2繞Y軸偏航慣量 Iz0.022 kg·m2繞Z軸力臂長(zhǎng)度 l0.225 m機(jī)臂長(zhǎng)度升力系數(shù) cT1.5e-5 N/(rad/s)2螺旋槳阻力系數(shù) cQ2.0e-7 N·m/(rad/s)2螺旋槳電機(jī)到升力和力矩的關(guān)系按標(biāo)準(zhǔn)十字布局計(jì)算F_total cT * (w12 w22 w32 w42) Mx l*cT*(w12 - w32) My l*cT*(w22 - w42) Mz cQ*(w12 - w22 w32 - w42)通過(guò)這套模型我就能在Simulink里搭建一個(gè)“虛擬無(wú)人機(jī)”用它來(lái)驗(yàn)證控制器在不同擾動(dòng)下的表現(xiàn)。3. 神經(jīng)網(wǎng)絡(luò)自適應(yīng)控制器設(shè)計(jì)3.1 控制器總體架構(gòu)整個(gè)姿態(tài)控制采用的是內(nèi)外環(huán)串級(jí)結(jié)構(gòu)內(nèi)環(huán)是角速度環(huán)快回路外環(huán)是姿態(tài)角環(huán)慢回路。外環(huán)PID生成期望角速度內(nèi)環(huán)負(fù)責(zé)實(shí)際跟蹤。神經(jīng)網(wǎng)絡(luò)不單獨(dú)做控制器而是并聯(lián)在角速度環(huán)PID的輸出端疊加一個(gè)補(bǔ)償力矩。這個(gè)架構(gòu)最大的好處是就算神經(jīng)網(wǎng)絡(luò)輸出異常底層的PID仍然能維持系統(tǒng)基本穩(wěn)定安全性有兜底。這是我當(dāng)時(shí)在筆記里畫的信號(hào)流向按這個(gè)理解就不會(huì)亂姿態(tài)角給定 —— 姿態(tài)角PID —— 角速度給定 —— 角速度PID —— [疊加神經(jīng)網(wǎng)絡(luò)補(bǔ)償] —— 電機(jī)混控 —— 四旋翼動(dòng)力學(xué) —— 姿態(tài)角輸出 ↑ 角速度誤差、誤差導(dǎo)數(shù)注入RBF網(wǎng)絡(luò) —— 網(wǎng)絡(luò)輸出補(bǔ)償力矩3.2 RBF網(wǎng)絡(luò)結(jié)構(gòu)我用的RBF網(wǎng)絡(luò)是最簡(jiǎn)潔的一種結(jié)構(gòu)。輸入層取兩個(gè)關(guān)鍵狀態(tài)量——角速度誤差 e 和角速度誤差變化率 ec隱藏層取5個(gè)高斯徑向基節(jié)點(diǎn)輸出層是1個(gè)補(bǔ)償力矩。高斯徑向基函數(shù)定義為phi_j(x) exp( -||x - c_j||2 / (2*sigma_j2) )其中 c_j 是第j個(gè)基函數(shù)的中心sigma_j 是寬度。這一步有講究基函數(shù)中心和寬度的選取直接決定網(wǎng)絡(luò)能在哪個(gè)輸入范圍產(chǎn)生有效響應(yīng)。我把中心均勻設(shè)置在 [-2, 2] × [-2, 2] 的網(wǎng)格上寬度取0.8這樣覆蓋了大部分實(shí)際飛行的角速度誤差范圍。中心太密會(huì)增加計(jì)算量太疏則局部逼近性能下降5個(gè)節(jié)點(diǎn)對(duì)單通道補(bǔ)償來(lái)說(shuō)是夠用的。網(wǎng)絡(luò)輸出就是簡(jiǎn)單的加權(quán)和M_nn sum( w_j * phi_j(x) )w_j 是輸出層權(quán)值需要通過(guò)自適應(yīng)律實(shí)時(shí)更新。3.3 自適應(yīng)律推導(dǎo)為什么權(quán)值這樣更新這里如果不解釋清楚整個(gè)設(shè)計(jì)和“玄學(xué)調(diào)參”沒(méi)區(qū)別。核心思想是構(gòu)造一個(gè)李雅普諾夫函數(shù)讓權(quán)值更新律保證系統(tǒng)狀態(tài)收斂。定義角速度跟蹤誤差為 e omega_d - omega并構(gòu)造滑模面 s e c*integral(e)。控制目標(biāo)是讓 s 趨于零。對(duì)滑模面求導(dǎo)并把四旋翼動(dòng)力學(xué)方程代入整理后可以得到一個(gè)形如s_dot -k*s (f_uncertain - W*phi(x))的形式其中 f_uncertain 是模型不確定項(xiàng)Wphi(x) 是RBF網(wǎng)絡(luò)對(duì)它的估計(jì)。如果能做到 f_uncertain ≈ Wphi(x)那么誤差項(xiàng)就被抵消了系統(tǒng)退化為線性穩(wěn)定的形式 s_dot -k*s。我構(gòu)造李雅普諾夫候選函數(shù)V 0.5*s2 0.5/gamma * sum(w_tilde_j2)其中 w_tilde_j w_j* - w_j 是權(quán)值估計(jì)誤差gamma 是學(xué)習(xí)率。對(duì) V 求導(dǎo)選擇合適的權(quán)值更新律使 V_dot ≤ 0就能證明跟蹤誤差和權(quán)值誤差是有界的。最終的權(quán)值更新律非常簡(jiǎn)單w_j_dot gamma * s * phi_j(x)這就是經(jīng)典的梯度下降形式的在線修正規(guī)則。在Simulink里實(shí)現(xiàn)時(shí)我用一個(gè)積分器對(duì) w_j_dot 做積分就得到每一時(shí)刻的權(quán)值。學(xué)習(xí)率 gamma 我取0.05太大權(quán)值震蕩劇烈太小自適應(yīng)速度跟不上。3.4 為什么不用標(biāo)準(zhǔn)BP網(wǎng)絡(luò)和深度網(wǎng)絡(luò)這個(gè)坑我替大家踩過(guò)了。最開始我用的是標(biāo)準(zhǔn)BP神經(jīng)網(wǎng)絡(luò)vanilla RNN的思路把角速度誤差序列作為輸入用時(shí)間反向傳播更新權(quán)值。結(jié)果在純仿真里表現(xiàn)尚可但仔細(xì)分析后發(fā)現(xiàn)問(wèn)題BP反向傳播每一層都要計(jì)算梯度在線運(yùn)行時(shí)每一控制周期都要做一遍矩陣運(yùn)算計(jì)算量是RBF的幾十倍更重要的是BP網(wǎng)絡(luò)是全局逼近任何輸入的微小變化都會(huì)導(dǎo)致所有神經(jīng)元權(quán)值一起調(diào)整在線學(xué)習(xí)的穩(wěn)定性很差。深度網(wǎng)絡(luò)就更不用說(shuō)了。姿態(tài)控制是一個(gè)毫秒級(jí)的實(shí)時(shí)任務(wù)每個(gè)控制周期一般只有1~10毫秒深度網(wǎng)絡(luò)的前向推理和反向傳播根本跑不滿這個(gè)時(shí)間約束。RBF網(wǎng)絡(luò)雖然結(jié)構(gòu)簡(jiǎn)單但足夠逼近連續(xù)非線性函數(shù)而且是局部響應(yīng)——輸入在某個(gè)基函數(shù)中心附近時(shí)只有對(duì)應(yīng)的少數(shù)節(jié)點(diǎn)被激活權(quán)值更新互不干擾在線學(xué)習(xí)的穩(wěn)定性和收斂速度都好得多。同理我也不推薦在姿態(tài)內(nèi)環(huán)用LSTM這類時(shí)序網(wǎng)絡(luò)。雖然它們能建模時(shí)間相關(guān)性但計(jì)算開銷和實(shí)現(xiàn)復(fù)雜度都是這個(gè)場(chǎng)景無(wú)法接受的。把時(shí)序記憶放在外環(huán)規(guī)劃層面可以放在內(nèi)環(huán)控制層面就是給飛控增加不必要的負(fù)擔(dān)。4. 仿真搭建與核心代碼實(shí)現(xiàn)4.1 仿真環(huán)境選型的取舍仿真平臺(tái)我選的是MATLAB/Simulink主要原因是控制算法驗(yàn)證方便、自帶豐富的積分器和信號(hào)可視化工具。Simulink的S-Function塊可以嵌入自定義的C語(yǔ)言或MATLAB代碼用來(lái)描述神經(jīng)網(wǎng)絡(luò)的在線更新特別順手。為了仿真我裝的是MATLAB R2021a這個(gè)版本對(duì)S-Function的支持已經(jīng)很成熟。如果不方便用MATLAB也可以用Python替代用numpy自己寫四旋翼動(dòng)力學(xué)用scipy.integrate求解微分方程控制器部分直接面向?qū)ο髮?shí)現(xiàn)。我下文會(huì)給出兩個(gè)版本的核心代碼。4.2 MATLAB腳本四旋翼動(dòng)力學(xué)與RBF控制器先貼一段最核心的MATLAB腳本結(jié)構(gòu)。動(dòng)力學(xué)部分用一個(gè)函數(shù)文件描述返回姿態(tài)角速度和角加速度f(wàn)unction [dot_state] quad_dynamics(state, M, params) % state: [roll; pitch; yaw; p; q; r] % M: 控制力矩向量 [Mx; My; Mz] % params: 結(jié)構(gòu)體包含慣性參數(shù) phi state(1); theta state(2); psi state(3); p state(4); q state(5); r state(6); % 運(yùn)動(dòng)學(xué)方程歐拉角變化率 dot_phi p sin(phi)*tan(theta)*q cos(phi)*tan(theta)*r; dot_theta cos(phi)*q - sin(phi)*r; dot_psi sin(phi)/cos(theta)*q cos(phi)/cos(theta)*r; % 動(dòng)力學(xué)方程角加速度 Ix params.Ix; Iy params.Iy; Iz params.Iz; dot_p ((Iy-Iz)*q*r M(1)) / Ix; dot_q ((Iz-Ix)*p*r M(2)) / Iy; dot_r ((Ix-Iy)*p*q M(3)) / Iz; dot_state [dot_phi; dot_theta; dot_psi; dot_p; dot_q; dot_r]; endRBF神經(jīng)網(wǎng)絡(luò)控制器的核心是權(quán)值更新。這段代碼放在Simulink的S-Function里每個(gè)采樣周期調(diào)用一次function [M_nn, w_new] rbf_controller(e, ec, w, x) % 輸入e角速度誤差, ec誤差變化率, 上一時(shí)刻權(quán)值, 基函數(shù)參數(shù) % 輸出神經(jīng)網(wǎng)絡(luò)補(bǔ)償力矩, 更新后的權(quán)值 % 基函數(shù)中心和寬度 c [-2 -1 0 1 2; -2 -1 0 1 2]; % 二維中心網(wǎng)格 sigma 0.8; % 計(jì)算高斯徑向基輸出 phi zeros(1, 5); for j 1:5 phi(j) exp(-((e-c(1,j))^2 (ec-c(2,j))^2) / (2*sigma^2)); end % 權(quán)值更新律 w_j_dot gamma * s * phi_j gamma 0.05; s e 0.5 * integral_ec; % 滑模面 w_dot gamma * s * phi; w_new w w_dot * dt; % 輸出補(bǔ)償力矩 M_nn w_new * phi; end4.3 Simulink集成要點(diǎn)在Simulink里搭建時(shí)模塊連線并不復(fù)雜。我用三個(gè)積分器串聯(lián)表示姿態(tài)角和角速度狀態(tài)第一個(gè)積分器輸出姿態(tài)角輸入是角速度第二個(gè)積分器輸出角速度輸入是角加速度第三個(gè)積分器用來(lái)計(jì)算誤差積分項(xiàng)。S-Function塊接收角速度誤差和誤差變化率輸出補(bǔ)償力矩給混控模塊。比較值得注意的兩個(gè)細(xì)節(jié)一是基本采樣時(shí)間我設(shè)的是0.002秒即500Hz控制頻率模擬真實(shí)飛控Pixhawk默認(rèn)姿態(tài)環(huán)就是這個(gè)頻率。二是積分器初值第一次跑仿真時(shí)我初始姿態(tài)角設(shè)置了[5°, -3°, 0°]相當(dāng)于給控制器一個(gè)初始偏差測(cè)試它能不能快速拉回水平。這里的響應(yīng)曲線最能說(shuō)明問(wèn)題初始偏差歸零越快控制器的瞬態(tài)性能越好。4.4 Python版本如果不用MATLAB在Gazebo里跑過(guò)仿真的人都知道ROS和Gazebo的環(huán)境配置有時(shí)候比寫控制算法還折磨人。這里我分享一個(gè)輕量級(jí)的Python仿真方案更利于理解控制算法的本質(zhì)對(duì)于只關(guān)注算法原理驗(yàn)證的場(chǎng)景是完全足夠的。核心代碼如下import numpy as np from scipy.integrate import solve_ivp class RBFController: def __init__(self, n_centers5, gamma0.05, dim2): self.gamma gamma self.sigma 0.8 centers np.linspace(-2, 2, n_centers) self.c np.array(np.meshgrid(centers, centers)).T.reshape(-1, dim) self.w np.zeros(len(self.c)) def phi(self, x): # 高斯徑向基函數(shù) d np.linalg.norm(self.c - x, axis1) return np.exp(-d**2 / (2 * self.sigma**2)) def update(self, e, ec, s): phis self.phi(np.array([e, ec])) self.w self.gamma * s * phis return np.dot(self.w, phis) # 補(bǔ)償力矩 # 主仿真循環(huán) def simulate(): params {Ix: 0.012, Iy: 0.012, Iz: 0.022} state np.array([0.05, -0.02, 0, 0, 0, 0]) # 初始小角度偏移 rbf RBFController() dt 0.002 for t in range(10000): # 這里根據(jù)姿態(tài)角和角速度誤差調(diào)用rbf.update()再疊加PID輸出 # 用歐拉積分更新state passPython方案的好處是能直接在腳本里打日志、畫曲線、做批量參數(shù)掃描特別適合論文里的參數(shù)對(duì)比實(shí)驗(yàn)。缺點(diǎn)是沒(méi)有Simulink那種可視化搭模型的方式被控對(duì)象和控制器之間的連接需要自己在代碼里捏合。最開始跑的時(shí)候我建議先用Simulink搭一遍對(duì)信號(hào)流有整體感覺(jué)再遷移到Python做大規(guī)模實(shí)驗(yàn)。5. 結(jié)果分析自適應(yīng)效果與踩坑實(shí)錄5.1 測(cè)試工況怎么設(shè)計(jì)才有說(shuō)服力仿真只設(shè)定懸停一個(gè)工況是不夠的控制器到底自適應(yīng)在哪里需要用多種工況來(lái)驗(yàn)證。我設(shè)計(jì)了四組實(shí)驗(yàn)階躍給定給一個(gè)30°的俯仰角階躍考察跟蹤速度和超調(diào)量。風(fēng)擾力矩在2秒時(shí)注入一個(gè)8 m/s的持續(xù)陣風(fēng)擾動(dòng)力矩看看控制器能否頂住。參數(shù)突變?cè)诘?秒把質(zhì)量從1.5kg突加到1.8kg模擬掛載載荷的變化。重心偏移給機(jī)體添加一個(gè)恒定的偏置力矩模擬重心偏離幾何中心的情況。每一組都有對(duì)照組即不帶神經(jīng)網(wǎng)絡(luò)、只有PID的版本。同一套PID參數(shù)跑兩組對(duì)照差異一目了然。5.2 實(shí)測(cè)結(jié)果神經(jīng)網(wǎng)絡(luò)補(bǔ)償?shù)降讕?lái)什么先說(shuō)結(jié)論效果最驚艷的不是階躍響應(yīng)PID本來(lái)就能跟蹤得不錯(cuò)而是在抗擾和參數(shù)突變這兩項(xiàng)。參數(shù)突變實(shí)驗(yàn)里不帶神經(jīng)網(wǎng)絡(luò)的PID重新爬升到穩(wěn)態(tài)需要約3秒期間俯仰角出現(xiàn)了約8°的偏差。帶RBF補(bǔ)償?shù)木W(wǎng)絡(luò)則在0.2秒內(nèi)就補(bǔ)償?shù)袅舜蟛糠制梅€(wěn)態(tài)誤差從2.1°降到了0.3°以內(nèi)。原因是神經(jīng)網(wǎng)絡(luò)通過(guò)在線權(quán)值更新快速辨識(shí)出了額外的重力力矩需要并在輸出端加了一個(gè)恒定的前饋補(bǔ)償量。這個(gè)補(bǔ)償量本質(zhì)上是“學(xué)會(huì)”了新的掛載重量不需要重新整定PID增益。重心偏移實(shí)驗(yàn)更有意思。給無(wú)人機(jī)的滾轉(zhuǎn)軸疊加強(qiáng)制擾動(dòng)力矩后PID控制器的反應(yīng)是“對(duì)抗”——它會(huì)維持一個(gè)恒定的靜差或者說(shuō)需要積分項(xiàng)慢慢吃掉偏差。RBF網(wǎng)絡(luò)則直接把重心偏移的等效力矩學(xué)了出來(lái)權(quán)值穩(wěn)定后控制器輸出里多了一個(gè)恒定的偏置項(xiàng)恰好等于重心偏移產(chǎn)生的力矩。這就是“補(bǔ)償”和“對(duì)抗”的本質(zhì)區(qū)別神經(jīng)網(wǎng)絡(luò)學(xué)會(huì)的是“原因”PID只能在“結(jié)果”層面糾偏。5.3 仿真過(guò)程中踩過(guò)的坑排在首位的坑是基函數(shù)中心范圍設(shè)置不當(dāng)。我第一次設(shè)中心范圍是[-1, 1]結(jié)果大角度機(jī)動(dòng)時(shí)輸入超出覆蓋范圍徑向基輸出近乎為零網(wǎng)絡(luò)直接“失明”了補(bǔ)償量消失PID獨(dú)自扛下所有。改成[-2, 2]之后問(wèn)題消失。這是RBF網(wǎng)絡(luò)特有的問(wèn)題網(wǎng)絡(luò)的表達(dá)能力只在中心覆蓋的區(qū)間內(nèi)有效輸入一旦超出覆蓋范圍輸出就截?cái)酁榱??;瘮?shù)覆蓋范圍必須大于最大誤差范圍沒(méi)有捷徑。第二個(gè)坑是學(xué)習(xí)率過(guò)大導(dǎo)致的權(quán)值振蕩。我把 gamma 設(shè)成0.3時(shí)前200步網(wǎng)絡(luò)權(quán)值劇烈震蕩補(bǔ)償力矩像噪聲一樣疊加在控制輸出上差點(diǎn)以為控制器發(fā)散。后來(lái)把學(xué)習(xí)率降到0.05并用滑模面s代替純誤差e做驅(qū)動(dòng)項(xiàng)震蕩立刻緩解。這里的原理不復(fù)雜學(xué)習(xí)率大權(quán)值對(duì)誤差的響應(yīng)快但如果誤差本身還在振蕩權(quán)值就會(huì)跟著振蕩形成正反饋惡性循環(huán)。第三個(gè)坑比較隱蔽Simulink代數(shù)環(huán)。S-Function的當(dāng)前輸出依賴于當(dāng)前輸入而輸入又由輸出決定時(shí)Simulink會(huì)報(bào)代數(shù)環(huán)錯(cuò)誤。我的解決辦法是在S-Function輸出后加一個(gè)單位延遲塊unit delay雖然理論分析時(shí)差了一個(gè)采樣周期但實(shí)際控制頻率500Hz下一個(gè)周期的延遲對(duì)系統(tǒng)穩(wěn)定性的影響可以忽略。這個(gè)坑在純代碼仿真里不存在只在Simulink里遇到。第四個(gè)坑關(guān)于代碼生成部署。仿真跑通后我曾想過(guò)把控制器遷移到Pixhawk真機(jī)上。但MATLAB Coder生成的C代碼默認(rèn)只用單精度浮點(diǎn)RBF高斯計(jì)算里的exp函數(shù)在Cortex-M4上開銷不小一個(gè)控制周期根本算不完。后來(lái)我用查表法替代實(shí)時(shí)的exp計(jì)算才勉強(qiáng)壓縮到1ms以內(nèi)。如果打算最終上真機(jī)建議從一開始就把計(jì)算量控制住比如固定基函數(shù)中心后預(yù)先計(jì)算好高斯函數(shù)查找表。6. 關(guān)于這個(gè)系統(tǒng)的設(shè)計(jì)和擴(kuò)展方向6.1 整體設(shè)計(jì)復(fù)盤回顧整個(gè)仿真項(xiàng)目值得肯定的是分層控制架構(gòu)和“PID保底 RBF補(bǔ)償”的組合方式。這種設(shè)計(jì)的好處不言而喻神經(jīng)網(wǎng)絡(luò)部分即使失效系統(tǒng)也不至于完全失控這在工程上是極其重要的保險(xiǎn)機(jī)制。整個(gè)系統(tǒng)的設(shè)計(jì)邏輯是先確定控制目標(biāo)然后建立被控對(duì)象的非線性模型再選擇能夠在線學(xué)習(xí)不確定項(xiàng)的網(wǎng)絡(luò)結(jié)構(gòu)最后用仿真驗(yàn)證各種工況下的表現(xiàn)。每一步都有清晰的動(dòng)機(jī)而不是拍腦袋堆砌算法。我最初的方案里也考慮過(guò)直接套用完全神經(jīng)網(wǎng)絡(luò)控制器——即讓網(wǎng)絡(luò)直接輸出全部控制力矩。第一版仿真就發(fā)現(xiàn)網(wǎng)絡(luò)初始權(quán)值為零時(shí)無(wú)人機(jī)根本飛不起來(lái)需要很長(zhǎng)的預(yù)訓(xùn)練時(shí)間。而“PID 自適應(yīng)補(bǔ)償”的方案初始階段PID保證基本飛行能力網(wǎng)絡(luò)可以在飛行過(guò)程中從零開始逐漸學(xué)習(xí)兩者配合默契幾乎沒(méi)有冷啟動(dòng)問(wèn)題。6.2 后續(xù)在飛控上的擴(kuò)展思路在整個(gè)項(xiàng)目的收尾階段我仔細(xì)思考了這套算法的擴(kuò)展空間。目前RBF網(wǎng)絡(luò)只能補(bǔ)償每個(gè)軸獨(dú)立的力矩偏差軸間耦合還沒(méi)有建模。復(fù)雜機(jī)動(dòng)時(shí)滾轉(zhuǎn)和俯仰之間的交叉耦合依然明顯下一步可以用多維輸入把p*q耦合項(xiàng)一起送入網(wǎng)絡(luò)學(xué)習(xí)理論上能進(jìn)一步減小動(dòng)態(tài)誤差。從控制角度現(xiàn)在神經(jīng)網(wǎng)絡(luò)補(bǔ)償?shù)氖恰翱刂屏亍睂用娴牟淮_定項(xiàng)還沒(méi)有觸及“參考模型”層面的自適應(yīng)。如果改用模型參考自適應(yīng)控制結(jié)構(gòu)讓網(wǎng)絡(luò)直接調(diào)整到期望閉環(huán)動(dòng)態(tài)的誤差那就能針對(duì)不同任務(wù)的敏捷性需求在線調(diào)整控制帶寬這是目前PID加固定補(bǔ)償方案做不到的。在部署方面如果要做真機(jī)驗(yàn)證把Simulink模型通過(guò)Embedded Coder生成C代碼、部署到Pixhawk飛行控制器是通用的路線。需要注意的是一個(gè)控制周期內(nèi)RBF網(wǎng)絡(luò)的5個(gè)徑向基函數(shù)求值再加上PID計(jì)算在STM32F4這類主控上的耗時(shí)已經(jīng)比較可觀要么降低控制頻率到250Hz要么減少基函數(shù)的數(shù)量。6.3 給想復(fù)現(xiàn)這個(gè)項(xiàng)目的人的建議根據(jù)我做這個(gè)仿真的全程經(jīng)驗(yàn)給準(zhǔn)備復(fù)現(xiàn)的讀者三點(diǎn)建議。第一先跑通純PID對(duì)照版本觀測(cè)記錄最基本的姿態(tài)響應(yīng)再疊加RBF模塊。直接上完整系統(tǒng)會(huì)分不清問(wèn)題出在控制器設(shè)計(jì)還是網(wǎng)絡(luò)調(diào)參。第二把所有參數(shù)寫到一個(gè)配置文件中參數(shù)掃描時(shí)批量跑比手動(dòng)改Simulink塊參數(shù)高效得多。仿真中我每次改一組參數(shù)就要另存一份模型文件管理起來(lái)非常混亂后來(lái)干脆用腳本統(tǒng)一修改m文件中的參數(shù)并調(diào)sim函數(shù)才從重復(fù)勞動(dòng)里解脫出來(lái)。第三記錄每一組實(shí)驗(yàn)的完整數(shù)據(jù)包括權(quán)值軌跡、控制力矩、姿態(tài)誤差曲線這些數(shù)據(jù)對(duì)寫論文和答辯非常重要。仿真完隨手導(dǎo)出成mat文件或csv比事后補(bǔ)做實(shí)驗(yàn)省時(shí)間得多。我至今還記得第一次看到權(quán)值軌跡穩(wěn)定收斂時(shí)的場(chǎng)景俯仰角被強(qiáng)風(fēng)拉偏6°BP補(bǔ)償力矩迅速頂上去姿態(tài)在不到一秒鐘內(nèi)回到水平而PID對(duì)照組還在0.5°誤差附近掙扎。那一瞬間你會(huì)直觀感受到自適應(yīng)控制的真正價(jià)值——它不是調(diào)出一個(gè)更好的參數(shù)而是讓系統(tǒng)有了自我糾正的能力。這種能力在純仿真中已經(jīng)足夠令人興奮如果有一天跑在真機(jī)上飛行器的適應(yīng)性和魯棒性又會(huì)上一個(gè)臺(tái)階。希望這篇文章能幫你繞過(guò)我踩過(guò)的坑在仿真的基礎(chǔ)上走得更遠(yuǎn)。本文還有配套的精品資源點(diǎn)擊獲取