KalmanImu.h

Go to the documentation of this file.
00001 // ----------------------------------------------------------------------------
00002 //
00003 // $Id$ 
00004 //
00005 // Copyright 2008, 2009, 2010, 2011, 2012  Antonio Franchi and Paolo Stegagno    
00006 //
00007 // This file is part of MIP.
00008 //
00009 // MIP is free software: you can redistribute it and/or modify
00010 // it under the terms of the GNU General Public License as published by
00011 // the Free Software Foundation, either version 3 of the License, or
00012 // (at your option) any later version.
00013 //
00014 // MIP is distributed in the hope that it will be useful,
00015 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017 // GNU General Public License for more details.
00018 //
00019 // You should have received a copy of the GNU General Public License
00020 // along with MIP. If not, see <http://www.gnu.org/licenses/>.
00021 //
00022 // Contact info: franchi@diag.uniroma1.it stegagno@diag.uniroma1.it
00023 //
00024 // ----------------------------------------------------------------------------
00025 
00026 
00030 
00032 /* @{ */
00033 
00034 #ifndef __KALMAN_IMU_H_
00035 #define __KALMAN_IMU_H_
00036 
00037 #include <stdlib.h>
00038 #include <time.h>
00039 
00040 #include <Types.h>
00041 #include <fstream>
00042 
00043 #include <S1.h>
00044 #include <R2.h>
00045 #include <Surface.h>
00046 #include <MIPMatrix.h>
00047 
00048 #define GRAV     9.81    // Gravity acceleration.
00049 #define EPSILON                  0.01    // Maximum acceptable error in calculus.
00050 
00051 
00052 #define A_ROW_IMU            5    // Number of rows in the A(k) matrix.
00053 #define A_COL_IMU            5    // Number of columns in the A(k) matrix.
00054 #define C_ROW_IMU               5    // Number of rows in the C(k) matrix. C_ROW must be equal to G_ROW, see function matrix_K
00055 #define C_COL_IMU               5    // Number of columns in the C(k) matrix.
00056 #define Pp_ROW_IMU     5    // Number of rows in the Pp(k) matrix.
00057 #define Pp_COL_IMU     5    // Number of columns in the Pp(k) matrix.
00058 #define K_ROW_IMU               5    // Number of rows in the K(k+1) matrix.
00059 #define K_COL_IMU               5    // Number of columns in the K(k+1) matrix.
00060 #define P_ROW_IMU                   5    // Number of rows in the P(k+1) matrix.
00061 #define P_COL_IMU                    5    // Number of columns in the P(k+1) matrix.
00062 #define F_ROW_IMU                  5    // Number of rows in the F(k) matrix.
00063 #define F_COL_IMU                  5    // Number of columns in the F(k) matrix.
00064 #define G_ROW_IMU               5    // Number of rows in the G(k+1) matrix. G_ROW must be equal to C_ROW, see function matrix_K
00065 #define G_COL_IMU               5    // Number of columns in the G(k+1) matrix.
00066 #define OUT_PRED_ROWS_IMU       5    // Number of rows in the OutPred(k+1) matrix.
00067 #define OUT_MEAS_ROWS_IMU       5    // Number of rows in the OutMeas(k+1) matrix.
00068 #define GPS_MEAS_IMU              2    // GPS data.
00069 #define ENC_MEAS_IMU    5    // Encoder data.
00070 #define ACC_MEAS_IMU    3    // Accelerometer data.
00071 #define GYRO_MEAS_IMU    3    // Gyro data.
00072 #define MAGN_MEAS_IMU    3    // Magnetometer data.
00073 
00078 /*
00079 Nel filtro di Kalman ci sono 4 variabili fondamentali:
00080 1:- La stima dello stato al passo k fatta utilizzando le misure fino al passo k. Tale stima è indicata con X(k|k)
00081 2:- La stima dello stato al passo k+1 fatta utilizzando le misure fino al passo k. Tale stima è indicata con X(k+1|k).
00082 3:- La stima della uscita al passo k fatta utilizzando le misure fino al passo k. Tale stima è indicata con Y(k|k) e  coincide con la misura stessa 
00083     effettuata al passo k cioè Y(k).
00084 4:- La stima della uscita al passo k+1 fatta utilizzando le misure fino al passo k. Tale stima è indicata con Y(k+1|k).
00085 
00086 Dato il modello matematico del robot nella forma:
00087 X(k+1)=f(x(k),u(k),k) -- Equazione di stato
00088 Y(k)=h(x(k),u(k),k)   -- Equazione di uscita
00089 
00090 Le stime indicate di sopra ai passi 2 e 4 si fanno utilizzando, rispettivamente, le equazioni di stato e di uscita del modello matematico del robot.
00091 */
00092 
00093 
00094 #include <boost/concept_check.hpp>
00095 
00096 class KalmanFilterImu
00097 {
00098  private:
00099   Decimal  CycleTime;   //Kalman filter sampling time in seconds.
00100   Decimal  Force;       //Force applied to the robot
00101   Decimal  Torque;      //Torque applied to the robot
00102   
00103   MIPMatrix *State_0;   //Estimate of robot status at time k: X(k|k). 3 data: x,y,theta.
00104   MIPMatrix *State_1;   //Estimate of robot status at time k+1: X(k+1|k). 3 data: x,y,theta.
00105   MIPMatrix *OutPred;   //Prediction of robot output at time k+1: Y(k+1|k). 3 data: x,y,theta.
00106   MIPMatrix *OutMeas;   //Estimation of robot output at time k+1: 
00107   
00108   // GPS Measures
00109   MIPMatrix *GPS_Meas;  //GPS measures at time k: Y(k|k); 2 data: x,y.
00110   Decimal    GPS_MeasTime;  //Time at GPS measures read
00111   Decimal    GPS_DeltaTime;
00112   
00113   // Encoder Measures
00114   MIPMatrix *ENC_Meas;      //Encoder measures at time k.
00115   Decimal    ENC_MeasTime;  //Time at encoder measures read
00116   Decimal    ENC_DeltaTime;
00117   
00118   // IMU Measures
00119   MIPMatrix *ACC_Meas;  //Accelerometer measures at time k.
00120   MIPMatrix *GYRO_Meas;  //Gyro measures at time k.
00121   MIPMatrix *MAGN_Meas;  //Magnetometer measures at time k.
00122   Decimal    IMU_MeasTime;  //Time at IMU measures read
00123   Decimal    IMU_DeltaTime;
00124   
00125   Decimal RobotMass;    //Mass of the robot.
00126   Decimal RobotMoI;     //Moment of Inertia of the robot (yaw axis).
00127   
00128   Surface *Surf;         //Surface on which the robot is moving
00129   int CurrentRobotPlane; // Reference to the current plane where the robot is moving.
00130   int SemiSpace;         //Side w.r.t. the next plane. Used to detect the change of the plane where the robot is moving.
00131   
00132   // Current robot distance from reference points  
00133   //Decimal CurRefPointDist;//Robot distance from reference point in the current surface plane
00134   //Decimal NextRefPointDist;//Robot distance from reference point in the next surface plane
00135   //Decimal PrevRefPointDist;//Robot distance from reference point in the previous surface plane
00136   
00137   MIPMatrix *Mat_Pp;
00138   MIPMatrix *Mat_A;  
00139   MIPMatrix *Mat_C;
00140   MIPMatrix *Mat_K;
00141   MIPMatrix *Mat_P;
00142   MIPMatrix *Mat_G;
00143   MIPMatrix *Mat_F;
00144 
00145 //   MIPMatrix *tmpmat;//Only for matrix functions test
00146   
00147   //Decimal Force;//Force applied to the robot.
00148   //Decimal Torque;//Torque applied to the robot.
00149   bool GPS_MeasAvail;//1 = GPS measure available; 0 = GPS measures not available;
00150   
00151   //void initializeMatrixC(); I(5x5) matrix initialized at its instantiation
00152   
00153   void initializeState_1();//This function initializes the robot predicted status matrix: State_1(k+1|k).
00154 
00155   void initializeMatrixF();//This function initializes the robot status noise matrix.
00156   
00157                 void initializeMatrixG();//This function initializes the robot output noise matrix.
00158 
00159   void initializeMatrixPp();//This function initializes the equivalent of the covariance error prediction matrix.
00160 
00161   void setSemiSpace();//This function sets a reference value (+1 or -1) to tag the semi-space where the robot is moving.
00162                       //The reference plane is the next w.r.t the one on which the robot is moving.
00163   
00164   void updRobotPlane();//This function updates the plane on which the robot is moving
00165   
00166   // The following functions implements the Kalman filter steps
00167   
00168   void outPred();//II: This function calculates the output prediction.
00169   
00170   //void Matrix_C();//III: This matrix is the Jacobian matrix of h() in X(k+1,k). It is 
00171                     // a (2x3) matrix and is built by the EKF constructor.
00172   
00173   void matrix_K();//IV: This function calculates the Kalman gain matrix K(k+1).
00174   
00175   void matrix_P();//V: This function calculates the matrix P(k+1).
00176 
00177   void estimateRobotStatus();//VI: This function estimates the matrix X(k+1,k+1) using GPS measures.
00178 
00179   void calculateStatusPrediction();//VIII: This function calculates the prediction of the status of the robot X(k+1|k)
00180 
00181   void calculate_A();//IX: This function calculates the Jacobian matrix of f() in X(k,k).
00182 
00183   void calculatePp();//X:  This function calculates the Pp(k+1) matrix
00184     
00185   //void Get_GPS_Measures();
00186  
00187        
00188  public:
00190   KalmanFilterImu (string namefile)
00191   {
00192           cout << "KalmanFilterImu::KalmanFilterImu() starting" << "\n";
00193    //tmpmat = new MIPMatrix(3,3,ZERO_MATRIX); //Used only for matrix functions test.
00194    State_0 = new MIPMatrix(A_ROW_IMU,1,ZERO_MATRIX);     
00195    State_1 = new MIPMatrix(A_ROW_IMU,1,ZERO_MATRIX);
00196    
00197           //cout << "KalmanFilterImu::KalmanFilterImu() starting 2" << "\n";   
00198    OutPred = new MIPMatrix(OUT_PRED_ROWS_IMU,1,ZERO_MATRIX);
00199    OutMeas = new MIPMatrix(OUT_MEAS_ROWS_IMU,1,ZERO_MATRIX);
00200    
00201    ENC_Meas = new MIPMatrix(ENC_MEAS_IMU,1,ZERO_MATRIX);  //Encoder measures at time k.
00202    ENC_MeasTime = 0;
00203    ENC_DeltaTime = 0; 
00204    
00205    ACC_Meas = new MIPMatrix(ACC_MEAS_IMU,1,ZERO_MATRIX);  //Accelerometer measures at time k.
00206    GYRO_Meas = new MIPMatrix(GYRO_MEAS_IMU,1,ZERO_MATRIX); //Gyro measures at time k.
00207    MAGN_Meas = new MIPMatrix(MAGN_MEAS_IMU,1,ZERO_MATRIX); //Magnetometer measures at time k.
00208    IMU_MeasTime = 0;
00209    IMU_DeltaTime = 0; 
00210 
00211    GPS_Meas = new MIPMatrix(GPS_MEAS_IMU,1,ZERO_MATRIX);  //GPS measures at time k.
00212    GPS_MeasTime = 0;
00213    GPS_DeltaTime = 0; 
00214 
00215           //cout << "KalmanFilterImu::KalmanFilterImu() starting 3" << "\n";   
00216    Mat_Pp = new MIPMatrix(Pp_ROW_IMU, Pp_COL_IMU,IDENTITY_MATRIX);     
00217    Mat_A = new MIPMatrix(A_ROW_IMU, A_COL_IMU,IDENTITY_MATRIX);
00218    //cout << "KalmanFilterImu::KalmanFilterImu() starting 4" << "\n";
00219    Mat_C = new MIPMatrix(C_ROW_IMU, C_COL_IMU,IDENTITY_MATRIX);
00220           //cout << "KalmanFilterImu::KalmanFilterImu() starting 4a" << "\n";
00221    Mat_K = new MIPMatrix(K_ROW_IMU, K_COL_IMU,ZERO_MATRIX); 
00222           //cout << "KalmanFilterImu::KalmanFilterImu() starting 5" << "\n";
00223    Mat_P = new MIPMatrix(P_ROW_IMU, P_COL_IMU,ZERO_MATRIX);       
00224    Mat_G = new MIPMatrix(G_ROW_IMU, G_COL_IMU,ZERO_MATRIX);
00225    Mat_F = new MIPMatrix(F_ROW_IMU, F_COL_IMU,ZERO_MATRIX);
00226 
00227    CycleTime = 0;
00228    Force = 0;
00229    Torque = 0;
00230 
00231           //cout << "KalmanFilterImu::KalmanFilterImu() starting 6" << "\n";
00232    cout << "Kalman Surface construction" << "\n";
00233    Surf = new Surface(namefile);
00234    
00235    cout << "KalmanFilterImu::Matrix_C" << endl;
00236    //initializeMatrixC();//In this particular case mat_C  is a constant matrix and it's initialized at startup.
00237                         Mat_C->printMIPMatrix();
00238                         cout << "\n";
00239 
00240    //cout << "Initialize F matrix" << endl;
00241    initializeMatrixF();
00242                         //Mat_F->printMIPMatrix();
00243                         cout << "\n";
00244 
00245    //cout << "Initialize Matrix G" << endl;
00246    initializeMatrixG();
00247                         //Mat_G->printMIPMatrix();
00248                         cout << "\n";
00249 
00250    cout << "KalmanFilterImu:: Initialize status prediction matrix: State_1." << endl;
00251    initializeState_1();//This function initializes the robot predicted status matrix: State_1(k+1|k). Initial conditions.
00252                         cout << "\n";
00253 
00254    initializeMatrixPp();
00255                         cout << "\n";
00256 
00257    CurrentRobotPlane = 0;// It is assumed that the robot initial position belongs to the first plane.
00258    SemiSpace = 0;
00259    setSemiSpace();
00260    GPS_MeasAvail = false; 
00261    cout << "KalmanFilterImu:: Constructor end." << endl;  }
00262 
00265   ~KalmanFilterImu()
00266   {
00267    cout << "KalmanFilterImu destructor starting." << endl;
00268    delete State_0;
00269    delete State_1;
00270    
00271    delete OutPred;
00272    delete OutMeas;
00273    
00274    delete GPS_Meas;
00275    delete ENC_Meas;
00276    delete ACC_Meas;
00277    delete GYRO_Meas;
00278    delete MAGN_Meas;
00279 
00280    delete Mat_Pp;     
00281    delete Mat_A;          
00282    delete Mat_C;
00283    delete Mat_K; 
00284    delete Mat_P;       
00285    delete Mat_G;
00286    delete Mat_F;
00287    
00288    delete Surf;
00289    
00290    cout << "KalmanFilterImu destructor OK" << endl;
00291   }
00292   
00293   void setAppliedForce (Decimal F)
00294   {
00295    Force = F;
00296    return;
00297   }
00298 
00299   void setAppliedTorque (Decimal To)
00300   {
00301       Torque = To;
00302       return;
00303   }
00304 
00305   void setCycleTime (Decimal T)
00306   {
00307       CycleTime = T;
00308       return;
00309   }
00310 
00311   void setCurrentRobotPlane (int Plane)
00312   {
00313       CurrentRobotPlane = Plane;
00314       return;
00315   }
00316   
00318   void setGPSAvailability()
00319   {
00320       GPS_MeasAvail = true;
00321       return;
00322   }
00323   
00325   void unsetGPSAvailability()
00326   {
00327       GPS_MeasAvail = false;
00328       return;
00329   }
00330   
00331   Decimal getAppliedForce(){return Force;}
00332   
00333   Decimal getAppliedTorque(){return Torque;}
00334 
00335   Decimal getCycleTime(){return CycleTime;}
00336 
00337   int getCurrentRobotPlane(){return CurrentRobotPlane;}
00338   
00339   int getGPSAvailability(){return GPS_MeasAvail;}
00340   
00341   MIPMatrix* getRobStatus(){return State_0;}
00342   
00343   void updateENCMeasuresTime(Decimal Time)
00344   {
00345       ENC_DeltaTime = Time - ENC_MeasTime; 
00346       cout << "KalmanFilterImu::updateENCMeasuresTime(). previous read time = " << ENC_MeasTime << "; Last read time = " << Time << "; Delta time = " << ENC_DeltaTime << "\n";
00347       ENC_MeasTime = Time;
00348       return;
00349   }
00350 
00351   void updateIMUMeasuresTime(Decimal Time)
00352   {
00353       IMU_DeltaTime = Time - IMU_MeasTime; 
00354       cout << "KalmanFilterImu::updateIMUMeasuresTime(). previous read time = " << IMU_MeasTime << "; Last read time = " << Time << "; Delta time = " << IMU_DeltaTime << "\n";
00355       IMU_MeasTime = Time;
00356       return;
00357   }
00358 
00359   void updateGPSMeasuresTime(Decimal Time)
00360   {
00361       GPS_DeltaTime = Time - GPS_MeasTime; 
00362       cout << "KalmanFilterImu::updateGPSMeasuresTime(). previous read time = " << GPS_MeasTime << "; Last read time = " << Time << "; Delta time = " << GPS_DeltaTime << "\n";
00363       GPS_MeasTime = Time;
00364       return;
00365   }
00366 
00367   void ProcessENCMeasures(MIPMatrix *RobStat)
00368   {
00369       Decimal meas_speed;
00370       Decimal meas_turnrate;
00371       
00372       Decimal dx_loc;
00373       Decimal dy_loc;
00374       Decimal Noise;
00375       Angle   Noise_1;
00376       Decimal tmp;
00377       Angle   tmp_1;
00378       
00379       //MIPMatrix *ds_Iner;
00380       //MIPMatrix *ds_Loc;
00381       //MIPMatrix *RotLoc2Iner;//Rotation matrix from local reference frame to inertial reference frame
00382       //MIPMatrix *RotIner2Loc;//Rotation matrix from inertial reference frame to local reference frame
00383       
00384       cout << "KalmanFilterImu::ProcessENCMeasures() (without noise) X = "    << RobStat->GetMIPMatrixVal(1,1) << "\n";
00385       cout << "KalmanFilterImu::ProcessENCMeasures() (without noise) Y = "    << RobStat->GetMIPMatrixVal(2,1) << "\n";
00386       cout << "KalmanFilterImu::ProcessENCMeasures() (without noise) Th = "   << RobStat->GetMIPMatrixVal(3,1) << "\n";
00387       cout << "KalmanFilterImu::ProcessENCMeasures() (without noise) ds = "   << RobStat->GetMIPMatrixVal(4,1) << "\n";
00388       cout << "KalmanFilterImu::ProcessENCMeasures() (without noise) dTh = "  << RobStat->GetMIPMatrixVal(5,1) << "\n";
00389       
00390       // Add noise to X measure
00391       tmp = RobStat->GetMIPMatrixVal(1,1);
00392       if(tmp == 0)
00393       {
00394    cout << "KalmanFilterImu::ProcessENCMeasures()  X = 0" << "\n";
00395    srand(time(NULL));
00396    Noise=(drand48() - 0.5)*0.001;
00397    RobStat->SetMIPMatrixVal(1,1,Noise); 
00398    cout << "KalmanFilterImu::ProcessENCMeasures()  X Noise=" << Noise << "\n";
00399       }
00400       else
00401       {
00402    srand(time(NULL));
00403    Noise=(drand48() - 0.5)*0.01*tmp;
00404    tmp = tmp + Noise;
00405    RobStat->SetMIPMatrixVal(1,1,tmp + Noise);
00406    cout << "KalmanFilterImu::ProcessENCMeasures()  X Noise=" << Noise << "\n";
00407       }
00408 
00409       // Add noise to Y measure
00410       tmp = RobStat->GetMIPMatrixVal(2,1);
00411       if(tmp == 0)
00412       {
00413    cout << "KalmanFilterImu::ProcessENCMeasures()  Y = 0" << "\n";
00414    srand(time(NULL));
00415    Noise=(drand48() - 0.5)*0.001;
00416    RobStat->SetMIPMatrixVal(2,1,Noise);
00417    cout << "KalmanFilterImu::ProcessENCMeasures() Y Noise=" << Noise << "\n";
00418       }
00419       else
00420       {
00421    srand(time(NULL));
00422    Noise=(drand48() - 0.5)*0.01*tmp;
00423    tmp = tmp + Noise;
00424    cout << "KalmanFilterImu::ProcessENCMeasures()  Y Noise=" << Noise << "\n";  
00425    RobStat->SetMIPMatrixVal(2,1,tmp + Noise);
00426       }
00427 
00428       // Add noise to theta measure
00429       tmp_1 = RobStat->GetMIPMatrixVal(3,1);
00430       if(tmp_1.dCast2Pi() == 0)
00431       {
00432           cout << "KalmanFilterImu::ProcessENCMeasures()  theta = 0" << "\n";
00433    srand(time(NULL));
00434    Noise_1 = Angle(drand48() - 0.5)*0.01;//Circa mezzo grado di errore
00435    RobStat->SetMIPMatrixVal(3,1,Noise_1.dCast2Pi());
00436    cout << "KalmanFilterImu::ProcessENCMeasures()  _theta Noise=" << Noise << "\n";
00437       }
00438       else
00439       {
00440    srand(time(NULL));
00441    Noise_1 = Angle(drand48() - 0.5)*0.01*tmp_1.dCast2Pi();
00442    tmp_1.operator+=(Noise_1);
00443    RobStat->SetMIPMatrixVal(3,1,tmp_1.dCast2Pi());
00444    cout << "KalmanFilterImu::ProcessENCMeasures()  _theta Noise=" << Noise << "\n";
00445       }
00446 
00447       // Add noise to ds measure
00448       tmp = RobStat->GetMIPMatrixVal(4,1);
00449       if(tmp == 0)
00450       {
00451    cout << "KalmanFilterImu::ProcessENCMeasures()  ds = 0" << "\n";
00452    srand(time(NULL));
00453    Noise=(drand48() - 0.5)*0.001;
00454    RobStat->SetMIPMatrixVal(4,1,Noise);
00455    cout << "KalmanFilterImu::ProcessENCMeasures()  ds Noise=" << Noise << "\n"; 
00456       }
00457       else
00458       {
00459    srand(time(NULL));
00460    Noise=(drand48() - 0.5)*0.01*tmp;
00461    tmp = tmp + Noise; 
00462    RobStat->SetMIPMatrixVal(4,1,tmp + Noise);
00463           cout << "KalmanFilterImu::ProcessENCMeasures()  ds Noise=" << Noise << "\n"; 
00464       }
00465 
00466       // Add noise to dtheta measure
00467       tmp_1 = RobStat->GetMIPMatrixVal(5,1);
00468       if(tmp_1.dCast2Pi() == 0)
00469       {
00470           cout << "KalmanFilterImu::ProcessENCMeasures()  dtheta = 0" << "\n";
00471    srand(time(NULL));
00472    Noise_1 = Angle(drand48() - 0.5)*0.01;//Circa mezzo grado di errore
00473    RobStat->SetMIPMatrixVal(5,1,Noise_1.dCast2Pi());
00474    cout << "KalmanFilterImu::ProcessENCMeasures()  dtheta Noise=" << Noise << "\n";
00475       }
00476       else
00477       {
00478    srand(time(NULL));
00479    Noise_1 = Angle(drand48() - 0.5)*0.01*tmp_1.dCast2Pi();
00480    tmp_1.operator+=(Noise_1);
00481    RobStat->SetMIPMatrixVal(5,1,tmp_1.dCast2Pi());
00482    cout << "KalmanFilterImu::ProcessENCMeasures()  dtheta Noise=" << Noise << "\n";
00483       }
00484 
00485           cout << "KalmanFilterImu::ProcessENCMeasures() with noise" << "\n"; 
00486       cout << "X = " << RobStat->GetMIPMatrixVal(1,1) << "\n"; 
00487       cout << "Y = " << RobStat->GetMIPMatrixVal(2,1) << "\n"; 
00488       cout << "Theta = " << RobStat->GetMIPMatrixVal(3,1) << "\n";
00489       cout << "ds = " << RobStat->GetMIPMatrixVal(4,1) << "\n";
00490       cout << "dth = " << RobStat->GetMIPMatrixVal(5,1) << "\n";
00491       
00492       meas_speed = RobStat->GetMIPMatrixVal(4,1)/ENC_DeltaTime;// The relative speed of the local reference frame w.r.t the inertial reference frame is zero
00493       meas_turnrate = RobStat->GetMIPMatrixVal(5,1)/ENC_DeltaTime;
00494  
00495       ENC_Meas->SetMIPMatrixVal(1,1,RobStat->GetMIPMatrixVal(1,1));
00496       ENC_Meas->SetMIPMatrixVal(2,1,RobStat->GetMIPMatrixVal(2,1));
00497       ENC_Meas->SetMIPMatrixVal(3,1,RobStat->GetMIPMatrixVal(3,1));
00498       ENC_Meas->SetMIPMatrixVal(4,1,meas_speed);
00499       ENC_Meas->SetMIPMatrixVal(5,1,meas_turnrate);
00500       
00501       cout << "KalmanFilterImu::ProcessENCMeasures() calculated ENC measures." << "\n";
00502       cout << "KalmanFilterImu::ProcessENCMeasures() (with noise) X      = "  << ENC_Meas->GetMIPMatrixVal(1,1) << "\n"; 
00503       cout << "KalmanFilterImu::ProcessENCMeasures() (with noise) Y      = "  << ENC_Meas->GetMIPMatrixVal(2,1) << "\n"; 
00504       cout << "KalmanFilterImu::ProcessENCMeasures() (with noise) Theta  = "  << ENC_Meas->GetMIPMatrixVal(3,1) << "\n";
00505       cout << "KalmanFilterImu::ProcessENCMeasures() (with noise) ds/dt  = "  << ENC_Meas->GetMIPMatrixVal(4,1) << "\n";
00506       cout << "KalmanFilterImu::ProcessENCMeasures() (with noise) dTh/dt = "  << ENC_Meas->GetMIPMatrixVal(5,1) << "\n";
00507 
00508 
00509       cout << "KalmanFilterImu::ProcessENCMeasures() end." << "\n";
00510       
00511       return;
00512   }
00513 
00514 
00515   void ProcessIMUMeasures(Acceleration3D &acc, Acceleration3D &gyro, Orientation3D &magn)
00516   {
00517       Decimal   Noise_x;
00518       Decimal   Noise_y;
00519       Decimal   Noise_z;
00520       
00521       MIPMatrix *acc_Iner;//Accelerometer measures in the Inertial Reference Frame
00522       MIPMatrix *gyro_Iner;//Gyro measures in the Inertial Reference Frame
00523       MIPMatrix *magn_Iner;//Magnetometer measures in the Inertial Reference Frame
00524 
00525       MIPMatrix *RotLoc2Iner;//Rotation matrix from local reference frame to inertial reference frame
00526       MIPMatrix *RotIner2Loc;//Rotation matrix from inertial reference frame to local reference frame
00527       
00528       cout << "KalmanFilterImu::ProcessIMUMeasures() begin." << "\n";
00529       cout << "KalmanFilterImu::ProcessIMUMeasures() Accelerometer measures with noise (Inertial Reference Frame)." << "\n";
00530       cout << "Acc x=" << acc.x() << ", Acc y=" << acc.y() << ", Acc z=" << acc.z() << "\n";
00531       cout << "KalmanFilterImu::ProcessIMUMeasures() Gyro measures with noise (Inertial Reference Frame)." << "\n";
00532       cout << "Gyro x=" << gyro.x() << ", Gyro y=" << gyro.y() << ", Gyro z=" << gyro.z() << "\n";
00533       cout << "KalmanFilterImu::ProcessIMUMeasures() magnetometer measures with noise (Inertial Reference Frame)." << "\n";
00534       cout << "Magn roll=" << magn.roll().dCast2Pi() << ", Magn pitch=" << magn.pitch().dCast2Pi() << ", Magn yaw=" << magn.yaw().dCast2Pi() << "\n";
00535       
00536       acc_Iner  = new MIPMatrix(ACC_MEAS_IMU,1,ZERO_MATRIX); //Accelerometer measures in the Inertial Reference Frame
00537       gyro_Iner  = new MIPMatrix(GYRO_MEAS_IMU,1,ZERO_MATRIX); //Gyro measures in the Inertial Reference Frame
00538       magn_Iner  = new MIPMatrix(MAGN_MEAS_IMU,1,ZERO_MATRIX); //Magnetometer measures in the Inertial Reference Frame
00539       acc_Iner->SetMIPMatrixVal(1,1,acc.x());
00540       acc_Iner->SetMIPMatrixVal(2,1,acc.y());
00541       acc_Iner->SetMIPMatrixVal(3,1,acc.z());
00542       gyro_Iner->SetMIPMatrixVal(1,1,gyro.x());
00543       gyro_Iner->SetMIPMatrixVal(2,1,gyro.y());
00544       gyro_Iner->SetMIPMatrixVal(3,1,gyro.z());
00545       magn_Iner->SetMIPMatrixVal(1,1,magn.roll().dCast2Pi());
00546       magn_Iner->SetMIPMatrixVal(2,1,magn.pitch().dCast2Pi());
00547       magn_Iner->SetMIPMatrixVal(3,1,magn.yaw().dCast2Pi());
00548       //cout << "KalmanFilterImu::ProcessIMUMeasures() Accelerometer measures with noise (Inertial Reference Frame)." << "\n";
00549       //cout << "Acc x=" << acc_Iner->GetMIPMatrixVal(1,1) << ", Acc y=" << acc_Iner->GetMIPMatrixVal(2,1) << ", Acc z=" << acc_Iner->GetMIPMatrixVal(3,1) << "\n";
00550       //cout << "KalmanFilterImu::ProcessIMUMeasures() Gyro measures with noise (Inertial Reference Frame)." << "\n";
00551       //cout << "Gyro x=" << gyro_Iner->GetMIPMatrixVal(1,1) << ", Gyro y=" << gyro_Iner->GetMIPMatrixVal(2,1) << ", Gyro z=" << gyro_Iner->GetMIPMatrixVal(3,1) << "\n";
00552       //cout << "KalmanFilterImu::ProcessIMUMeasures() magnetometer measures with noise (Inertial Reference Frame)." << "\n";
00553       //cout << "Magn roll=" << magn_Iner->GetMIPMatrixVal(1,1) << ", Magn pitch=" << magn_Iner->GetMIPMatrixVal(2,1) << ", Magn yaw=" << magn_Iner->GetMIPMatrixVal(3,1) << "\n";
00554       
00555       //Get rotation matrix from local to inertial reference frame
00556       RotLoc2Iner = new MIPMatrix(3,3,ZERO_MATRIX);
00557       RotIner2Loc = new MIPMatrix(3,3,ZERO_MATRIX);
00558          cout << "KalmanFilterImu::ProcessIMUMeasures(), RotTranslMatrix matrix: " << "\n";
00559       (Surf->GetRotTranslMatrix(CurrentRobotPlane))->printMIPMatrix();
00560       RotLoc2Iner->MinorMatrix(*(Surf->GetRotTranslMatrix(CurrentRobotPlane)),4,4);
00561       cout << "KalmanFilterImu::ProcessIMUMeasures(), RotLoc2Iner matrix: " << "\n";
00562       RotLoc2Iner->printMIPMatrix();
00563       
00564       //Calculate rotation matrix from inertial to local reference frame
00565       RotIner2Loc->inv33(*RotLoc2Iner);
00566       cout << "KalmanFilterImu::ProcessIMUMeasures(), RotIner2Loc matrix: " << "\n";
00567       RotIner2Loc->printMIPMatrix();
00568 
00569       //Translate imu measures from inertial to local reference frame
00570       ACC_Meas->mul(*RotIner2Loc, *acc_Iner);
00571       GYRO_Meas->mul(*RotIner2Loc, *gyro_Iner);
00572       MAGN_Meas->mul(*RotIner2Loc, *magn_Iner);
00573           
00574       //IMU measures in the local reference frame.
00575       cout << "KalmanFilterImu::ProcessIMUMeasures() Accelerometer measures with noise (Local Reference Frame)." << "\n";
00576       cout << "Acc x=" << ACC_Meas->GetMIPMatrixVal(1,1) << ", Acc y=" << ACC_Meas->GetMIPMatrixVal(2,1) << ", Acc z=" << ACC_Meas->GetMIPMatrixVal(3,1) << "\n";
00577       cout << "KalmanFilterImu::ProcessIMUMeasures() Gyro measures with noise (Local Reference Frame)." << "\n";
00578       cout << "Gyro x=" << GYRO_Meas->GetMIPMatrixVal(1,1) << ", Gyro y=" << GYRO_Meas->GetMIPMatrixVal(2,1) << ", Gyro z=" << GYRO_Meas->GetMIPMatrixVal(3,1) << "\n";
00579       cout << "KalmanFilterImu::ProcessIMUMeasures() magnetometer measures with noise (Local Reference Frame)." << "\n";
00580       cout << "Magn roll=" << MAGN_Meas->GetMIPMatrixVal(1,1) << ", Magn pitch=" << MAGN_Meas->GetMIPMatrixVal(2,1) << ", Magn yaw=" << MAGN_Meas->GetMIPMatrixVal(3,1) << "\n";
00581       
00582       delete RotLoc2Iner;
00583       delete RotIner2Loc;
00584       delete acc_Iner;
00585       delete gyro_Iner;
00586       delete magn_Iner;
00587       
00588       cout << "KalmanFilterImu::ProcessIMUMeasures() end." << "\n";
00589       return;
00590   }
00591 
00592  
00593   bool processGPSMeasures(Position3D &pos)
00594   {
00595       // pos = Received GPS measures expressed in the Inertial Reference Frame to be translated in the Local Reference Frame.
00596       MIPMatrix *GPS_MeasInert;//GPS measures expressed in the inertial reference frame.
00597       MIPMatrix *GPS_Measlocal;//GPS measures expressed in the local reference frame.
00598       MIPMatrix *InertialToLocal;//Rototranslation matrix from Inertial reference frame to local reference frame.
00599       
00600       MIPMatrix *tmp;
00601 
00602       Decimal x_loc;
00603       Decimal y_loc;
00604       Decimal z_loc;
00605     
00606       GPS_MeasInert = new MIPMatrix(4,1,ZERO_MATRIX);
00607       GPS_Measlocal = new MIPMatrix(4,1,ZERO_MATRIX);
00608       InertialToLocal = new MIPMatrix(4,4,ZERO_MATRIX);
00609       
00610       tmp = new MIPMatrix(4,4,ZERO_MATRIX);
00611       
00612       GPS_MeasInert->SetMIPMatrixVal(1,1,pos.x());
00613       GPS_MeasInert->SetMIPMatrixVal(2,1,pos.y());
00614       GPS_MeasInert->SetMIPMatrixVal(3,1,pos.z());
00615       GPS_MeasInert->SetMIPMatrixVal(4,1,1);
00616       
00617       cout << "KalmanFilterImu:setGPSMeasures(): GPS data in the inertial reference frame:" << endl;
00618       GPS_MeasInert->printMIPMatrix();
00619       cout << "\n";      
00620 
00621   //  cout << "Pause 2 sec" << "\n";
00622       
00623       tmp->operator=(*(Surf->GetRotTranslMatrix(CurrentRobotPlane)));
00624   //  tmp->printMIPMatrix();
00625 
00626       if(InertialToLocal->inv44(*tmp) == 0)
00627       {
00628    cout << "KalmanFilterImu::setGPSMeasures():   Invalid GPS measures." << "\n";
00629    return false;
00630       }
00631       
00632       cout << "KalmanFilterImu::setGPSMeasures(): Rototranslation Matrix from inertial to local reference frame:" << endl;
00633       InertialToLocal->printMIPMatrix();
00634       cout << "\n";
00635       
00636       GPS_Measlocal->mul(*InertialToLocal,*GPS_MeasInert);
00637       
00638       x_loc = GPS_Measlocal->GetMIPMatrixVal(1,1);
00639       y_loc = GPS_Measlocal->GetMIPMatrixVal(2,1);
00640       z_loc = GPS_Measlocal->GetMIPMatrixVal(3,1);
00641       
00642       delete GPS_MeasInert;
00643       delete GPS_Measlocal;
00644       delete InertialToLocal;
00645       
00646       if((z_loc < -EPSILON) || (z_loc > EPSILON))//z_loc != 0. EPSILON=0.01
00647       {
00648    cout << "Wrong data received from GPS. Error too big for z_loc = " << z_loc << " it should be zero!!" << endl;
00649    //return false;
00650       }
00651        
00652       //Write the GPS measure in the input matrix of the Kalman Filter.
00653       GPS_Meas->SetMIPMatrixVal(1,1,x_loc);
00654       GPS_Meas->SetMIPMatrixVal(2,1,y_loc);
00655       cout << "KalmanFilterImu::setGPSMeasures(): GPS data in the local reference frame:" << endl;
00656       GPS_Meas->printMIPMatrix();
00657       cout << "\n";
00658       cout << "KalmanFilterImu::setGPSMeasures(): GPS z_loc= " << z_loc << endl;
00659 
00660       return true;
00661   }
00662 
00663 
00664   void PositionErrorEstimate(Position3D &pos)//This function calculates position error estimate.
00665   {
00666           MIPMatrix *LoclRobPos;//GPS measures expressed in the local reference frame.
00667       MIPMatrix *InerRobPos;//GPS measures expressed in the inertial reference frame.
00668                     
00669       Decimal X_err;
00670       Decimal Y_err;
00671       Decimal Z_err;
00672       
00673       cout << "KalmanFilterImu::PositionErrorEstimate()" << "\n";
00674       LoclRobPos = new MIPMatrix(4,1,ZERO_MATRIX);
00675       InerRobPos = new MIPMatrix(4,1,ZERO_MATRIX);
00676       
00677       //Estimated Robot position in the local reference frame. z_loc = 0; Component (4,1) of the vector is 1 for rototranslation matrix.
00678       LoclRobPos->SetMIPMatrixVal(1,1,State_0->GetMIPMatrixVal(1,1));
00679       LoclRobPos->SetMIPMatrixVal(2,1,State_0->GetMIPMatrixVal(2,1));
00680       LoclRobPos->SetMIPMatrixVal(3,1,0);
00681       LoclRobPos->SetMIPMatrixVal(4,1,1);
00682       
00683       //Estimated Robot position in the inertial reference frame.
00684       InerRobPos->mul(*(Surf->GetRotTranslMatrix(CurrentRobotPlane)),*LoclRobPos);
00685       
00686       //Kalman Filtering position error.
00687       cout << "KalmanFilterImu::PositionErrorEstimate(): Robot position from proxi interface." << "\n";
00688           cout << "X_pos (proxi) = " << pos.x() << "\n";
00689       cout << "Y_pos (proxi) = " << pos.y() << "\n";
00690       cout << "Z_pos (proxi) = " << pos.z() << "\n";
00691 
00692       cout << "KalmanFilterImu::PositionErrorEstimate(): Estimated Robot position." << "\n";
00693           cout << "X_pos (estimated) = " << InerRobPos->GetMIPMatrixVal(1,1) << "\n";
00694       cout << "Y_pos (estimated) = " << InerRobPos->GetMIPMatrixVal(2,1) << "\n";
00695       cout << "Z_pos (estimated) = " << InerRobPos->GetMIPMatrixVal(3,1) << "\n";
00696       
00697           cout << "KalmanFilterImu::PositionErrorEstimate(): Estimated position error." << "\n";
00698       cout << "X_err = " << pos.x()-InerRobPos->GetMIPMatrixVal(1,1) << "\n";
00699       cout << "Y_err = " << pos.y()-InerRobPos->GetMIPMatrixVal(2,1) << "\n";
00700       cout << "Z_err = " << pos.z()-InerRobPos->GetMIPMatrixVal(3,1) << "\n";
00701 
00702       //Predicted Robot position in the local reference frame. z_loc = 0; Component (4,1) of the vector is 1 for rototranslation matrix.
00703       LoclRobPos->SetMIPMatrixVal(1,1,State_1->GetMIPMatrixVal(1,1));
00704       LoclRobPos->SetMIPMatrixVal(2,1,State_1->GetMIPMatrixVal(2,1));
00705       LoclRobPos->SetMIPMatrixVal(3,1,0);
00706       LoclRobPos->SetMIPMatrixVal(4,1,1);
00707       
00708       //Predicted Robot position in the inertial reference frame.
00709       InerRobPos->mul(*(Surf->GetRotTranslMatrix(CurrentRobotPlane)),*LoclRobPos);
00710 
00711       cout << "KalmanFilterImu::PositionErrorEstimate(): Predicted Robot position." << "\n";
00712           cout << "X_pos (Predicted) = " << InerRobPos->GetMIPMatrixVal(1,1) << "\n";
00713       cout << "Y_pos (Predicted) = " << InerRobPos->GetMIPMatrixVal(2,1) << "\n";
00714       cout << "Z_pos (Predicted) = " << InerRobPos->GetMIPMatrixVal(3,1) << "\n";
00715       
00716           cout << "KalmanFilterImu::PositionErrorEstimate(): Predicted position error." << "\n";
00717       cout << "X_err = " << pos.x()-InerRobPos->GetMIPMatrixVal(1,1) << "\n";
00718       cout << "Y_err = " << pos.y()-InerRobPos->GetMIPMatrixVal(2,1) << "\n";
00719       cout << "Z_err = " << pos.z()-InerRobPos->GetMIPMatrixVal(3,1) << "\n";
00720 
00721       return;
00722   }
00723   
00724   
00725   void updateKalmanFilterImu()//Kalman filter algorithm implementation
00726   {
00727           Decimal tmp;
00728    Angle tmp_1;
00729    Decimal c_31;//Rototranslation matrix coefficient A(3,1)
00730    Decimal c_32;//Rototranslation matrix coefficient A(3,2)
00731    Decimal alpha_k;
00732    
00733           cout << "updateKalmanFilterImu() started." << endl;
00734    CycleTime = (ENC_DeltaTime + IMU_DeltaTime)/2;
00735    //Initial conditions already set at Kalman Filter instantiation. (Status prediction initialization and Pp matrix initialization). 
00736    //See EKF constructor. //I
00737    
00738    //cout << "Previous predicted state: " << "\n";
00739    //cout << "x = " << State_1->GetMIPMatrixVal(1,1) << "\n";
00740    //cout << "y = " << State_1->GetMIPMatrixVal(2,1) << "\n";
00741    //cout << "theta = " << State_1->GetMIPMatrixVal(3,1) << "\n";
00742    //cout << "Speed = " << State_1->GetMIPMatrixVal(4,1) << "\n";
00743    //cout << "Ang rate = " << State_1->GetMIPMatrixVal(5,1) << "\n";
00744  
00745    //cout << "Previous estimated state: " << "\n";
00746    //cout << "x = " << State_0->GetMIPMatrixVal(1,1) << "\n";
00747    //cout << "y = " << State_0->GetMIPMatrixVal(2,1) << "\n";
00748    //cout << "theta = " << State_0->GetMIPMatrixVal(3,1) << "\n";
00749    //cout << "Speed = " << State_0->GetMIPMatrixVal(4,1) << "\n";
00750    //cout << "Ang rate = " << State_0->GetMIPMatrixVal(5,1) << "\n";
00751    
00752 //    if(GPS_MeasAvail == true)
00753 //    {
00754 //    cout << "updateKalmanFilterImu() - GPS measure available." << endl;
00755    
00756    outPred();//II: This function calculates the prediction of the output Y(k+1|k). 
00757    
00758    //Matrix_C();//III: Since this is a constant matrix it is calculated only once at EKF initialization.
00759    
00760    matrix_K();//IV: This function calculates the Kalman gain matrix K(k+1). 
00761         
00762    matrix_P();//V: This function calculates the matrix P(k+1).
00763         
00764    estimateRobotStatus();//VI: This function estimates the matrix X(k+1,k+1).
00765    
00766    calculateStatusPrediction();//VIII: This function calculates the prediction of the status of the robot X(k+1|k)=f(-)
00767    
00768    calculate_A();//IX: This function calculates the Jacobian matrix of f() in X(k,k).
00769    
00770    calculatePp();//X: This function calculates the Pp(k+1) matrix.      
00771 
00772    updRobotPlane();//This function calculates the plane on which the robot is moving.
00773    
00774    unsetGPSAvailability();
00775 /*    }
00776     else
00777     {
00778       //GPS measures not available, execute odometry integration to predict the new robot status X(k+1,k) //VIII
00779        
00780       cout << "updateKalmanFilterImu() - GPS measure not available." << endl;
00781       //Calculates alfa(k) coefficient. See tesis pag 67.
00782       c_31 = Surf->GetRotTranslMatrixElem(CurrentRobotPlane, 3, 1);
00783       c_32 = Surf->GetRotTranslMatrixElem(CurrentRobotPlane, 3, 2);
00784        
00785       cout << "KalmanFilterImu::updateKalmanFilterImu(), CurrentRobotPlane: " << CurrentRobotPlane 
00786            << "; Rototranslation matrix coefficient A(3,1): "
00787     << c_31 << "; Rototranslation matrix coefficient A(3,2): " << c_32 << endl;
00788        
00789       //The only component of the linear acceleration of the robot is the one directed along the positive Local Reference Frame X axis. 
00790       //The other two components are compensated by the friction force. So the component to be considered is: ACC_Meas->GetMIPMatrixVal(1,1).
00791       //alpha_k = GRAV*(c_31*cos(State_0->GetMIPMatrixVal(3,1)) + c_32*sin(State_0->GetMIPMatrixVal(3,1)) + Force/RobotMass);//To put IMU accel measure
00792       alpha_k = (c_31*cos(State_0->GetMIPMatrixVal(3,1)) + c_32*sin(State_0->GetMIPMatrixVal(3,1))*GRAV + ACC_Meas->GetMIPMatrixVal(1,1));
00793 
00794       //x1 = x1_0 + T*v*cos(th)
00795       State_1->SetMIPMatrixVal(1, 1, State_1->GetMIPMatrixVal(1,1) + CycleTime*State_1->GetMIPMatrixVal(4,1)*cos(State_1->GetMIPMatrixVal(3,1)));
00796 
00797       //y1 = y1_0 + T*v*sin(th)
00798       State_1->SetMIPMatrixVal(2, 1, State_1->GetMIPMatrixVal(2,1) + CycleTime*State_1->GetMIPMatrixVal(4,1)*sin(State_1->GetMIPMatrixVal(3,1)));
00799 
00800       //th1 = th1_0 + T*w    
00801       State_1->SetMIPMatrixVal(3, 1, Angle(State_1->GetMIPMatrixVal(3,1) + CycleTime*State_1->GetMIPMatrixVal(5,1)).dCast());
00802 
00803       //v1 = v1_0 + T*alpha_k     
00804       State_1->SetMIPMatrixVal(4, 1, State_1->GetMIPMatrixVal(4,1) + CycleTime*alpha_k);
00805 
00806       //w1 = w1_0 + T*Torque/RobotMoI
00807       //The only component of the angular acceleration of the robot is the one directed along the positive Local Reference Frame Z axis. 
00808       //The other two components are compensated by the friction force of the plane.So the component to be considered is: GYRO_Meas->GetMIPMatrixVal(3,1).
00809       //State_1->SetMIPMatrixVal(5, 1, State_1->GetMIPMatrixVal(5,1) + CycleTime*Torque/RobotMoI);//To put IMU gyro measure  
00810       State_1->SetMIPMatrixVal(5, 1, State_1->GetMIPMatrixVal(5,1) + CycleTime*GYRO_Meas->GetMIPMatrixVal(3,1));
00811    }  */ 
00812    
00813    cout << "Predicted state: " << "\n";
00814    cout << "x = " << State_1->GetMIPMatrixVal(1,1) << "\n";
00815    cout << "y = " << State_1->GetMIPMatrixVal(2,1) << "\n";
00816    cout << "theta = " << State_1->GetMIPMatrixVal(3,1) << "\n";
00817    cout << "Speed = " << State_1->GetMIPMatrixVal(4,1) << "\n";
00818    cout << "Ang rate = " << State_1->GetMIPMatrixVal(5,1) << "\n";
00819    
00820    cout << "Estimated state: " << "\n";
00821    cout << "x = " << State_0->GetMIPMatrixVal(1,1) << "\n";
00822    cout << "y = " << State_0->GetMIPMatrixVal(2,1) << "\n";
00823    cout << "theta = " << State_0->GetMIPMatrixVal(3,1) << "\n";
00824    cout << "Speed = " << State_0->GetMIPMatrixVal(4,1) << "\n";
00825    cout << "Ang rate = " << State_0->GetMIPMatrixVal(5,1) << "\n";
00826    
00827    return;
00828   }
00829 };
00830 #endif
00831 
00832 
00833 
00834 

Generated on Mon Feb 20 07:01:06 2017 for MIP by  doxygen 1.5.6