MPU6050のサンプルプログラム2

Dependencies:   ConfigFile SDFileSystem mbed

Fork of LAURUS_program by LAURUS

Files at this revision

API Documentation at this revision

Comitter:
ojan
Date:
Fri Jun 19 01:08:35 2015 +0000
Parent:
12:0d978eb4d639
Child:
14:f85cb5340cb8
Commit message:
add scripts to avoid Spiral.; modify Kalman filter model.

Changed in this revision

Vector/Vector.cpp Show annotated file Show diff for this revision Revisions of this file
Vector/Vector.h Show annotated file Show diff for this revision Revisions of this file
main.cpp Show annotated file Show diff for this revision Revisions of this file
myConstants.h Show annotated file Show diff for this revision Revisions of this file
--- a/Vector/Vector.cpp	Tue Jun 16 17:04:58 2015 +0000
+++ b/Vector/Vector.cpp	Fri Jun 19 01:08:35 2015 +0000
@@ -85,6 +85,10 @@
     components[dimNo-1] = val;
 }
 
+void Vector::SetComps(float* pComps) {
+    memcpy(components, pComps, sizeof(float) * dim);
+}
+
 float Vector::GetNorm() const {
     float norm = 0.0f;
     for (int i = 0; i < dim; i++) {
--- a/Vector/Vector.h	Tue Jun 16 17:04:58 2015 +0000
+++ b/Vector/Vector.h	Fri Jun 19 01:08:35 2015 +0000
@@ -18,6 +18,7 @@
     Vector& operator-=(const Vector& v);
 
     void SetComp(int dimNo, float val);
+    void SetComps(float* vals);
     float GetNorm() const;
     Vector Normalize() const;
     Vector GetParaCompTo(Vector v);
--- a/main.cpp	Tue Jun 16 17:04:58 2015 +0000
+++ b/main.cpp	Fri Jun 19 01:08:35 2015 +0000
@@ -16,11 +16,7 @@
 #define TRUE    1
 #define FALSE   0
 
-#define x       1
-#define y       2
-#define z       3
-
-const float dt = 0.1f;              // 割り込み周期(s)
+const float dt = 0.01f;              // 割り込み周期(s)
 const float ServoMax = 0.0023f;     // サーボの最大パルス長(s)
 const float ServoMin = 0.0006f;     // サーボの最小パルス長(s)
 const float PullMax  = 25.0f;       // 引っ張れる紐の最大量(mm)
@@ -76,9 +72,11 @@
 int pull_L = 0;                 // 左サーボの引っ張り量(mm:0~PullMax)
 int pull_R = 0;                 // 右サーボの引っ張り量(mm:0~PullMax)
 
-float yaw = 0.0f;               // 本体のヨー角(deg)
-float pitch = 0.0f;             // 本体のピッチ角(deg)
-float roll = 0.0f;              // 本体のロール角(deg)
+float yaw = 0.0f;               // 本体のヨー角(deg)z軸周り
+float pitch = 0.0f;             // 本体のピッチ角(deg)y軸周り
+float roll = 0.0f;              // 本体のロール角(deg)x軸周り
+
+float vrt_acc = 0.0f;           // 鉛直方向の加速度成分(落下検知に使用)
 
 /** config.txt **
 * #から始めるのはコメント行 
@@ -90,27 +88,27 @@
 
 /* ----- Kalman Filter ----- */
 // 地磁気ベクトル用
-Vector pri_x1(6);
-Matrix pri_P1(6, 6);
-Vector post_x1(6);
-Matrix post_P1(6, 6);
-Matrix F1(6, 6), H1(3, 6);
-Matrix R1(6, 6), Q1(3, 3);
-Matrix I1(6, 6);
-Matrix K1(6, 3);
+Vector pri_x1(7);
+Matrix pri_P1(7, 7);
+Vector post_x1(7);
+Matrix post_P1(7, 7);
+Matrix F1(7, 7), H1(3, 7);
+Matrix R1(7, 7), Q1(3, 3);
+Matrix I1(7, 7);
+Matrix K1(7, 3);
 Matrix S1(3, 3), S_inv1(3, 3);
 
 // 重力ベクトル用
 // ジャイロのバイアスも同時に推定する
-Vector pri_x2(4);
-Matrix pri_P2(4, 4);
-Vector post_x2(4);
-Matrix post_P2(4, 4);
-Matrix F2(4, 4), H2(2, 4);
-Matrix R2(4, 4), Q2(2, 2);
-Matrix I2(4, 4);
-Matrix K2(4, 2);
-Matrix S2(2, 2), S_inv2(2, 2);
+Vector pri_x2(5);
+Matrix pri_P2(5, 5);
+Vector post_x2(5);
+Matrix post_P2(5, 5);
+Matrix F2(5, 5), H2(3, 5);
+Matrix R2(5, 5), Q2(3, 3);
+Matrix I2(5, 5);
+Matrix K2(5, 3);
+Matrix S2(3, 3), S_inv2(3, 3);
 /* ----- ------------- ----- */
 
 Timer timer;
@@ -166,12 +164,12 @@
     raw_g.SetComp(3, 1.0f);
     
     // 機体に固定されたベクトルの初期化
-    b_f.SetComp(1, 1.0f);
+    b_f.SetComp(1, 0.0f);
     b_f.SetComp(2, 0.0f);
-    b_f.SetComp(3, 0.0f);
-    b_u.SetComp(1, 0.0f);
+    b_f.SetComp(3, -1.0f);
+    b_u.SetComp(1, 1.0f);
     b_u.SetComp(2, 0.0f);
-    b_u.SetComp(3, 1.0f);
+    b_u.SetComp(3, 0.0f);
     b_l = Cross(b_u, b_f);
     
     /* ---------- ↓↓↓ ここからメインループ ↓↓↓ ---------- */
@@ -182,10 +180,10 @@
         // 0.1秒おきにセンサーの出力をpcへ出力
         myled = 1; // LED is ON
         
-        INT_flag = FALSE;           // 割り込みによる変数書き換えを阻止
         
         // データ処理
         {
+            INT_flag = FALSE;           // 割り込みによる変数書き換えを阻止
             gms.read();                                     // GPSデータ取得
             UTC_t = (int)gms.time;
             
@@ -205,18 +203,16 @@
             float R_23 = r_l * b_u;             // 回転行列の(2,3)成分
             float R_33 = r_u * b_u;             // 回転行列の(3,3)成分
             
-            yaw = atan2(-R_12, R_11) * RAD_TO_DEG;
+            yaw = atan2(-R_12, R_11) * RAD_TO_DEG - MAG_DECLINATION;
             roll = atan2(-R_23, R_33) * RAD_TO_DEG;
             pitch = asin(R_13) * RAD_TO_DEG;
-            /*
-            pc.printf("%.3f, %.3f, %.3f, %.3f\r\n", 
-                    gyro.GetComp(1), post_x2.GetComp(3), 
-                    gyro.GetComp(2), post_x2.GetComp(4));
-            */
             
-            /*pc.printf("%.3f, %.3f, %.3f\r\n", 
-                    yaw, roll, pitch);
-            */
+            pc.printf("%.3f, %.3f, %.3f\r\n", 
+                    //geomag.GetComp(1), geomag.GetComp(2), geomag.GetComp(3));
+                    //yaw, pitch, roll);
+                    post_x2.GetComp(4), 
+                    post_x2.GetComp(5), 
+                    post_x1.GetComp(7));
             
             if(UTC_t - pre_UTC_t >= 1) {                    // GPSデータが更新されていたら
                 p.SetComp(1, gms.longitude * DEG_TO_RAD);
@@ -227,28 +223,53 @@
             
             pre_p = p;
             pre_UTC_t = UTC_t;
+        
+            float sv = (float)servoVcc.read_u16() * ADC_LSB_TO_V * 2.0f;
+            float lv = (float)logicVcc.read_u16() * ADC_LSB_TO_V * 2.0f;
+            
+            // データをmicroSDに保存し、XBeeでPCへ送信する
+            sprintf(data, "%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%d\r\n", 
+                    g.GetComp(1), g.GetComp(2), g.GetComp(3), 
+                    geomag.GetComp(1), geomag.GetComp(2), geomag.GetComp(3), 
+                    press, gms.longitude, gms.latitude, 
+                    sv, lv, optSensor.read_u16());
+            //fprintf(fp, data);
+            //fflush(fp);
+            //xbee.printf(data);
+            
+            INT_flag = TRUE;            // 割り込み許可
         }
         
-        float sv = (float)servoVcc.read_u16() * ADC_LSB_TO_V * 2.0f;
-        float lv = (float)logicVcc.read_u16() * ADC_LSB_TO_V * 2.0f;
-        
-        sprintf(data, "%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%.3f,%d\r\n", 
-                g.GetComp(1), g.GetComp(2), g.GetComp(3), 
-                geomag.GetComp(1), geomag.GetComp(2), geomag.GetComp(3), 
-                press, gms.longitude, gms.latitude, 
-                sv, lv, optSensor.read_u16());
-        //fprintf(fp, data);
-        //fflush(fp);
-        //xbee.printf(data);
-        
-        INT_flag = TRUE;            // 割り込み許可
         
         // 制御ルーチン
         {
-            pull_L = (pull_L+5)%30;
-            pull_R = (pull_R+5)%30;
+            
+            if(fabs(roll) > 40.0f) {
+                // スパイラル回避行動
+                if(roll > 0) {
+                    pull_L = PullMax;
+                    pull_R = 0;
+                } else {
+                    pull_L = 0;
+                    pull_R = PullMax;
+                }
+            } else {
+                
+            }
+                
+            //pull_L = (pull_L+5)%PullMax;
+            //pull_R = (pull_R+5)%PullMax;
             //pull_L = 0;
             //pull_R = 30;
+            
+            
+            
+            // 指定された引っ張り量だけ紐を引っ張る
+            if(pull_L < 0) pull_L = 0;
+            else if(pull_L > PullMax) pull_L = PullMax;
+            if(pull_R < 0) pull_R = 0;
+            else if(pull_R > PullMax) pull_R = PullMax;
+            
             servoL.pulsewidth((ServoMax - ServoMin) * pull_L / PullMax + ServoMin);
             servoR.pulsewidth((ServoMax - ServoMin) * pull_R / PullMax + ServoMin);
             
@@ -311,119 +332,122 @@
     // 重力
     {
         // 誤差共分散行列の値を決める(対角成分のみ)
-        float alpha_R2 = 0.001f;
+        float alpha_R2 = 0.002f;
         float alpha_Q2 = 0.5f;
         R2 *= alpha_R2;
-        R2.SetComp(3, 3, 0.003f);
-        R2.SetComp(4, 4, 0.003f);
         Q2 *= alpha_Q2;
         
-        // 状態方程式のヤコビアンの初期値を代入(時間変化無し)
-        float f[16] = {
-            1.0f, 0.0f, -dt, 0.0f, 
-            0.0f, 1.0f, 0.0f, -dt, 
-            0.0f, 0.0f, 1.0f, 0.0f, 
-            0.0f, 0.0f, 0.0f, 1.0f
+        // 観測方程式のヤコビアンの値を設定(時間変化無し)
+        float h2[15] = {
+            1.0f, 0.0f, 0.0f, 0.0f, 0.0f,
+            0.0f, 1.0f, 0.0f, 0.0f, 0.0f,  
+            0.0f, 0.0f, 1.0f, 0.0f, 0.0f
         };
         
-        F2.SetComps(f);
-        
-        // 観測方程式のヤコビアンの値を設定(時間変化無し)
-        float h[8] = {
-            1.0f, 0.0f, 0.0f, 0.0f,  
-            0.0f, 1.0f, 0.0f, 0.0f
-        };
-        
-        H2.SetComps(h);
+        H2.SetComps(h2);
     }
     
     // 地磁気
     {
         // 誤差共分散行列の値を決める(対角成分のみ)
-        float alpha_R1 = 500.0f;
-        float alpha_Q1 = 1000.0f;
+        float alpha_R1 = 0.002f;
+        float alpha_Q1 = 0.5f;
         R1 *= alpha_R1;
         Q1 *= alpha_Q1;
         
-        // 状態方程式のヤコビアンの初期値を代入(時間変化あり)
-        float f[36] = {
-            1.0f, raw_gyro.GetComp(3)*dt, -raw_gyro.GetComp(2)*dt, 0.0f, 0.0f, 0.0f, 
-            -raw_gyro.GetComp(3)*dt, 1.0f, raw_gyro.GetComp(1)*dt, 0.0f, 0.0f, 0.0f, 
-            raw_gyro.GetComp(2)*dt, -raw_gyro.GetComp(1)*dt, 1.0f, 0.0f, 0.0f, 0.0f, 
-            0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 
-            0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+        // 観測方程式のヤコビアンの値を設定(時間変化無し)
+        float h1[21] = {
+            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f,
+            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,
+            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f
         };
         
-        F1.SetComps(f);
-        
-        // 観測方程式のヤコビアンの値を設定(時間変化無し)
-        float h[18] = {
-            1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  
-            0.0f, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
-            0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 1.0f
-        };
-        
-        H1.SetComps(h);
+        H1.SetComps(h1);
     }
 }
 
 void KalmanUpdate() {
+    // 重力
+    
     {
-        // 入力ベクトル(角速度)
-        Vector u(4);
-        u.SetComp(1, raw_gyro.GetComp(1) * dt);
-        u.SetComp(2, raw_gyro.GetComp(2) * dt);
-        u.SetComp(3, 0.0f);
-        u.SetComp(4, 0.0f);
+        // ヤコビアンの更新
+        float f2[25] = {
+            1.0f, (raw_gyro.GetComp(3) - post_x1.GetComp(7))*dt, -(raw_gyro.GetComp(2) - post_x2.GetComp(5))*dt, 0.0f, post_x2.GetComp(3)*dt, 
+            -(raw_gyro.GetComp(3) - post_x1.GetComp(7))*dt, 1.0f, (raw_gyro.GetComp(1) - post_x2.GetComp(4))*dt, -post_x2.GetComp(3)*dt, 0.0f, 
+            (raw_gyro.GetComp(2) - post_x2.GetComp(5))*dt, -(raw_gyro.GetComp(1) - post_x2.GetComp(4))*dt, 1.0f, post_x2.GetComp(2)*dt, -post_x2.GetComp(1)*dt, 
+            0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 
+            0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+        };
+        
+        F2.SetComps(f2);
         
         // 事前推定値の更新
-        pri_x2 = F2 * post_x2;
+        //pri_x2 = F2 * post_x2;
+        
+        float pri_x2_vals[5] = {
+            post_x2.GetComp(1) + post_x2.GetComp(2) * (raw_gyro.GetComp(3) - post_x1.GetComp(7)) * dt - post_x2.GetComp(3) * (raw_gyro.GetComp(2) - post_x2.GetComp(5)) * dt, 
+            post_x2.GetComp(2) + post_x2.GetComp(3) * (raw_gyro.GetComp(1) - post_x2.GetComp(4)) * dt - post_x2.GetComp(1) * (raw_gyro.GetComp(3) - post_x1.GetComp(7)) * dt, 
+            post_x2.GetComp(3) + post_x2.GetComp(1) * (raw_gyro.GetComp(2) - post_x2.GetComp(5)) * dt - post_x2.GetComp(2) * (raw_gyro.GetComp(1) - post_x2.GetComp(4)) * dt, 
+            post_x2.GetComp(4), 
+            post_x2.GetComp(5)
+        };
+        
+        pri_x2.SetComps(pri_x2_vals);
+        
         // 事前誤差分散行列の更新
         pri_P2 = F2 * post_P2 * F2.Transpose() + R2;
         
         // カルマンゲインの計算
         S2 = Q2 + H2 * pri_P2 * H2.Transpose();
-        float det;
+        static float det;
         if((det = S2.Inverse(S_inv2)) >= 0.0f) {
             pc.printf("E:%.3f\r\n", det);
             return;     // 万が一、逆行列が見つからなかった場合は前回の推定値を保持して終了
         }
         K2 = pri_P2 * H2.Transpose() * S_inv2;    
         
-        // 観測ベクトル(重力加速度ベクトルから算出した角度)
-        Vector alpha(2);
-        alpha.SetComp(1, -atan2(raw_acc.GetComp(2), raw_acc.GetComp(3)));
-        alpha.SetComp(2, -atan2(raw_acc.GetComp(1), raw_acc.GetComp(3)));
-        
         // 事後推定値の更新
-        post_x2 = pri_x2 + K2 * (alpha - H2 * pri_x2);
+        post_x2 = pri_x2 + K2 * (raw_acc - H2 * pri_x2);
         // 事後誤差分散行列の更新
         post_P2 = (I2 - K2 * H2) * pri_P2;
     }
     
+    
     // 地磁気
     {
         // ヤコビアンの更新
-        float f[36] = {
-            1.0f, raw_gyro.GetComp(3)*dt, -raw_gyro.GetComp(2)*dt, 0.0f, 0.0f, 0.0f, 
-            -raw_gyro.GetComp(3)*dt, 1.0f, raw_gyro.GetComp(1)*dt, 0.0f, 0.0f, 0.0f, 
-            raw_gyro.GetComp(2)*dt, -raw_gyro.GetComp(1)*dt, 1.0f, 0.0f, 0.0f, 0.0f, 
-            0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 
-            0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
-            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
+        float f1[49] = {
+            1.0f, (raw_gyro.GetComp(3) - post_x1.GetComp(7))*dt, -(raw_gyro.GetComp(2) - post_x2.GetComp(5))*dt, 0.0f, 0.0f, 0.0f, -post_x1.GetComp(2) * dt, 
+            -(raw_gyro.GetComp(3) - post_x1.GetComp(7))*dt, 1.0f, (raw_gyro.GetComp(1) - post_x2.GetComp(4))*dt, 0.0f, 0.0f, 0.0f, post_x1.GetComp(1) * dt, 
+            (raw_gyro.GetComp(2) - post_x2.GetComp(5))*dt, -(raw_gyro.GetComp(1) - post_x2.GetComp(4))*dt, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 
+            0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 
+            0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f,  
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f,  
+            0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
         };
         
-        F1.SetComps(f);
+        F1.SetComps(f1);
         
         // 事前推定値の更新
-        pri_x1 = F1 * post_x1;
+        //pri_x1 = F1 * post_x1;
+        float pri_x1_vals[7] = {
+            post_x1.GetComp(1) + post_x1.GetComp(2) * (raw_gyro.GetComp(3) - post_x1.GetComp(7)) * dt - post_x1.GetComp(3) * (raw_gyro.GetComp(2) - post_x2.GetComp(5)) * dt, 
+            post_x1.GetComp(2) + post_x1.GetComp(3) * (raw_gyro.GetComp(1) - post_x2.GetComp(4)) * dt - post_x1.GetComp(1) * (raw_gyro.GetComp(3) - post_x1.GetComp(7)) * dt, 
+            post_x1.GetComp(3) + post_x1.GetComp(1) * (raw_gyro.GetComp(2) - post_x2.GetComp(5)) * dt - post_x1.GetComp(2) * (raw_gyro.GetComp(1) - post_x2.GetComp(4)) * dt, 
+            post_x1.GetComp(4), 
+            post_x1.GetComp(5), 
+            post_x1.GetComp(6), 
+            post_x1.GetComp(7)
+        };
+        
+        pri_x1.SetComps(pri_x1_vals);
+        
         // 事前誤差分散行列の更新
         pri_P1 = F1 * post_P1 * F1.Transpose() + R1;
         
         // カルマンゲインの計算
         S1 = Q1 + H1 * pri_P1 * H1.Transpose();
-        float det;
+        static float det;
         if((det = S1.Inverse(S_inv1)) >= 0.0f) {
             pc.printf("E:%.3f\r\n", det);
             return;     // 万が一、逆行列が見つからなかった場合は前回の推定値を保持して終了
@@ -432,6 +456,19 @@
         
         // 事後推定値の更新
         post_x1 = pri_x1 + K1 * (raw_geomag - H1 * pri_x1);
+        // 地磁気ベクトルの大きさに拘束条件を与える
+        /*{
+            Vector gm(3);
+            gm.SetComp(1, post_x1.GetComp(1));
+            gm.SetComp(2, post_x1.GetComp(2));
+            gm.SetComp(3, post_x1.GetComp(3));
+            
+            gm = MAG_MAGNITUDE * gm.Normalize();
+            
+            post_x1.SetComp(1, gm.GetComp(1));
+            post_x1.SetComp(2, gm.GetComp(2));
+            post_x1.SetComp(3, gm.GetComp(3));
+        }*/
         // 事後誤差分散行列の更新
         post_P1 = (I1 - K1 * H1) * pri_P1;
     }
@@ -440,13 +477,13 @@
 float distance(Vector p1, Vector p2) {
     if(p1.GetDim() != p2.GetDim()) return 0.0f;
     
-    float mu_y = (p1.GetComp(2) + p2.GetComp(2)) * 0.5f;
-    float s_mu_y = sin(mu_y);
-    float w = sqrt(1 - GPS_SQ_E * s_mu_y * s_mu_y);
-    float m = GPS_A * (1 - GPS_SQ_E) / (w * w * w);
-    float n = GPS_A / w;
-    float d1 = m * (p1.GetComp(2) - p2.GetComp(2));
-    float d2 = n * cos(mu_y) * (p1.GetComp(1) - p2.GetComp(1));
+    static float mu_y = (p1.GetComp(2) + p2.GetComp(2)) * 0.5f;
+    static float s_mu_y = sin(mu_y);
+    static float w = sqrt(1 - GPS_SQ_E * s_mu_y * s_mu_y);
+    static float m = GPS_A * (1 - GPS_SQ_E) / (w * w * w);
+    static float n = GPS_A / w;
+    static float d1 = m * (p1.GetComp(2) - p2.GetComp(2));
+    static float d2 = n * cos(mu_y) * (p1.GetComp(1) - p2.GetComp(1));
     
     return sqrt(d1 * d1 + d2 * d2);
 }
@@ -486,6 +523,8 @@
         gyro = raw_gyro;
         press = raw_press;
         
+        vrt_acc = raw_acc * raw_g;
+        
     }
 }
 
--- a/myConstants.h	Tue Jun 16 17:04:58 2015 +0000
+++ b/myConstants.h	Fri Jun 19 01:08:35 2015 +0000
@@ -27,6 +27,7 @@
 #define MAG_LSB_TO_GAUSS    0.00092f                // Gauss/LSB
 #define MAG_MAGNITUDE       0.46f                   // Magnitude of GeoMagnetism (Gauss)
 #define MAG_SIN             -0.754709580f           // Sin-Value of Inclination
+#define MAG_DECLINATION     7.5f                    // declination (deg)
 
 /* ADC */
 #define ADC_LSB_TO_V        0.000050354f            // 3.3(V)/65535(LSB)
\ No newline at end of file