姿態解算知識(三)-陀螺儀加速度計6軸資料融合
這麼久的慣導總算是沒白看,加上一篇部落格的指點,這兩天把Mahony的九軸資料融合演算法看懂了。可惜第二版硬體還沒到,磁力計用不了,沒法驗證效果~今天先總結下陀螺儀和加速度計的六軸資料融合。
原創文章,轉載請說明出處:sheng-blog.cn
原文出處
加計和陀螺儀都能計算出姿態,但為何要對它們融合呢,是因為加速度計對振動之類的擾動很敏感,但長期資料計算出的姿態可信,而陀螺儀雖然對振動這些不敏感,但長期使用陀螺儀會出現漂移,因此我們要進行互補,短期相信陀螺,長期相信加計。不過,其實加計無法對航向角進行修正,修正航向角需要磁力計,也就是下次要總結的9軸資料融合。
在融合之前先要對感測器原始資料進行一些處理。理想情況下,加速度計水平放置時,XY軸應該是0輸出的,僅Z軸輸出1個G,因此,我們需要對加速度計進行XY軸的零點校準(注意Z軸可不能一起校準去了~);同樣的,陀螺儀在水平靜止放置時各軸輸出應為0,因此需對陀螺儀進行三軸的校準。方法就是把機體標準水平靜止放置時採集它個一兩百次資料求個平均作為校準值儲存起來嘍,然後工作狀態下各軸輸出的資料就是採集來的資料減去校準值嘍。僅此還不夠,陀螺儀不進行濾波還可以接受,但加速度計噪聲比較大,所以至少也得來個滑動視窗濾波,我用了20深度的滑動視窗,資料還是有很大波動,不過最後計算出的姿態角只有0.3度左右的抖動(我看大家一般都是建議8深度就夠了,所以單滑動視窗濾波效果是沒法做到更好了,可以考慮加個卡爾曼濾波?還沒研究,不過這樣處理器運算量就上去了)。(11.28補充:後面改對加計使用8深度滑動濾波,陀螺儀進行16階凱撒窗濾波後只有0.1不到的波動,不過凱撒濾波引數的整定還不會,用的別人整定的一組引數,近期繼續研究)。濾波效果如圖:
接下來上六軸資料融合程式碼:(程式碼來源網路,我在前人的基礎上再加些註釋,稍作改動)
#defineKp 10.0f // 這裡的KpKi是用於調整加速度計修正陀螺儀的速度
#defineKi 0.008f
#definehalfT 0.001f // 取樣週期的一半,用於求解四元數微分方程時計算角增量
floatq0 = 1, q1 = 0, q2 = 0, q3 = 0; // 初始姿態四元數,由上篇博文提到的變換四元數公式得來
floatexInt = 0, eyInt = 0, ezInt = 0 ; //當前加計測得的重力加速度在三軸上的分量
//與用當前姿態計算得來的重力在三軸上的分量的誤差的積分
voidIMUupdate(float gx, float gy, float gz, float ax, float ay, float az)//g表陀螺儀,a表加計
{
float q0temp,q1temp,q2temp,q3temp;//四元數暫存變數,求解微分方程時要用
float norm; //向量的模或四元數的範數
float vx, vy, vz;//當前姿態計算得來的重力在三軸上的分量
float ex, ey, ez;//當前加計測得的重力加速度在三軸上的分量
//與用當前姿態計算得來的重力在三軸上的分量的誤差
// 先把這些用得到的值算好
float q0q0 = q0*q0;
float q0q1 = q0*q1;
float q0q2 = q0*q2;
float q1q1 = q1*q1;
float q1q3 = q1*q3;
float q2q2 = q2*q2;
float q2q3 = q2*q3;
float q3q3 = q3*q3;
if(ax*ay*az==0)//加計處於自由落體狀態時不進行姿態解算,因為會產生分母無窮大的情況
return;
norm = sqrt(ax*ax + ay*ay + az*az);//單位化加速度計,
ax = ax /norm;// 這樣變更了量程也不需要修改KP引數,因為這裡歸一化了
ay = ay / norm;
az = az / norm;
//用當前姿態計算出重力在三個軸上的分量,
//參考座標n系轉化到載體座標b系的用四元數表示的方向餘弦矩陣第三列即是(博文一中有提到)
vx = 2*(q1q3 - q0q2);
vy = 2*(q0q1 + q2q3);
vz = q0q0 - q1q1 - q2q2 + q3q3 ;
//計算測得的重力與計算得重力間的誤差,向量外積可以表示這一誤差
//原因我理解是因為兩個向量是單位向量且sin0等於0
//不過要是夾角是180度呢~這個還沒理解
ex = (ay*vz - az*vy) ;
ey = (az*vx - ax*vz) ;
ez = (ax*vy - ay*vx) ;
exInt = exInt + ex * Ki; //對誤差進行積分
eyInt = eyInt + ey * Ki;
ezInt = ezInt + ez * Ki;
// adjusted gyroscope measurements
gx = gx + Kp*ex + exInt; //將誤差PI後補償到陀螺儀,即補償零點漂移
gy = gy + Kp*ey + eyInt;
gz = gz + Kp*ez + ezInt; //這裡的gz由於沒有觀測者進行矯正會產生漂移,表現出來的就是積分自增或自減
//下面進行姿態的更新,也就是四元數微分方程的求解
q0temp=q0;//暫存當前值用於計算
q1temp=q1;//網上傳的這份演算法大多沒有注意這個問題,在此更正
q2temp=q2;
q3temp=q3;
//採用一階畢卡解法,相關知識可參見《慣性器件與慣性導航系統》P212
q0 = q0temp + (-q1temp*gx - q2temp*gy -q3temp*gz)*halfT;
q1 = q1temp + (q0temp*gx + q2temp*gz -q3temp*gy)*halfT;
q2 = q2temp + (q0temp*gy - q1temp*gz +q3temp*gx)*halfT;
q3 = q3temp + (q0temp*gz + q1temp*gy -q2temp*gx)*halfT;
//單位化四元數在空間旋轉時不會拉伸,僅有旋轉角度,這類似線性代數裡的正交變換
norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
q0 = q0 / norm;
q1 = q1 / norm;
q2 = q2 / norm;
q3 = q3 / norm;
//四元數到尤拉角的轉換,公式推導見博文一
//其中YAW航向角由於加速度計對其沒有修正作用,因此此處直接用陀螺儀積分代替
Q_ANGLE.Z = GYRO_I.Z; // yaw
Q_ANGLE.Y = asin(-2 * q1 * q3 + 2 * q0* q2)*57.3; // pitch
Q_ANGLE.X = atan2(2 * q2 * q3 + 2 * q0 * q1,-2 * q1 * q1 - 2 * q2* q2 + 1)* 57.3; // roll
}
上述程式碼圖解:
新浪部落格插程式碼好不方便,格式全亂了。最後忘了說了,千萬別忘了傳入的陀螺儀資料需乘一個係數將其轉化為弧度制角速度!!!
補充,梯度下降法六軸融合圖解: