繼之前研究了一些飛行姿態理論方面的問題後,又找到了之前很流行的一段外國大神寫的**,來分析分析。 第二篇文章的最後,講到了文章中的演算法在實際使用中有重大缺陷。
大家都知道,分析演算法理論的時候很多情況下我們沒有考慮太多外界干擾的情況,原因是很多情況下,感測器的精度以及受到的干擾並不會特別大,而顯著的影響到演算法。但是在imu系統中,有點不同。由於地磁場十分微弱,而我們生活中有大量使用電子裝置,使得磁場非常的混亂,以至於地磁感測器非常容易受到干擾。
由於以上演算法把地磁感測器一同加入到姿態的測定中,並基本給予了地磁感測器與加速度感測器同樣的加權,導致地磁感測器一旦被干擾,會對姿態產生地球重力突然被干擾一樣的結果。。。對姿態的測量是毀滅性的。
綜上,考慮到磁場的不穩定性,必須對地磁感測器進行降權處理,使得他對姿態的影響變小。
於是設計了以下的演算法。
將磁場感測器的資料在姿態角度中剔除,更新姿態的俯仰角(pitch)以及橫滾角(roll)的時候只使用加速度感測器以及陀螺儀(角速度感測器)。
只在計算偏航角的(yaw)的時候使用磁場感測器。也就是只使用磁場感測器作為乙個電子指南針,定位整個姿態在水平面旋轉的角度。這樣設計,讓磁場感測器只影響姿態中的乙個數值,減少了磁場的權重,即使磁場收到干擾,也不會導致姿態驟變,使得四軸墜機。
在對yaw進行計算的時候使用了如下函式。
eulerangleraw.yaw = 0.9 * (eulerangleraw.yaw - gzf*2*halft) + 0.1 * anglemagyaw;
此處的0.9和0.1是可以變動的但他們相加應該為1,此處為乙個最簡單的1階低通濾波器,增加0.1則是增大截止頻率。
演算法的流程圖是這樣的:
程式流程圖
新的姿態更新演算法是這樣的
voidahrsupdate(float gxf, float gyf, float gzf, float axf, float ayf, float azf, float mxf, float myf, float mzf)
double norm;
float vx, vy, vz;
float ex, ey, ez;
float halft; //取樣週期的一半
// 輔助變數,以減少重複運算元
float q0q0 = q0*q0;
float q0q1 = q0*q1;
float q0q2 = q0*q2;
float q0q3 = q0*q3;
float q1q1 = q1*q1;
float q1q2 = q1*q2;
float q1q3 = q1*q3;
float q2q2 = q2*q2;
float q2q3 = q2*q3;
float q3q3 = q3*q3;
// 測量歸一化
norm = invsqrt(axf*axf + ayf*ayf + azf*azf);
axf = axf * norm; //向量a 為感測器重力 飛行器分量
ayf = ayf * norm;
azf = azf * norm;
//norm = invsqrt(mxf*mxf + myf*myf + mzf*mzf);
// 向量m 為感測器磁場 飛行器分量
//mxf = mxf * norm;
//myf = myf * norm;
//mzf = mzf * norm;
// 計算參考磁通方向
//hx = 2*mxf*(0.5 - q2q2 - q3q3) + 2*myf*(q1q2 - q0q3) + 2*mzf*(q1q3 + q0q2); //向量h 為磁場通過旋轉以後 參考係分量
//hy = 2*mxf*(q1q2 + q0q3) + 2*myf*(0.5 - q1q1 - q3q3) + 2*mzf*(q2q3 - q0q1);
//hz = 2*mxf*(q1q3 - q0q2) + 2*myf*(q2q3 + q0q1) + 2*mzf*(0.5 - q1q1 - q2q2);
//bx = 1.0f/invsqrt((hx*hx) + (hy*hy));
//原則上應該只有x向的分量 ex的磁場感測器部分誤差就是由此式產生。
//bz = hz;
//估計方向的重力和磁通(v和w)
//反向使用 四元數 及把a用-a替換。
vx = 2*(q1q3 - q0q2);
//v為把重力反向旋轉到飛行器參考係時重力的向量
vy = 2*(q0q1 + q2q3);
vz = q0q0 - q1q1 - q2q2 + q3q3;
//wx = 2*bx*(0.5 - q2q2 - q3q3) + 2*bz*(q1q3 - q0q2);
// w為把磁場反向旋轉到飛行器參考係時磁場的向量
//wy = 2*bx*(q1q2 - q0q3) + 2*bz*(q0q1 + q2q3);
//wz = 2*bx*(q0q2 + q1q3) + 2*bz*(0.5 - q1q1 - q2q2);
// 錯誤是跨產品的總和之間的參考方向的領域和方向測量感測器 //建立誤差函式 向量的外積
//ex = (ayf*vz - azf*vy) + (myf*wz - mzf*wy);
//ey = (azf*vx - axf*vz) + (mzf*wx - mxf*wz);
//ez = (axf*vy - ayf*vx) + (mxf*wy - myf*wx);
ex = (ayf*vz - azf*vy);
ey = (azf*vx - axf*vz);
ez = (axf*vy - ayf*vx);
halft=getcurrenttime(timer4);
if (halft>0.05)halft=0;
//printf("%f\n\r",halft);
if(ex != 0.0f && ey != 0.0f && ez != 0.0f)
// 積分誤差比例積分增益
exint = exint + ex*ki*(halft);
eyint = eyint + ey*ki*(halft);
ezint = ezint + ez*ki*(halft);
// 調整後的陀螺儀測量
gxf = gxf + kp*ex + exint;
gyf = gyf + kp*ey + eyint;
gzf = gzf + kp*ez + ezint;
// halft=getcurrenttime();
// printf("%f \n\r", halft);
// 整合四元數率和歸一化
//龍格-庫格法
q0 = q0 + (-q1*gxf - q2*gyf - q3*gzf)*halft;
q1 = q1 + (q0*gxf + q2*gzf - q3*gyf)*halft;
q2 = q2 + (q0*gyf - q1*gzf + q3*gxf)*halft;
q3 = q3 + (q0*gzf + q1*gyf - q2*gxf)*halft;
// 歸一化四元數
norm = invsqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
q0 = q0 * norm;
q1 = q1 * norm;
q2 = q2 * norm;
q3 = q3 * norm;
與第二篇相比,演算法中注釋掉了所有與磁場有關的部分。
姿態更新後,用如下語句與磁場感測器計算出來的yaw(偏航角)進行混合
eulerangleraw.yaw = 0.9 * (eulerangleraw.yaw - gzf*2*halft) + 0.1 * anglemagyaw;
經過檢驗,該演算法姿態穩定,準確,變化迅速,yaw的值也能長期保證穩定,能為四軸飛行器提供很好的姿態資料。
發布於 2015-12-10
LPMS IMU姿態解算
參考文章 ahrs姿態解算說明 加速度 陀螺儀 磁力計原理及原始資料分析 ahrs俗稱航姿參考系統,ahrs由加速度計,磁場計,陀螺儀構成,ahrs的真正參考來自於地球的重力場和地球的磁場 他的靜態終精度取決於對磁場的測量精度和對重力的測量精度 而則陀螺決定了他的動態效能。如何用加速度計和陀螺儀的資...
姿態解算解析
用四元素法進行姿態解算,其步驟如下 1.四元素初始化 第一次解算時計算 靜止狀態下由加速度,磁力計值求取初始 gamma theta psi gamma frac theta frac psi frac 初始化四元素 left begin end right left begin cos frac ...
四軸飛行器姿態解算預備知識
其實我覺得要說四軸的姿態,我們必須說幾樣東西。1 座標系 2 方向余弦矩陣 3 尤拉角 4 四元數 對上面這四樣東西有了初步的理解,就可以開始看imu的飛控解算程式了。其實我剛剛接觸四軸的時候我沒明白為什麼四軸裡面一會來個地理座標系,一會來個機體座標系。搞這麼多座標系幹什麼用的。後來在秦永元的書裡面...