1. 程式人生 > >圓點博士小四軸演算法快速入門--四元數和PID圖解

圓點博士小四軸演算法快速入門--四元數和PID圖解

參考http://www.eeboard.com/bbs/thread-32321-1-1.html

飛控的演算法程式碼一般包括下面三個部分:濾波,姿態,PID

1,濾波可以用互補濾波來實現,互補濾波的資料很多,大家隨便就能找到。基本公式是:

互補濾波 


2,濾波完就是四元數拉。直接用老外Madgwick的IMU就可以。超級簡單
unsigned char BS004_IMU_Update(float ax,float ay,float az,float gx,float gy,float gz) 
{
        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;

        //        
        //圓點博士:歸一化處理
        norm = sqrt(ax*ax + ay*ay + az*az);     
        if(norm==0) return 0;        
        ax = ax / norm;
        ay = ay / norm;
        az = az / norm;   
  //        
        //圓點博士:建立小四軸座標系        
        vx = 2*(q1q3 - q0q2);                                                                

        vy = 2*(q0q1 + q2q3);
        vz = q0q0 - q1q1 - q2q2 + q3q3;
        //
        //圓點博士:座標系和重力叉積運算
        ex = (ay*vz - az*vy);                                                                
        ey = (az*vx - ax*vz);
        ez = (ax*vy - ay*vx);
        //
        //圓點博士:比例運算
        exInt = exInt + ex*bs004_quad_Ki;
        eyInt = eyInt + ey*bs004_quad_Ki;
        ezInt = ezInt + ez*bs004_quad_Ki;
        //
        //圓點博士:陀螺儀融合
        gx = gx + bs004_quad_Kp*ex + exInt;
        gy = gy + bs004_quad_Kp*ey + eyInt;
        gz = gz + bs004_quad_Kp*ez + ezInt;
        //
        //圓點博士:整合四元數率
        q0 = q0 + (-q1*gx - q2*gy - q3*gz)*bs004_quad_halfT;
        q1 = q1 + (q0*gx + q2*gz - q3*gy)*bs004_quad_halfT;
        q2 = q2 + (q0*gy - q1*gz + q3*gx)*bs004_quad_halfT;
        q3 = q3 + (q0*gz + q1*gy - q2*gx)*bs004_quad_halfT;  
        //
        //圓點博士:歸一化處理
        norm = sqrt(q0*q0 + q1*q1 + q2*q2 + q3*q3);
        if(norm==0) return 0;        
        q0 = q0 / norm;
        q1 = q1 / norm;
        q2 = q2 / norm;
        q3 = q3 / norm;
        //
        //圓點博士:尤拉角轉換
        bs004_imu_roll=asin(-2*q1q3 + 2*q0q2)*57.30f;
  bs004_imu_pitch=atan2(2*q2q3 + 2*q0q1, -2*q1q1-2*q2q2 + 1)*57.30f; 
  bs004_imu_yaw=bs004_imu_yaw-gz*bs004_mpu6050_gyro_scale;
        //
        return 1;        
}


3, PID的程式碼其實也很簡單,主要是要了解其中的原理,才能更好地調整引數。為了方便新手們理解,樓主建立了一個數學模型來讓大家瞭解。(只針對新手,老手就算了)

========圓點博士小四軸之PID控制模式分析=======
PID控制的P是Proportional的縮寫, 是比例的意思,I是Integral的縮寫,是積分的意思,D是Derivative的縮寫,是微分的意思。所以,PID就是我們常說的比例,積分,微分控制。
我們首先來看一個PID控制模型曲線圖:
該圖包含了比例控制,比例+積分控制,比較+積分+微分控制的電機響應圖的對比。

PID模型 
下面我們對曲線進行具體分析:
PID中的比例控制是最容易理解的,比例控制就是把角度的誤差乘以一個常數作為輸出驅動。假定我們有一個理想模型的電機,1V電壓的變化會帶來小四軸1度的角度改變。假定現在電機控制電壓是5V,小四軸在某一軸上的偏角是5度,目標角度是100度。我們把當前的電壓量定義為Vin,把輸出控制量定義為Vout。假定P等於0.2,那麼比例控制的結果就是:
第一次:Vout=Vin+(100-5)*P=5V+19V=24V,得到電機電壓是24V,對應的小四軸角度是24度,距離目標角度的誤差是100-24=76度。
第二次:Vout=Vin+(100-24)*P=24V+15V=39V, 從而引起的角度是39度。
我們看到,在這麼的一個比例控制系統下,小四軸角度在慢慢地向目標角度靠近。

PID中的積分控制就是把把所有角度誤差相加起來,然後乘上一個常數作為輸出驅動。在上述例子中,假定I=0.2, 我們來看看比例和積分控制同時起作用下的系統反應。
第一次:Vout=Vin+(100-5)*P+(100-5)*I=5V+19V+19V=43V,這時候小四軸角度為43度。
由於第一次控制前的誤差是100-5=95,第二次控制前的誤差是100-43=57,所以積分結果是152。
第二次:Vout=Vin+(100-43)*P+((100-5)+(100-43))*I=43V+11V+30V=84V, 這時候小四軸角度變為84度。
第三次:Vout=Vin+(100-84)*P+((100-5)+(100-43)+(100-84))*I=84+3V+33V=120V。這時小四軸角度變為120度。
我們看到,在增加了積分控制後,小四軸角度在快速向目標角度靠近。

PID中的微分控制就是把角度的變化乘上一個常數來作為電機驅動輸出。在上述例子中,假定D=0.2, 我們來看看比例,積分和微分共同控制下的系統反應。假定第一次前,電機轉速保持5轉,那麼第一次前的角度變化為0。
第一次:Vout=Vin+(100-5)*P+(100-5)*I-(5-5)*D=5V+19V+19V-0V=43V,這時候小四軸角度為43度。
和上一次相比,角度從5度變化到了43度,所以小四周角度變化是43-5=38度。
第二次:Vout=Vin+(100-43)*P+((100-5)+(100-43))*I-(43-5)*D=43V+11V+30V-7V=77V, 這時候小四周角度77度。

把上述的計算結果列出來,我們看到:
PID計算 

從上面的資料,我們可以看到:
1,單獨比例控制的時候,資料慢慢接近目標 (圖表中的紅色線)
2,加入積分控制之後,資料快速接近目標 (圖表中的藍色線)
3,微分控制起到抑制變化的作用。(圖表中的綠色線)

有了這些理論基礎,就可以寫PID控制程式碼拉。

========圓點博士小四軸之PID控制程式碼分析=======
在圓點博士小四軸2014版程式碼裡,我們只使用到PD引數。
首先我們來看PID中的比例控制。跟上一節模型提到的一樣,比例是針對誤差的控制。
首先我們獲取小四軸當前角度。
bs004_angle_cur_pitch=bs004_imu_pitch;
bs004_angle_cur_roll =bs004_imu_roll;
把當前角度和目標角度相減,就可以得到角度偏差。
bs004_angle_err_pitch=bs004_angle_cur_pitch-bs004_angle_target_pitch;
bs004_angle_err_roll=bs004_angle_cur_roll-bs004_angle_target_roll;
然後進行比例控制:
bs004_fly_m1=bs004_fly_m1
+bs004_pitch_p*bs004_angle_err_pitch
-bs004_roll_p *bs004_angle_err_roll
-bs004_yaw_p*bs004_angle_err_yaw;
bs004_fly_m2=bs004_fly_m2
-bs004_pitch_p*bs004_angle_err_pitch
-bs004_roll_p *bs004_angle_err_roll
+bs004_yaw_p*bs004_angle_err_yaw;

bs004_fly_m3=bs004_fly_m3
-bs004_pitch_p*bs004_angle_err_pitch
+bs004_roll_p *bs004_angle_err_roll
-bs004_yaw_p*bs004_angle_err_yaw;
bs004_fly_m4=bs004_fly_m4
+bs004_pitch_p*bs004_angle_err_pitch
+bs004_roll_p *bs004_angle_err_roll
+bs004_yaw_p*bs004_angle_err_yaw;

在上一節模型中,我們提到PID中的微分控制針對的是角度變化而進行的控制。
所以我們首先要得到當前角度和上一次角度的差異。
bs004_angle_dif_pitch=bs004_angle_cur_pitch-bs004_angle_last_pitch;
bs004_angle_dif_roll =bs004_angle_cur_roll-bs004_angle_last_roll;
bs004_angle_dif_yaw  =bs004_angle_last_yaw-bs004_angle_cur_yaw;
然後進行微分控制:
bs004_fly_m1=bs004_fly_m1
+bs004_pitch_d*bs004_angle_dif_pitch
-bs004_roll_d *bs004_angle_dif_roll
-bs004_yaw_d*bs004_angle_dif_yaw;
bs004_fly_m2=bs004_fly_m2
-bs004_pitch_d*bs004_angle_dif_pitch
-bs004_roll_d *bs004_angle_dif_roll
+bs004_yaw_d*bs004_angle_dif_yaw;
bs004_fly_m3=bs004_fly_m3
-bs004_pitch_d*bs004_angle_dif_pitch
+bs004_roll_d *bs004_angle_dif_roll
-bs004_yaw_d*bs004_angle_dif_yaw;
bs004_fly_m4=bs004_fly_m4
+bs004_pitch_d*bs004_angle_dif_pitch
+bs004_roll_d *bs004_angle_dif_roll
+bs004_yaw_d*bs004_angle_dif_yaw;

從上面的描述我們可以看出,小四軸的PID控制還是比較簡單的。