Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages | Examples

QuaternionEKFObserver.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file QuaternionEKFObserver.cpp
00003  *  \brief Estimation of the Quaternion and angular rates. Based on the Multiplicatimve Quaternion
00004  *              Formulation in "Optimal Estimation of Dynamic Systems" by Crassidis and Junkins. 
00005  *  \author     $Author: jayhawk_hokie $
00006  *  \version $Revision: 1.9 $
00007  *  \date    $Date: 2007/08/31 16:08:01 $
00008 *//////////////////////////////////////////////////////////////////////////////////////////////////
00009 /*
00010 */
00011 //////////////////////////////////////////////////////////////////////////////////////////////////
00012 
00013 #include"QuaternionEKFObserver.h"
00014 
00015 
00016 QuaternionEKFObserver::QuaternionEKFObserver( )
00017 { }
00018 
00019 QuaternionEKFObserver::QuaternionEKFObserver( TiXmlHandle handle, Whorl* ptr_whorl )
00020 {
00021         m_whorl = ptr_whorl;
00022 
00023         pthread_mutex_init( &m_Mutex, NULL );
00024 
00025         m_accelerometerInertial.initialize(3);
00026         m_magnetometerInertial.initialize(3);
00027         m_angularRates.initialize(3);
00028         m_measurementsBody.initialize(6);
00029         m_rsensor.initialize(3);
00030         m_R.initialize(6,6);
00031         
00032         m_outputState.initialize(7);
00033         m_previousMeasurement.initialize(6);
00034         //m_previousMeasurement.initialize(3);
00035         
00036         m_currentMeasurementTime=0;
00037         m_previousMeasurementTime=0;
00038         m_stepTime=0;
00039         m_durationTime=0;
00040         m_sigmav=0;
00041         m_sigmau=0;
00042         m_P0a=0;
00043         m_P0b=0;
00044         
00045         m_BM.initialize(3);
00046         
00047         m_K.initialize(6,6);
00048         m_qminus.initialize(4);
00049         m_qplus.initialize(4);
00050         m_H.initialize(6,6);
00051         m_h.initialize(6);
00052         m_angularRatehat.initialize(3);
00053         m_Pminus.initialize(6,6);
00054         m_Pplus.initialize(6,6);
00055         m_phi.initialize(6,6);
00056 
00057         m_initialRange = 1;
00058         m_finalRange = 6;
00059         
00060         m_magnetometerCondition = 0;
00061         
00062         m_exitCondition = 1;
00063 
00064         Parse( handle );
00065         Initialize( );
00066 
00067 }
00068 
00069 QuaternionEKFObserver::~QuaternionEKFObserver( )
00070 { 
00071 
00072         cerr << "Stop Quaternion EKF Routine" << endl;
00073         StopEKF( );
00074 
00075         //delete m_previousMeasurement;
00076         
00077         // Deallocating memory from mutex
00078         pthread_mutex_destroy( &m_Mutex );
00079 
00080 }
00081 
00082 int QuaternionEKFObserver::Initialize( )
00083 {
00084 
00085         // Start EKF Routine
00086         cerr << "Start Quaternion EKF Routine" << endl;
00087         StartEKF( );
00088         usleep( 500000 );
00089 
00090 
00091         return( 0 );
00092 }
00093 
00094 /*! \brief Parse inertial measurement vectors from configuration file
00095         * @param handle XML handle with current whorl as starting node
00096         */
00097 void QuaternionEKFObserver::Parse( TiXmlHandle handle )
00098 {
00099 
00100         int response;
00101 
00102         // create handles with magnetometer and accelerometer nodes as starting points
00103         TiXmlHandle accelElement =  handle.FirstChild( m_whorl->GetSimulatorName( ) ).FirstChild("HARDWARE_PROPERTIES").FirstChild("DMU_ACCELEROMETER");
00104         TiXmlHandle magElement = handle.FirstChild( m_whorl->GetSimulatorName( ) ).FirstChild("HARDWARE_PROPERTIES").FirstChild("MAGNETOMETER");
00105 
00106         // get magnetometer inertial vector and normalize
00107         response = magElement.Child("INERTIAL_VECTOR", 0).Element() ->  QueryDoubleAttribute( "valueX", &(m_magnetometerInertial)(1) );
00108         checkResponse(response);
00109         response = magElement.Child("INERTIAL_VECTOR", 0).Element() ->  QueryDoubleAttribute( "valueY", &(m_magnetometerInertial)(2) );
00110         checkResponse(response);
00111         response = magElement.Child("INERTIAL_VECTOR", 0).Element() ->  QueryDoubleAttribute( "valueZ", &(m_magnetometerInertial)(3) );
00112         checkResponse(response);
00113 
00114         // Normalize magnetmeter inertial vector
00115         normalize( m_magnetometerInertial );
00116 
00117         // get accelerometer inertial vector and normalize
00118         response = accelElement.Child("INERTIAL_VECTOR", 0).Element() -> QueryDoubleAttribute( "valueX", &(m_accelerometerInertial)(1) );
00119         checkResponse(response);
00120         response = accelElement.Child("INERTIAL_VECTOR", 0).Element() -> QueryDoubleAttribute( "valueY", &(m_accelerometerInertial)(2) );
00121         checkResponse(response);
00122         response = accelElement.Child("INERTIAL_VECTOR", 0).Element() -> QueryDoubleAttribute( "valueZ", &(m_accelerometerInertial)(3) );
00123         checkResponse(response);
00124 
00125         // Normalize accelerometer inertial vector
00126         normalize( m_accelerometerInertial ); // [rad/s^2]
00127 
00128         // get motion pak sensor radius
00129         for (int i=0;i<3;i++)
00130         {
00131                 response = handle.FirstChild( m_whorl->GetSimulatorName( ) ).FirstChild("PHYSICAL_PROPERTIES").FirstChild("SENSOR_RADIUS").Child("VECTOR",i)
00132                         .Element() -> QueryDoubleAttribute("value",&(m_rsensor)(i+1));
00133                 checkResponse(response);
00134         }
00135 
00136         ////////////////
00137         ///////////////
00138 
00139         // This section sets the measurement covariance based on the variance for each sensor
00140         // Future move to xml
00141         (m_R)(1,1) = 2.324*1e7; // magnetometer x (counts)
00142         (m_R)(2,2) = 3.226*1e7; // magnetometer y (counts)
00143         (m_R)(3,3) = 2.394*1e7; // magnetometer z (counts)
00144         (m_R)(4,4) = 0.000106; // accelerometer x (m/s^2)
00145         (m_R)(5,5) = 0.000105; // accelerometer y (m/s^2)
00146         (m_R)(6,6) = 0.000102; // accelerometer z (m/s^2)
00147 
00148         // move to xml
00149         m_sigmav = sqrt( 0.00004 ); // rate gyro variance
00150         m_sigmau = 2e-5; // rate gyro bias variance
00151 
00152         // variables to use in covariance initialization
00153         // move to xml
00154         m_P0a= 8.46e-6;
00155         m_P0b = 9.4018e-13;
00156         
00157         // Bias initial vector
00158         // Future move to xml
00159         (m_BM)(1) = 0;
00160         (m_BM)(2) = 0;
00161         (m_BM)(3) = 0;
00162         
00163         /////////////////
00164         ////////////////
00165 }
00166 
00167 void QuaternionEKFObserver::StartEKF( )
00168 {
00169         //pthread_create( &m_EKFThreadID, NULL, QuaternionEKF, (void*) this );
00170         pthread_create( &m_EKFThreadID, NULL, QuaternionEKFOriginal, (void*) this );
00171 }
00172 
00173 void* QuaternionEKF( void* arg )
00174 {
00175         QuaternionEKFObserver *EKFObserver = (QuaternionEKFObserver*) arg;
00176         // Initialize Filter Parameters
00177         EKFObserver->InitializeFilter( );
00178 
00179         // Get Current Measurement
00180         EKFObserver->GetCurrentMeasurements( );
00181         
00182         EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime; 
00183         
00184         EKFObserver->m_stepTime = EKFObserver->m_currentMeasurementTime - EKFObserver->m_previousMeasurementTime; 
00185 
00186         EKFObserver->m_durationTime += EKFObserver->m_stepTime.GetSeconds( );
00187 
00188         // Get initial Guess from Triad Algorithm       
00189         EKFObserver->GetInitialGuessTriad( );
00190         
00191         // Murrell's Algorithm for computationally efficient attitude estimation
00192         EKFObserver->MurrellAlgorithm( );
00193 
00194         pthread_testcancel( );
00195 
00196         EKFObserver->m_previousMeasurement = EKFObserver->m_measurementsBody;
00197 
00198         int exit = 1;
00199         
00200         while( exit )
00201         {
00202                 usleep( 100000 );
00203                 
00204                 pthread_testcancel( );
00205 
00206                 // Get Current Measurement
00207                 EKFObserver->GetCurrentMeasurements( );
00208 
00209                 // Check Measurement
00210                 EKFObserver->CheckMagnetometerMeasurement( );   
00211                 
00212                 EKFObserver->m_stepTime = EKFObserver->m_currentMeasurementTime - EKFObserver->m_previousMeasurementTime; 
00213 
00214                 EKFObserver->m_durationTime += EKFObserver->m_stepTime.GetSeconds( );
00215 
00216                 pthread_testcancel( );
00217 
00218                 // Murrell's Algorithm for computationally efficient attitude estimation
00219                 EKFObserver->MurrellAlgorithm( );
00220 
00221                 pthread_testcancel( );
00222         
00223                 //EKFObserver->MeasurementUpdate( );
00224 
00225                 //pthread_testcancel( );
00226 
00227                 EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime; // reset previous time measurement
00228                 
00229                 pthread_testcancel( );
00230                 
00231                 pthread_mutex_lock(&EKFObserver->m_Mutex); 
00232                         exit = EKFObserver->m_exitCondition;
00233                 pthread_mutex_unlock(&EKFObserver->m_Mutex); 
00234         }
00235 
00236         return( arg );
00237 }
00238 
00239 void QuaternionEKFObserver::StopEKF( )
00240 {
00241         // Lock output state vector
00242         pthread_mutex_lock(&m_Mutex);
00243                 m_exitCondition = 0;
00244         // Unlock output state vector
00245         pthread_mutex_unlock(&m_Mutex);
00246         
00247         pthread_join( m_EKFThreadID, NULL );
00248 
00249         return;
00250 }
00251 
00252 void QuaternionEKFObserver::InitializeFilter( )
00253 {
00254 
00255         // covariance initialization (diagonal)
00256         (m_Pminus)(1,1) = m_P0a;
00257                 (m_Pminus)(2,2) = m_P0a;
00258                         (m_Pminus)(3,3) = m_P0a;
00259                                 (m_Pminus)(4,4) = m_P0b;
00260                                         (m_Pminus)(5,5) = m_P0b;
00261                                                 (m_Pminus)(6,6) = m_P0b;
00262 
00263         return;
00264 }
00265 
00266 void QuaternionEKFObserver::GetCurrentMeasurements( )
00267 {
00268         // vector measurements for both time update and measurement update steps are taken here
00269         (m_measurementsBody)( _(1,3) ) = m_whorl->GetMagnetometer() -> GetVectorMeasurement( );
00270         
00271         string axis;
00272         for( int i =0; i < 3; i++ )
00273         {
00274                 // set up a string to designate axis
00275                 switch( i ) 
00276                 {
00277                         case 0:
00278                                 axis = "X";
00279                                 break;
00280                         case 1:
00281                                 axis = "Y";
00282                                 break;
00283                         case 2:
00284                                 axis = "Z";
00285                                 break;
00286                         default:
00287                                 break;
00288                 }       
00289 
00290                 /* Rate Gyros */
00291                 (m_angularRates)(i+1) = m_whorl->GetRateGyro( "RATE_GYRO_" + axis ) -> GetMeasurement().GetAsDouble();
00292                 /* Accelerometers */
00293                 (m_measurementsBody)(i+4) = m_whorl->GetAccelerometer( "ACC_" + axis ) -> GetMeasurement().GetAsDouble();
00294         } 
00295 
00296         m_currentMeasurementTime = Now( );
00297         
00298         return;
00299 }
00300 
00301 void QuaternionEKFObserver::CheckMagnetometerMeasurement( )
00302 {
00303         /* Check Magnetometer vector. If bad ignore measurement */
00304         double condition = norm2( (m_previousMeasurement)( _(1,3) ) ) - norm2( (m_measurementsBody)( _(1,3) ) );
00305         if ( fabs(condition) > 50 )
00306         {
00307                 // ignore measurement
00308                 m_magnetometerCondition = 1;
00309                 m_initialRange = 4;
00310                 m_finalRange = 6;
00311 
00312         }
00313         else
00314         { // update previous measurement
00315                 m_magnetometerCondition = 0;
00316                 m_previousMeasurement = m_measurementsBody; // good measurement
00317         }
00318         return;
00319 }
00320 
00321 void QuaternionEKFObserver::GetInitialGuessTriad( )
00322 {
00323         // use Triad to get initial guess
00324         triadObserver initialGuess;
00325         initialGuess.SetMagnetometerBodyVector( (m_measurementsBody)( _(1,3)) );
00326         initialGuess.SetMagnetometerInertialVector( m_magnetometerInertial );
00327         initialGuess.SetAccelerometerBodyVector( (m_measurementsBody)( _(4,6)) );
00328         initialGuess.SetAccelerometerInertialVector( m_accelerometerInertial );
00329         
00330         DirectionCosineMatrix attitudeMatrix = initialGuess.GetAttitude( );
00331         m_qminus = attitudeMatrix.GetQuaternion( );
00332 
00333         return;
00334 }       
00335 
00336 void QuaternionEKFObserver::MurrellAlgorithm( )
00337 {
00338         // set estimated attitude DCM (3x3)
00339         Quaternion qminus( m_qminus );
00340         Matrix estimatedAttitude(3,3);
00341         estimatedAttitude = DirectionCosineMatrix( qminus );
00342 
00343         // set dXhatMinus to zero (6x1)
00344         Vector dXhatMinus(6);
00345 
00346         // set dXhatPlus to zero (6x1)
00347         Vector dXhatPlus(6);
00348 
00349         // Magnetometer Measurement
00350         if( m_magnetometerCondition )
00351         { cerr << "no magnetomter measurement" << endl; /* ignore mag measurement */ }
00352         else
00353         {
00354                 dXhatPlus = SingleMeasurement( m_magnetometerInertial, (m_measurementsBody)(_(1,3)), dXhatMinus, estimatedAttitude, (m_R)( _(1,3), _(1,3) ) );
00355         }
00356 
00357         // Update       
00358         dXhatMinus = dXhatPlus;
00359         (m_Pminus) = (m_Pplus);
00360         // Accelerometer Measurement
00361         dXhatPlus = SingleMeasurement( m_accelerometerInertial, (m_measurementsBody)(_(4,6)), dXhatMinus, estimatedAttitude, (m_R)( _(4,6), _(4,6) ) );
00362 
00363         // Update State Transition Matrix and Covariance Matrix
00364         StateCovarianceUpdate( dXhatPlus );
00365 
00366         return; 
00367 }       
00368 
00369 Vector QuaternionEKFObserver::SingleMeasurement( Vector _inertial, Vector _measurement, Vector _dXhatMinus, Matrix _estimatedAttitude, Matrix _sensorNoise )
00370 {
00371         // Estimate Output (3x1)
00372         Vector h(3);
00373         h( _(1,3) ) = _estimatedAttitude * (_inertial);
00374         // Determine Sensitivity matrix (3x6)
00375         Matrix H(3,6);
00376         H( _(1,3),_(1,3) ) = skew( h ); 
00377 
00378         // Determine Gain Matrix (6x3)  
00379         Matrix K(6,3);
00380         Matrix _temp(3,3);
00381         _temp = ( H*(m_Pminus)*~(H) + _sensorNoise );
00382         Matrix denominator(3,3);
00383         denominator = matrixInv3x3( _temp ) ; // denominator for the kalman gain (K)
00384         K = (m_Pminus)*~(H)*denominator;
00385 
00386         // Update Covariance ( 6x6 )
00387         m_Pplus = ( eye(6) - K*H )*(m_Pminus);
00388         //m_Pplus = ( CAMdoubleMatrix::identity(6) - K*H )*(m_Pminus);
00389 
00390         // Determine Residual (3x1)
00391         Vector E(3);
00392         E = ( _measurement - h );
00393 
00394         // Update State (6x1)
00395         Vector dXhatPlus(6);
00396         dXhatPlus = _dXhatMinus + K*( E-H*_dXhatMinus );
00397         
00398         return ( dXhatPlus );
00399 }
00400 
00401         
00402 // update error covariance and state
00403 void QuaternionEKFObserver::StateCovarianceUpdate( Vector dXhatPlus )
00404 {
00405         Vector dAlphaPlus(3);
00406         dAlphaPlus = dXhatPlus( _(1,3) );
00407         Vector dBetaPlus(3);
00408         dBetaPlus = dXhatPlus( _(4,6) );
00409 
00410         // Determine qplus (output state)
00411         Matrix Xi( 4,3 );
00412         Xi( _(1,3), _ ) = ( (m_qminus)(4)*CAMdoubleMatrix::identity(3)+skew ( (m_qminus)( _(1,3) ) ) );
00413         Xi(4,_) = -(~((m_qminus)(_(1,3))));
00414         m_qplus = ( m_qminus + 0.5*Xi*dAlphaPlus );
00415         normalize( m_qplus ); // do a forced normalization
00416 
00417         // set bias
00418         Vector biasPlus(3);
00419         biasPlus = m_BM + dBetaPlus;
00420         m_BM = biasPlus;
00421 
00422         // get new angular rates (output state)
00423         m_angularRatehat = m_angularRates - biasPlus;
00424 
00425         // Lock output state vector
00426         pthread_mutex_lock(&m_Mutex);
00427 
00428                 // set output state vector
00429                 (m_outputState)( _(1,4) ) = m_qplus;
00430                 (m_outputState)( _(5,7) ) = m_angularRates;
00431                 //(m_outputState)( _(5,7) ) = m_angularRatehat; // might be returning bad result
00432 
00433         // Unlock output state vector
00434         pthread_mutex_unlock(&m_Mutex);
00435         
00436         // Process noise matrix
00437         Matrix Q(6,6);
00438         Q(_(1,3),_(1,3)) = ( pow( m_sigmav, 2 )*m_stepTime.GetSeconds( ) + (1/3) *
00439                 pow( m_sigmau, 2 ) * pow( m_stepTime.GetSeconds( ),3 ) )*CAMdoubleMatrix::identity(3);
00440         Q(_(1,3),_(4,6)) = (0.5 * pow( m_sigmau, 2 ) *
00441                 pow( m_stepTime.GetSeconds( ), 2 ) ) * CAMdoubleMatrix::identity(3);
00442         Q(_(4,6),_(1,3)) = (0.5 * pow( m_sigmau, 2 ) *
00443                 pow( m_stepTime.GetSeconds( ),2 ))*CAMdoubleMatrix::identity(3);
00444         Q(_(4,6),_(4,6)) = (pow( m_sigmau, 2 )*m_stepTime.GetSeconds( ))*CAMdoubleMatrix::identity(3);
00445 
00446         StateTransitionMatrix( );
00447 
00448         Matrix Gm(6,6);
00449         Gm(_(1,3),_(1,3)) = -CAMdoubleMatrix::identity(3);
00450         Gm(_(4,6),_(4,6)) = CAMdoubleMatrix::identity(3);
00451         // propagate Pminus
00452         m_Pminus = m_phi*(m_Pplus)*~(m_phi) + Gm*Q*~Gm;
00453                 
00454         return;
00455 }
00456 
00457 // State Transition Matrix
00458 void QuaternionEKFObserver::StateTransitionMatrix( )
00459 {
00460         Matrix phi11(3,3);
00461         Matrix phi12(3,3);
00462         Matrix phi21(3,3);
00463         Matrix phi22(3,3);
00464 
00465         double angratemag = norm2( m_angularRatehat );
00466         
00467         if (angratemag == 0) // angular rates = 0
00468         {
00469                 phi11 = CAMdoubleMatrix::identity(3);
00470                 phi12 = -CAMdoubleMatrix::identity(3)*m_stepTime.GetSeconds( );
00471                 phi22 = CAMdoubleMatrix::identity(3);
00472 
00473                 (m_qminus) = (m_qplus); // state does not change
00474         }
00475         else // rates not equal to zero
00476         {
00477                 Matrix omegaBar(4,4);
00478 
00479                 Vector psiPlus(3);
00480                 psiPlus = sin( 0.5*angratemag*m_stepTime.GetSeconds( ) ) * (m_angularRatehat) /
00481                     angratemag;
00482                         
00483                 omegaBar(_(1,3),_(1,3)) = cos( 0.5*angratemag*m_stepTime.GetSeconds( ) ) *
00484                                 CAMdoubleMatrix::identity(3) - skew(psiPlus);
00485                 omegaBar(_(1,3),4) = psiPlus;
00486                 omegaBar(4, _(1,3)) = -~psiPlus;
00487                 omegaBar(4,4) = cos( 0.5*angratemag*(m_stepTime.GetSeconds( ) ) );
00488                         
00489                 // propagate qminus
00490                 m_qminus = omegaBar*(m_qplus);
00491 
00492                 phi11 = CAMdoubleMatrix::identity(3) - skew( m_angularRatehat ) * sin( angratemag*m_stepTime.GetSeconds( ) ) /
00493                                 angratemag+
00494                                 skew( m_angularRatehat ) * skew( m_angularRatehat ) *
00495                                 ( 1.0 - cos( angratemag*m_stepTime.GetSeconds( ) )) /
00496                                 pow( angratemag, 2 );
00497 
00498                 phi12 = skew( m_angularRatehat ) * (1.0 - cos( angratemag*m_stepTime.GetSeconds( ))) /
00499                                 pow( angratemag, 2 ) - CAMdoubleMatrix::identity(3)*m_stepTime.GetSeconds( ) -
00500                                 skew( m_angularRatehat ) * skew( m_angularRatehat ) *
00501                                 ( angratemag*m_stepTime.GetSeconds( ) -
00502                                 sin( angratemag*m_stepTime.GetSeconds( ) )) /
00503                                 pow( angratemag,3);
00504 
00505                 phi22 = CAMdoubleMatrix::identity(3);
00506 
00507         }
00508 
00509         // Set State Transition Matrix
00510         (m_phi)( _(1,3),_(1,3) ) = phi11;       (m_phi)( _(1,3),_(4,6) ) = phi12;
00511         (m_phi)( _(4,6),_(1,3) ) = phi21;       (m_phi)( _(4,6),_(4,6) ) = phi22;
00512 
00513         return;
00514 }                
00515         
00516 int QuaternionEKFObserver::Run( )
00517 {
00518 
00519         // Lock output state vector
00520         pthread_mutex_lock(&m_Mutex);
00521                 
00522                 m_whorl->SetState( m_outputState );
00523         
00524         // Unlock output state vector
00525         pthread_mutex_unlock(&m_Mutex);
00526 
00527         return( 0 );
00528 }
00529 
00530 //////////////
00531 /////////////
00532 /////////////
00533 
00534 void* QuaternionEKFOriginal( void* arg )
00535 {
00536         QuaternionEKFObserver *EKFObserver = (QuaternionEKFObserver*) arg;
00537 
00538         //cout << "Set State: " << pthread_setcancelstate(PTHREAD_CANCEL_ENABLE,NULL) << endl;
00539         //cout << "Set Type: " << pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,NULL) << endl;
00540 
00541         // Initialize Filter Parameters
00542         EKFObserver->InitializeFilter( );
00543 
00544         // Get Current Measurement
00545         EKFObserver->GetCurrentMeasurements( );
00546 
00547         EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime;
00548 
00549         EKFObserver->m_stepTime = EKFObserver->m_currentMeasurementTime - EKFObserver->m_previousMeasurementTime;
00550 
00551         EKFObserver->m_durationTime += EKFObserver->m_stepTime.GetSeconds( );
00552 
00553         // Get initial Guess from Triad Algorithm
00554         EKFObserver->GetInitialGuessTriad( );
00555 
00556         EKFObserver->MeasurementUpdate( );
00557 
00558         // Update
00559         EKFObserver->StateCovarianceUpdate( );
00560 
00561         pthread_testcancel( );
00562 
00563         EKFObserver->m_previousMeasurement = EKFObserver->m_measurementsBody;
00564 
00565         int exit = 1;
00566 
00567         while( exit )
00568         {
00569                 usleep( 100000 );
00570 
00571                 pthread_testcancel( );
00572 
00573                 // Get Current Measurement
00574                 EKFObserver->GetCurrentMeasurements( );
00575 
00576                 EKFObserver->CheckMagnetometerMeasurement( );
00577 
00578                 pthread_testcancel( );
00579 
00580                 EKFObserver->m_stepTime = EKFObserver->m_currentMeasurementTime - EKFObserver->m_previousMeasurementTime;
00581 
00582                 EKFObserver->m_durationTime += EKFObserver->m_stepTime.GetSeconds( );
00583 
00584                 pthread_testcancel( );
00585 
00586                 EKFObserver->MeasurementUpdate( );
00587 
00588                 // Update State Transition Matrix and Covariance Matrix
00589                 EKFObserver->StateCovarianceUpdate( );
00590 
00591                 pthread_testcancel( );
00592 
00593                 EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime; // reset previous time measurement
00594 
00595                 pthread_testcancel( );
00596 
00597                 pthread_mutex_lock(&EKFObserver->m_Mutex);
00598                         exit = EKFObserver->m_exitCondition;
00599                 pthread_mutex_unlock(&EKFObserver->m_Mutex);
00600         }
00601 
00602         return( arg );
00603 }
00604 
00605 // update error covariance and state for original method
00606 void QuaternionEKFObserver::StateCovarianceUpdate( )
00607 {
00608         m_Pplus = ( CAMdoubleMatrix::identity(6) - (m_K)( _, _(m_initialRange,m_finalRange) )*(m_H)( _(m_initialRange,m_finalRange), _ ) )*(m_Pminus);
00609         Vector dXhatPlus(6);
00610         dXhatPlus = (m_K)( _, _(m_initialRange,m_finalRange) )*( (m_measurementsBody)( _(m_initialRange,m_finalRange) ) - (m_h)( _(m_initialRange,m_finalRange) ) );
00611         Vector dAlphaPlus(3);
00612         dAlphaPlus = dXhatPlus( _(1,3) );
00613         Vector dBetaPlus(3); 
00614         dBetaPlus = dXhatPlus( _(4,6) );
00615 
00616         // Determine qplus (output state)
00617         Matrix Xi( 4,3 );
00618         Xi( _(1,3), _ ) = ( (m_qminus)(4)*CAMdoubleMatrix::identity(3)+skew ( (m_qminus)( _(1,3) ) ) );
00619         Xi(4,_) = -(~((m_qminus)(_(1,3))));
00620         m_qplus = ( m_qminus + 0.5*Xi*dAlphaPlus );
00621         normalize( m_qplus ); // do a forced normalization
00622 
00623         // set bias
00624         Vector biasPlus(3);
00625         biasPlus = m_BM + dBetaPlus;
00626         m_BM = biasPlus;
00627 
00628         // get new angular rates (output state)
00629         m_angularRatehat = m_angularRates - biasPlus;
00630 
00631         // Lock output state vector
00632         pthread_mutex_lock(&m_Mutex);
00633 
00634                 // set output state vector
00635                 (m_outputState)( _(1,4) ) = m_qplus;
00636                 (m_outputState)( _(5,7) ) = m_angularRates;
00637                 //(m_outputState)( _(5,7) ) = m_angularRatehat; // might have problem
00638 
00639         // Unlock output state vector
00640         pthread_mutex_unlock(&m_Mutex);
00641 
00642         // Process noise matrix
00643         Matrix Q(6,6);
00644         Q(_(1,3),_(1,3)) = ( pow( m_sigmav, 2 )*m_stepTime.GetSeconds( ) + (1/3) *
00645                 pow( m_sigmau, 2 ) * pow( m_stepTime.GetSeconds( ),3 ) )*CAMdoubleMatrix::identity(3);
00646         Q(_(1,3),_(4,6)) = (0.5 * pow( m_sigmau, 2 ) *
00647                 pow( m_stepTime.GetSeconds( ), 2 ) ) * CAMdoubleMatrix::identity(3);
00648         Q(_(4,6),_(1,3)) = (0.5 * pow( m_sigmau, 2 ) *
00649                 pow( m_stepTime.GetSeconds( ),2 ))*CAMdoubleMatrix::identity(3);
00650         Q(_(4,6),_(4,6)) = (pow( m_sigmau, 2 )*m_stepTime.GetSeconds( ))*CAMdoubleMatrix::identity(3);
00651 
00652         StateTransitionMatrix( );
00653 
00654         Matrix Gm(6,6);
00655         Gm(_(1,3),_(1,3)) = -CAMdoubleMatrix::identity(3);
00656         Gm(_(4,6),_(4,6)) = CAMdoubleMatrix::identity(3);
00657         // propagate Pminus
00658         m_Pminus = m_phi*(m_Pplus)*~(m_phi) + Gm*Q*~Gm;
00659 
00660         return;
00661 }
00662 
00663 void QuaternionEKFObserver::MeasurementUpdate( )
00664 {
00665         // set estimated attitude DCM
00666         Matrix estimatedAttitude(3,3);
00667         estimatedAttitude = DirectionCosineMatrix( (Quaternion)(m_qminus) );
00668         
00669         // sensitivity matrix
00670         (m_H)( _(1,3),_(1,3) ) = skew( estimatedAttitude * (m_magnetometerInertial) );
00671         (m_H)( _(4,6),_(1,3) ) = skew( estimatedAttitude * (m_accelerometerInertial) );
00672         
00673 
00674         m_h( _(1,3) ) = estimatedAttitude * (m_magnetometerInertial);
00675         m_h( _(4,6) ) = estimatedAttitude * (m_accelerometerInertial);
00676 
00677         Matrix denominator = ( (m_H)( _(m_initialRange,m_finalRange), _ )*(m_Pminus)*~((m_H)( _(m_initialRange,m_finalRange), _ )) 
00678         + (m_R)( _(m_initialRange,m_finalRange), _(m_initialRange,m_finalRange) ) ).inverse( ) ; // denominator for the kalman gain (m_K)
00679         (m_K)( _, _(m_initialRange,m_finalRange) ) = (m_Pminus)*~(m_H)( _(m_initialRange,m_finalRange), _ )*denominator;
00680 
00681         return;
00682 }
00683 
00684 
00685 
00686 // Do not change the comments below - they will be added automatically by CVS
00687 /*****************************************************************************
00688 *       $Log: QuaternionEKFObserver.cpp,v $
00689 *       Revision 1.9  2007/08/31 16:08:01  jayhawk_hokie
00690 *       Modified.
00691 *
00692 *       Revision 1.8  2007/07/24 08:42:15  jayhawk_hokie
00693 *       Removed matrix pointers.
00694 *
00695 *       Revision 1.7  2007/06/19 20:00:07  jayhawk_hokie
00696 *       Changed inverse matrix function to basic algebra expression for a 3x3 matrix. Should reduce work load on PC104.
00697 *
00698 *       Revision 1.6  2007/06/18 13:31:34  jayhawk_hokie
00699 *       Added Murrell's Algorithm to EKF Observer.
00700 *
00701 *       Revision 1.5  2007/05/30 23:46:39  jayhawk_hokie
00702 *       Modified thread termination.
00703 *
00704 *       Revision 1.4  2007/05/29 21:39:00  jayhawk_hokie
00705 *       Fixed deconstructor seg fault.
00706 *
00707 *       Revision 1.3  2007/05/29 15:30:01  jayhawk_hokie
00708 *       Modified Deconstructor
00709 *
00710 *       Revision 1.2  2007/05/23 22:07:03  jayhawk_hokie
00711 *       Implemented ignoring magnetometer measurement due to magnitude spikes.
00712 *
00713 *       Revision 1.1  2007/05/21 17:47:48  jayhawk_hokie
00714 *       Initial Submission
00715 *
00716 *
00717 *
00718 *
00719 ******************************************************************************/
00720 

Generated on Wed Sep 5 12:54:24 2007 for DSACSS Operational Code by  doxygen 1.3.9.1