1. 程式人生 > >Pixhawk之姿態解算篇(2)_mahony演算法分析

Pixhawk之姿態解算篇(2)_mahony演算法分析

一、開篇

  還是沒能進入到原始碼部分研究,對姿態解算過程太過於模糊,所以主要開始研究一下關於姿態解算的過程和實現,本篇博文主要是以mahony的演算法為基礎理解姿態解算的過程,主要參考的論文就是William Premerlani and Paul Bizard的關於DCM的一篇經典論文《Direction Cosine Matrix IMU_Theory》,一定要搞透這篇論文,沒看過它都不敢稱自己研究過飛控演算法;然後接下來還有madgwick和mahony的論文需要研究,看英文的比較費時間,但是還是得慢慢的啃啊~~~

        然後就是結合國內的一本很不錯的書籍《捷聯慣性導航技術》,不需要細看,只需要瞭解其中關於姿態解算部分的即可。國內的課本嘛,大家都懂的,恨不得手把手的教你了。國外的論文就不一樣了,繼續啃吧。

三、實驗平臺

Software Version:ArduCopter(Ver_3.3)

Hardware Version:pixhawk

IDE:eclipse Juno (Windows)

四、基本知識

1、 陀螺儀和加速計(特性分析)

1)陀螺儀

         Gyro sensitivity、 operating range、offset、drift、calibrationandsaturation must be taken into account in the implementation of DCM。

靈敏度

        測量角速度,具有高動態特性,它是一個間接測量角度的器件其中一個關鍵引數就是gyro sensitivity(其單位是millivolts per degree persecond,把轉速轉換到電壓值),測量範圍越小氣靈敏度越好。也就是說測量的是角度的導數,即角速度,要將角速度對時間積分才能得到角度。陀螺儀就是內部有一個陀螺,它的軸由於陀螺效應始終與初始方向平行,這樣就可以通過與初始方向的偏差計算出旋轉方向和角度。

偏移

        偏移就是在陀螺沒有轉動的時候卻又輸出,這個輸出量的大小和供電電壓以及溫度有關,該偏移可以在陀螺儀上電時通過一小段時間的測量來修正。

漂移
        它是由於在時間的積累下偏移和噪聲相互影響的結果,例如有一個偏置(offset)0.1dps加在上面,於是測量出來是0.1dps,積分一秒之後,得到的角度是0.1度,1分鐘之後是6度,還能忍受,一小時之後是360度,轉了一圈,也就是說,陀螺儀在短時間內有很大的參考價值。
白噪聲
        電訊號的測量中,一定會帶有白噪聲,陀螺儀資料的測量也不例外。所以獲得的陀螺儀資料中也會帶有白噪聲,而且這種白噪聲會隨著積分而累加。
積分誤差


        對陀螺儀角速度的積分是離散的,長時間的積分會出現漂移的情況。所以要考慮積分誤差的問題。

溢位

        就是轉速超過了其測量的最大轉速範圍。關於這個問題的解決辦法,在DCM IMU:Theory中給出來三種解決辦法,不寫了。

2)加速度計
         加速度計的低頻特性好,可以測量低速的靜態加速度。在無人機上就是對重力加速度g的測量和分析。當把加速度計拿在手上隨意轉動時,看的是重力加速度在三個軸上的分量值。加速度計在自由落體時,其輸出為0。為什麼會這樣呢?這裡涉及到加速度計的設計原理:加速度計測量加速度是通過比力來測量(比力方程,秦永元的書中有介紹),而不是通過加速度。加速度計僅僅測量的是重力加速度,而重力加速度與剛才所說的R座標系(EarthFrame)是固連的,通過這種關係,可以得到加速度計所在平面與地面的角度關係。

        加速度計僅僅測量的是重力加速度,3軸加速度計輸出重力加速度在加速度計所在機體座標系3個軸上的分量大小。重力加速度的方向和大小是固定的。通過這種關係,可以得到加速度計所在平面與地面的角度關係。加速度計若是繞著重力加速度的軸轉動,則測量值不會改變,也就是說加速度計無法感知這種水平旋轉。

Accelerometersare used for roll-pitch drift correction because they have zero drift         有關陀螺儀和加速度計和關係,姿態解算融合的原理,再把下面這個比喻放到這裡一遍。
        機體好似一條船,姿態就是航向(船頭的方位),重力是燈塔,陀螺(角速度積分)是舵手,加速度計是瞭望手。舵手負責估計和把穩航向,他相信自己,本來船向北開的,就一定會一直往北開,覺得轉了90度彎,那就會往東開。當然如果舵手很牛逼,也許能估計很準確,維持很長時間。不過只信任舵手,肯定會迷路,所以一般都有瞭望手來觀察誤差。
        瞭望手根據地圖燈塔方位和船的當前航向,算出燈塔理論上應該在船的X方位。然而看到實際燈塔在船的Y方位,那肯定船的當前航向有偏差了,偏差就是ERR=X-Y。舵手收到瞭望手給的ERR報告,覺得可靠,那就聽個90%ERR,覺得天氣不好、地圖誤差大,那就聽個10%ERR,根據這個來糾正估算航向。

3)磁感測器

        可以測量磁場,在沒有其他磁場的情況下,僅僅測量的是地球的磁場,而地磁也是和R座標系固連的,通過這種關係,可以得到平面A和地平面的關係。(平面A:和磁場方向垂直的平面),同樣的,若是沿著磁場方向的軸旋轉,測量值不會改變,無法感知這種旋轉。

        綜合考慮,加速度計和磁感測器都是極易受外部干擾的感測器,都只能得到2維的角度關係,但是測量值隨時間的變化相對較小,結合加速度計和磁感測器可以得到3維的角度關係。陀螺儀可以積分得到三維的角度關係,動態效能好,受外部干擾小,但測量值隨時間變化比較大。可以看出,它們優缺點互補,結合起來才能有好的效果。

4)關於資料融合

        現在有了三個感測器,都能在一定程度上測量角度關係,但是究竟相信誰?根據剛才的分析,應該是在短時間內更加相信陀螺儀,隔三差五的問問加速度計和磁感測器,角度飄了多少了?有一點必須非常明確,陀螺儀才是主角,加速度計和磁感測器僅僅是跑龍套的。其實加速度計無法對航向角進行修正,修正航向角需要磁力計。

五、正文

1、首先就是基於mahony演算法的AHRS姿態解算的一套原始碼,理論基礎是DCM IMU:Theory,很有參考價值。先自己分析一下,看看每一行具體是做什麼的,是如何實現姿態解算和修正的。然後會給出相應的分析

   /*
    *AHRS
   */
   // AHRS.c
   // Quaternion implementation of the 'DCM filter' [Mayhony et al]. Incorporates the magnetic distortion
   // compensation algorithms from my filter [Madgwick] which eliminatesthe need for a reference
   // direction of flux (bx bz) to be predefined and limits the effect ofmagnetic distortions to yaw
   // axis only.
   // User must define 'halfT' as the (sample period / 2), and the filtergains 'Kp' and 'Ki'.
   // Global variables 'q0', 'q1', 'q2', 'q3' are the quaternion elementsrepresenting the estimated
   // orientation.  See my report foran overview of the use of quaternions in this application.
   // User must call 'AHRSupdate()' every sample period and parsecalibrated gyroscope ('gx', 'gy', 'gz'),
   // accelerometer ('ax', 'ay', 'ay') and magnetometer ('mx', 'my', 'mz')data.  Gyroscope units are
   // radians/second, accelerometer and magnetometer units are irrelevantas the vector is normalised.                                
   #include "stm32f10x.h"
   #include "AHRS.h"
   #include "Positioning.h"
   #include <math.h>
   #include <stdio.h>
/* Private define------------------------------------------------------------*/
   #define Kp 2.0f                       // proportional gain governs rate of convergence toaccelerometer/magnetometer
    #define Ki 0.005f          // integral gain governs rate of convergenceof gyroscope biases
    #define halfT 0.0025f      // half the sample period  
   #define ACCEL_1G 1000    //theacceleration of gravity is: 1000 mg
/* Private variables---------------------------------------------------------*/
   static float q0 = 1, q1 = 0, q2 = 0, q3 = 0;        // quaternion elements representing theestimated orientation
   static float exInt = 0, eyInt = 0, ezInt = 0;        // scaled integral error
/* Public variables----------------------------------------------------------*/
   EulerAngle_Type EulerAngle;       //unit: radian
    u8InitEulerAngle_Finished = 0;
   float Magnetoresistor_mGauss_X = 0, Magnetoresistor_mGauss_Y = 0,Magnetoresistor_mGauss_Z = 0;//unit: milli-Gauss                                                                                                                                                                                                      
   float Accelerate_mg_X, Accelerate_mg_Y, Accelerate_mg_Z;//unit: mg                                                              
   float AngularRate_dps_X, AngularRate_dps_Y, AngularRate_dps_Z;//unit:dps: degree per second       
   int16_t Magnetoresistor_X, Magnetoresistor_Y, Magnetoresistor_Z;                                                                                                                                                                                                      
   uint16_t Accelerate_X = 0, Accelerate_Y = 0, Accelerate_Z = 0;                                                                                                                                                                                              
   uint16_t AngularRate_X = 0, AngularRate_Y = 0, AngularRate_Z = 0;
   u8 Quaternion_Calibration_ok = 0;
   /* Private macro-------------------------------------------------------------*/
   /* Private typedef-----------------------------------------------------------*/
   /* Private function prototypes -----------------------------------------------*/
/******************************************************************************
    *Function Name  : AHRSupdate
    *Description    : None
    *Input          : None
    *Output         : None
    *Return         : None
*******************************************************************************
   void AHRSupdate(float gx, float gy, float gz, float ax, float ay, floataz, float mx, float my, float mz) {
           float norm;
           float hx, hy, hz, bx, bz;
           float vx, vy, vz, wx, wy, wz; 
           float ex, ey, ez;
 
           // auxiliary variables to reduce number of repeated operations
           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;
          
           // normalise the measurements
           norm = sqrt(ax*ax + ay*ay + az*az);
           ax = ax / norm;
           ay = ay / norm;
           az = az / norm;
           norm = sqrt(mx*mx + my*my + mz*mz);
           mx = mx / norm;
            my = my / norm;
           mz = mz / norm;
          
           // compute reference direction of magnetic field
           hx = 2*mx*(0.5 - q2q2 - q3q3) + 2*my*(q1q2 - q0q3) + 2*mz*(q1q3 + q0q2);
           hy = 2*mx*(q1q2 + q0q3) + 2*my*(0.5 - q1q1 - q3q3) + 2*mz*(q2q3 - q0q1);
           hz = 2*mx*(q1q3 - q0q2) + 2*my*(q2q3 + q0q1) + 2*mz*(0.5 - q1q1 -q2q2);        
           bx = sqrt((hx*hx) + (hy*hy));
           bz = hz;
          
// estimated direction of gravity and magnetic field (v and w)
           vx = 2*(q1q3 - q0q2);
           vy = 2*(q0q1 + q2q3);
           vz = q0q0 - q1q1 - q2q2 + q3q3;
           wx = 2*bx*(0.5 - q2q2 - q3q3) + 2*bz*(q1q3 - q0q2);
           wy = 2*bx*(q1q2 - q0q3) + 2*bz*(q0q1 + q2q3);
           wz = 2*bx*(q0q2 + q1q3) + 2*bz*(0.5 - q1q1 - q2q2); 
          
// error is sum ofcross product between reference direction of fields and directionmeasured by sensors 
           ex = (ay*vz - az*vy) + (my*wz - mz*wy);
           ey = (az*vx - ax*vz) + (mz*wx - mx*wz);
           ez = (ax*vy - ay*vx) + (mx*wy - my*wx);
          
           // integral error scaled integral gain
           exInt = exInt + ex*Ki* (1.0f / sampleFreq);
           eyInt = eyInt + ey*Ki* (1.0f / sampleFreq);
           ezInt = ezInt + ez*Ki* (1.0f / sampleFreq);
           // adjusted gyroscope measurements
           gx = gx + Kp*ex + exInt;
           gy = gy + Kp*ey + eyInt;
           gz = gz + Kp*ez + ezInt;
          
           // integrate quaternion rate and normalize
           q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
           q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
           q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
           q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT; 
          
           // normalise quaternion
           norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
           q0 = q0 / norm;
           q1 = q1 / norm;
           q2 = q2 / norm;
           q3 = q3 / norm;
}
2、上述演算法的原始碼分析
        先給一個簡要的程式碼註釋分析。
//陀螺儀、加速度計、磁力計資料融合
    void AHRSupdate(float gx, float gy, float gz, float ax, float ay, float az, float mx, float my, float mz) {
            float norm;
            float hx, hy, hz, bx, bz;
            float vx, vy, vz, wx, wy, wz; //v*當前姿態計算得來的重力在三軸上的分量
            float ex, ey, ez;

            // auxiliary variables to reduce number of repeated operations
            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;
           
            // normalise the measurements
            norm = sqrt(ax*ax + ay*ay + az*az); 
            ax = ax / norm;
            ay = ay / norm;
            az = az / norm;
            norm = sqrt(mx*mx + my*my + mz*mz); 
            mx = mx / norm;
            my = my / norm;
            mz = mz / norm;
           
            // compute reference direction of magnetic field
            hx = 2*mx*(0.5 - q2q2 - q3q3) + 2*my*(q1q2 - q0q3) + 2*mz*(q1q3 + q0q2);
            hy = 2*mx*(q1q2 + q0q3) + 2*my*(0.5 - q1q1 - q3q3) + 2*mz*(q2q3 - q0q1);
            hz = 2*mx*(q1q3 - q0q2) + 2*my*(q2q3 + q0q1) + 2*mz*(0.5 - q1q1 - q2q2);         
            bx = sqrt((hx*hx) + (hy*hy));
            bz = hz; 
           
// estimated direction of gravity and magnetic field (v and w) 
//參考座標n系轉化到載體座標b系的用四元數表示的方向餘弦矩陣第三列即是。
        //處理後的重力分量
            vx = 2*(q1q3 - q0q2);
            vy = 2*(q0q1 + q2q3);
            vz = q0q0 - q1q1 - q2q2 + q3q3;
//處理後的mag,反向使用DCM得到
            wx = 2*bx*(0.5 - q2q2 - q3q3) + 2*bz*(q1q3 - q0q2);
            wy = 2*bx*(q1q2 - q0q3) + 2*bz*(q0q1 + q2q3);
            wz = 2*bx*(q0q2 + q1q3) + 2*bz*(0.5 - q1q1 - q2q2);  
           
// error is sum of cross product between reference direction of fields and direction measured by sensors 體現在加速計補償和磁力計補償,因為僅僅依靠加速計補償沒法修正Z軸的變差,所以還需要通過磁力計來修正Z軸。(公式28)。《四元數解算姿態完全解析及資料彙總》的作者把這部分理解錯了,不是什麼叉積的差,而叉積的計算就是這樣的。計算方法是公式10。
            ex = (ay*vz - az*vy) + (my*wz - mz*wy);
            ey = (az*vx - ax*vz) + (mz*wx - mx*wz);
            ez = (ax*vy - ay*vx) + (mx*wy - my*wx);
           
            // integral error scaled integral gain 
            exInt = exInt + ex*Ki* (1.0f / sampleFreq);
            eyInt = eyInt + ey*Ki* (1.0f / sampleFreq);
            ezInt = ezInt + ez*Ki* (1.0f / sampleFreq);
            // adjusted gyroscope measurements
//將誤差PI後補償到陀螺儀,即補償零點漂移。通過調節Kp、Ki兩個引數,可以控制加速度計修正陀螺儀積分姿態的速度。(公式16和公式29)
            gx = gx + Kp*ex + exInt;
            gy = gy + Kp*ey + eyInt;
            gz = gz + Kp*ez + ezInt;
           
            // integrate quaternion rate and normalize
 //一階龍格庫塔法更新四元數
            q0 = q0 + (-q1*gx - q2*gy - q3*gz)*halfT;
            q1 = q1 + (q0*gx + q2*gz - q3*gy)*halfT;
            q2 = q2 + (q0*gy - q1*gz + q3*gx)*halfT;
            q3 = q3 + (q0*gz + q1*gy - q2*gx)*halfT;  
           
            // normalise quaternion
            norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
            q0 = q0 / norm;
            q1 = q1 / norm;
            q2 = q2 / norm;
            q3 = q3 / norm;
}
3、在深入一點

        1)無人機控制中,主要就是姿態解算和姿態控制部分,該部分主要介紹姿態解算,下面是來一張比較好理解的框圖。

        由上面兩幅圖很容易理解整個控制和姿態解算了吧,在第四部分也介紹了關於陀螺儀、加速計、磁力計它們的作用,所以不再單獨介紹了。不理解的往上翻翻再看看吧。

        2)在姿態解算過程中,到底用什麼表示無人機的姿態呢?姿態表示的方法有很多種,比如尤拉角、四元數、DCM,各有的各的優勢,比較常用的就是四元數,方便計算。上面的姿態解算演算法也是基於四元數的。下面介紹一個它們三個的優缺點。

姿態解算方法的比較:

演算法

優點

缺點

PS

尤拉角法(3引數)

1、  通過尤拉角微分方程直接解算出pitch、roll、yaw

2、  概念直觀,易於理解

3、  解算結果永遠是正交的,無需再次正交化處理

1、  方程中有三角函式的運算,接超越函式有一定的困難

2、  當俯仰角接近90°時出現退化現象

1、  適應於水平姿態角變化不大的情況

2、  不適用於全姿態運載體

方向餘弦法(9引數)

1、  對姿態矩陣微分方程的求解,避免了尤拉角法中出現的退化現象

2、  可以全姿態執行

1、引數量過多,計算量大,實時性不好

很少在工程中使用

四元數法(4引數)

1、  直接求解四元數微分方程

2、  只需要求解四個引數,計算量小

3、演算法簡單,易於操作

漂移比較嚴重

可以在實現過程中修正漂移,應用比較廣泛

 3)廢話不多說,進入正題。上述演算法主要就是利用加速度計和磁力計修正陀螺儀的誤差,演算法是使用了PI反饋控制器實現反饋修正的。如下圖:


        首先,東北天座標系是n系(地理座標系,參考座標系),載體座標系是b系,就是我們飛行器的座標系。對於四元數法的姿態解算,需要求取的就是四元數的值;方向餘弦矩陣(用於表示n系和b系的相對關係)中的元素本來應該是三角函式,這裡由於使用四元數法,所以矩陣中的元素就成了四元數。所以姿態解算的任務就是求解由四元數構成的方向餘弦矩陣nCb(nCb表示從b繫到n的轉換矩陣,同理,bCn表示從n繫到b的轉換矩陣,它們的關係是轉置)。

        顯然,上述矩陣是有誤差存在的。對於一個確定的向量n,用不同的座標系表示時,他們所表示的大小和方向一定是相同的。但是由於這兩個座標系的轉換矩陣存在誤差,那麼當一個向量經過這麼一個有誤差存在的旋轉矩陣變換後,在另一個座標系中肯定和理論值是有偏差的,我們通過這個偏差來修正這個旋轉矩陣。這個旋轉矩陣的元素是四元數,這就是說修正的就是四元數,於是乎姿態就這樣被修正了,這才是姿態解算的原理。姿態解算求的是四元數,是通過修正旋轉矩陣中的四元數來達到姿態解算的目的,而不要以為通過加速度計和地磁計來修正姿態,加速度計和地磁計只是測量工具和載體,通過這兩個器件表徵旋轉矩陣的誤差存在,然後通過演算法修正誤差,修正四元數,修正姿態。

加速度計修正pitch_roll

        加速度計可以修正pitch_roll,但是我們必須要考慮離心加速度(centrifugalacceleration),離心加速度就等於旋轉率向量(即gyro vector)和速度向量的叉積(沒有原因,平均得來的並且還相當準確,速度可以用GPS獲取)。我們假設飛機方向和X軸平行。

        在機體上測得的重力的為:

Pitch_roll的旋轉修正向量是由DCM的Z行與歸一化以後的重力參考向量的叉積。


        在n系中,加速度計輸出為,經過bCn(用四元數表示的轉換矩陣)轉換之後到b系中的值為;在b系中,加速度計的測量值為,現在和均表示在b系中的豎直向下的向量,由此,我們來做向量積(叉積),得到誤差,利用這個誤差來修正bCn矩陣,於是四元數就在這樣一個過程中被修正了。但是,由於加速度計無法感知z軸上的旋轉運動,所以還需要用地磁計來進一步補償。


        PS:公式不好加,只能直接切圖了~~~

        加速度計在靜止時測量的是重力加速度,是有大小和方向的;同理,地磁計同樣測量的是地球磁場的大小和方向,只不過這個方向不再是豎直向下,而是與x軸(或者y軸)呈一個角度,與z軸呈一個角度。記作,假設x軸對準北邊,所以by=0,即。倘若知道bx和bz的精確值,那麼就可以採用和加速度計一樣的修正方法來修正。只不過在加速度計中,在n系中的參考向量是,變成了地磁計的。如果我們知道bx和bz的精確值,那麼就可以擺脫掉加速度計的補償,直接用地磁計和陀螺儀進行姿態解算,但是你看過誰只用陀螺儀和地磁計進行姿態解算嗎?沒有,因為沒人會去測量當地的地磁場相對於東北天座標的夾角,也就是bx和bz(插曲:關於這個bx和bz的理解:可以對比重力加速度的理解,就像vx vy vz似的,因為在每一處的歸一化以後的重力加速度都是0 0 1然後旋轉到機體座標系,而地球每一處的地磁大小都不一樣的,不能像重力加速度那樣直接旋轉得到了,只能用磁力計測量到的資料去強制擬合。)那麼現在怎麼辦?前面已經講了,姿態解算就是求解旋轉矩陣,這個矩陣的作用就是將b系和n正確的轉化直到重合。現在我們假設nCb旋轉矩陣是經過加速度計校正後的矩陣,當某個確定的向量(b系中)經過這個矩陣旋轉之後(到n系),這兩個座標系在XOY平面上重合(參考DCM IMU:Theory的Drift cancellation部分),只是在z軸旋轉上會存在一個偏航角的誤差。下圖表示的是經過nCb旋轉之後的b系和n系的相對關係。可以明顯發現加速度計可以把b系通過四元數法從任意角度拉到與n系水平的位置上,此時只剩下一個偏航角誤差。這也是為什麼加速度計無法修正偏航的原因。


        為什麼在word中使用公式編譯器編輯的公式沒辦法複製到CSDN中呢????????????

        此方式在數學上沒有任何問題,但是由於地磁感測器極易受到各種干擾,而此演算法又將地磁感測器所指示的方向過度的融入到了姿態當中,導致實際使用中資料會非常不穩定。怪不得crazypony的演算法中沒有使用磁力計修正YAW,這應該就是原因所在吧。

六、來一點ardupilot原始碼分析

就理解了一個通過gyro_vector更新DCM的演算法,這個應該是在renormalization直接就需要了解,可以前期沒理解到底是幹嘛的,現在補上;關於renormalization的演算法可以參考上一篇博文。

        姿態解算過程中不僅需要修正陀螺儀的各種errors,還需要實時的更新的DCM。上週一直沒能理解的一個問題,在AP_AHRS_DCM.cpp中的matrix_update(delta_t),就是實時更新DCM矩陣的,原始碼如下,這一部分研究了很久,需要的基礎知識比較多。先上原始碼

// update the DCM matrix using only the gyros
Void AP_AHRS_DCM::matrix_update(float _G_Dt)
{
    _omega.zero();
    // average across first two healthy gyros. This reduces noise on
    // systems with more than one gyro. We don't use the 3rd gyro
    // unless another is unhealthy as 3rd gyro on PH2 has a lot more
    // noise
    uint8_t healthy_count = 0;
    Vector3f delta_angle;
    for (uint8_t i=0; i<_ins.get_gyro_count(); i++) {
        if (_ins.get_gyro_health(i) && healthy_count < 2) {
            Vector3f dangle;
            if (_ins.get_delta_angle(i, dangle)) {
                healthy_count++;
                delta_angle += dangle;
            }
        }
    }
    if (healthy_count > 1) {
        delta_angle /= healthy_count;
    }
    if (_G_Dt > 0) {
        _omega = delta_angle / _G_Dt;
        _omega += _omega_I;
        _dcm_matrix.rotate((_omega + _omega_P + _omega_yaw_P) * _G_Dt);
    }
}

          首先就是通過陀螺儀獲取兩次gyro_vector,然後取平均以降低誤差;然後就是比較專業的演算法實現_dcm_matrix.rotate((_omega +_omega_P + _omega_yaw_P) * _G_Dt)了。進入到matrix3.cpp中有rotate()函式,該函式就是實現DCM更新的演算法實現,演算法主要是用陀螺儀的輸出值與DCM矩陣的乘積再加回到DCM中去,處理過程中使用了離散化的概念,即dcm(k+1)=dcm(k)+增量,因為公式裡有求導,必須離散化後才能計算機處理,感謝青龍的指導。 

// apply an additional rotation from a body frame gyro vector
// to a rotation matrix.
template <typename T>
void Matrix3<T>::rotate(const Vector3<T> &g)
{
    Matrix3<T> temp_matrix;
    temp_matrix.a.x = a.y * g.z - a.z * g.y;
    temp_matrix.a.y = a.z * g.x - a.x * g.z;
    temp_matrix.a.z = a.x * g.y - a.y * g.x;
    temp_matrix.b.x = b.y * g.z - b.z * g.y;
    temp_matrix.b.y = b.z * g.x - b.x * g.z;
    temp_matrix.b.z = b.x * g.y - b.y * g.x;
    temp_matrix.c.x = c.y * g.z - c.z * g.y;
    temp_matrix.c.y = c.z * g.x - c.x * g.z;
    temp_matrix.c.z = c.x * g.y - c.y * g.x;

    (*this) += temp_matrix;//增加累加到原始資料上
}
        公式太多,沒辦法還是上圖吧~~~
        最後來一張神人做的圖。
六、總結         演算法的理解過程比較艱難,千萬不能閉門造車,要多多交流,思想的碰撞才能產生出火花,多謝各位群友的無私幫助。通過上述的分析以後,對整個姿態解算過程有了整體的框架理解,接下來會結合上面演算法的分析去分析ardupilot中關於姿態解算的原始碼,應該會理解的快一點了吧,希望如此~~~
        最近事情好多啊,愁死了,誰能幫我分擔一點啊~~~~
        昨天去三星見了一位智慧家居group的總監,聊了以後才發現自己有多low啊,我的BLE怎麼搞,大公司都在做壟斷化、平臺化,看來畢業只能硬著頭皮進大公司了,希望能找個好工作,誰在外企啊,幫我介紹工作啊,啊啊, 啊, ,啊, 啊。。。。
        寫的語無倫次的,湊合看吧

相關推薦

Pixhawk姿態2_mahony演算法分析

一、開篇   還是沒能進入到原始碼部分研究,對姿態解算過程太過於模糊,所以主要開始研究一下關於姿態解算的過程和實現,本篇博文主要是以mahony的演算法為基礎理解姿態解算的過程,主要參考的論文就是William Premerlani and Paul Bizard的關於DC

Pixhawk姿態4_補充

一、開篇         大家期待已久的第四篇來了,但是本篇可能比較水啊~~~見諒~~~         首先,上一週沒有什麼收穫,雖然看了不少的論文,但是卻沒有什麼質的飛越~~~~         看的論文都是關於姿態解算的,用的演算法大部分也都是基於mahony演算法的

React學習筆記react進階2

-s state ops category strong tro 服務 ive 周期 2.組件與服務器通信   組件的生命周期分為三個階段:掛載階段->更新階段->卸載階段,本文主要集中講述掛載和更新階段組件如何和服務器進行通信。 1.組件掛載階段通信  

姿態知識-陀螺儀加速度計6軸資料融合

這麼久的慣導總算是沒白看,加上一篇部落格的指點,這兩天把Mahony的九軸資料融合演算法看懂了。可惜第二版硬體還沒到,磁力計用不了,沒法驗證效果~今天先總結下陀螺儀和加速度計的六軸資料融合。 原創文章,轉載請說明出處:sheng-blog.cn 原文

Python學習【第2】:Python數據類型2

append 但是 iss 代碼 key 常用方法 uber ner ces 元組 #為何要有元組,存放多個值,元組不可變,更多的是用來做查詢 t=(1,[1,3],‘sss‘,(1,2)) #t=tuple((1,[1,3],‘sss‘,(1,2))) #

20180813視頻筆記 深度學習基礎上1必備基礎知識點 深度學習基礎上2神經網絡模型視頻筆記:深度學習基礎上3神經網絡案例實戰 和 深度學習基礎下篇

計算 概念 人臉識別 大量 png 技巧 表現 lex github 深度學習基礎上篇(3)神經網絡案例實戰 https://www.bilibili.com/video/av27935126/?p=1 第一課:開發環境的配置 Anaconda的安裝 庫的安裝 Windo

React學習筆記react基礎2

應用場景 組件 單元 ren provide form 實例 show wid   上一節我已經對React中基本的組件操作進行了說明,這一節我將對組件的一些附加屬性(如:組件的生命周期和組件的樣式)以及一些其他功能進行講解 一.組件的樣式 1.外部CSS樣式表: /

目標檢測模型2【RRPN】

文章目錄 1. 前言 2. 實現 2.1 關鍵idea 2.2 模型結構 2.3 具體細節 1.Rotated Bounding Box Representation-旋轉矩形框的表示 2.Rotati

資料庫redis2—— redis配置檔案,常用命令,效能測試工具

redis配置 如果你是找網上的其他教程來完成以上操作的話,相信你見過有的啟動命令是這樣的:   啟動命令帶了這個引數:redis.windows.conf,由於我測試環境是windows平臺,所以是這個,有的是redis.conf。顧名思義,redis.conf就是配置檔案,然後啟動時加

資料結構2:圖的基本操作 深度和廣度遍歷

程式碼實現 main.cpp(主函式) #include <iostream> #include "CMap.h" using namespace std; /** 圖的的儲存:鄰接矩陣 圖的遍歷:深度+廣度 A / \

目標檢測網路2【STN-空間變換網路】

1. STN是什麼 STN:Spatial Transformer Networks,即空間變換網路,是Google旗下 DeepMind 公司的研究成果。該論文提出空間變換網路STN,分為引數預測、座標對映、畫素採集三大部分,可以插入到現有的CNN模型中。通

高效能網站架構設計快取2- Redis C#客戶端

在上一篇中我簡單的介紹瞭如何利用redis自帶的客戶端連線server並執行命令來操作它,但是如何在我們做的專案或產品中操作這個強大的記憶體資料庫呢?首先我們來了解一下redis的原理吧。 官方文件上是這樣說的:Redis在TCP埠6379上監聽到來的連線,客戶端連線到來時,Redis伺服器為此建立一個TC

Netty進階基礎Buffer2

1、Buffer概念 1.1 緩衝區獲取 Buffer緩衝區是就是一個數組,有著不同的資料型別:ByteBuffer、Ch

.4-Vue源碼數據雙綁2

font _屬性 def ceo stat urn mark function return 開播了開播了!   vue通過數據劫持來達到監聽和操作DOM更新,上一節簡述了數組變化是如何監聽的,這一節先講講對象屬性是如何劫持的。 // Line-855

ArcGIS基礎2——如何將模型導成py文件?

src 代碼 使用 images 友好 編程 基礎篇 {} left Python腳本使用很方便,熟悉一點編程的,了解一點Python的,都可以在ArcGIS中嘗試用Python進行數據處理。把模型導出成py需要註意三個問題: 一是格式,Python對縮進很敏感,不使用{}

MQTT的學習Mosquitto發布-訂閱2

creat 訂閱模式 pub 測試 方法 ssa clientm art ble 在《MQTT的學習之Mosquitto安裝&使用(1)》一文末尾,我已經模擬了發布-訂閱模式,只是那時在服務器直接模擬的,並不是java代碼模擬的。下面貼出Java代碼 1、首先引入依

前端小白每天學習記錄----php2數據庫操作軟件

blog 4行 pan 一個數 修改 列數 tor 清0 插入數據 數據庫 存儲數據的倉庫(軟件)(DBA:Database Administrator)數據庫管理員mysqlsqlserveroracle...... 數據庫軟件架構 C(client)->

2——鏈表習題

給定 節點 code 定位 display 調整 urn position -c 題目:0:給定鏈表 L 和鏈表 P ,它們包含以升序排列的整數。操作 PrintList ( L , P ),將打印 L 中那些由 P 所指定位置上的元素,如 P 中的元素為 1 4 5,則

極化碼tal-vardy1

及其 討論 調用 指定 n) 十分 深入 alt 根據   繼前兩節我們分別探討了極化碼的編碼,以及深入到高斯信道探討高斯近似法之後,我們來關註一個非常重要的極化碼構造算法。這個算法並沒有一個明確的名詞,因此我們以兩位發明者的名字將其命名為“Tal-Vardy算法”。   

linux磁盤2——lvm

linux磁盤 lvm LVM Logical Volume Manager(邏輯卷管理)的簡寫,它是Linux環境下對磁盤分區進行管理的一種機制。LVM解決了分區大小分配磁盤擴展問題。例如: 在創建的系統的時候講/date 分配掛載在/目錄下,後期由於業務需求需要獨立出來。重新掛載一個新的分區