00001
00002
00003
00004
00005
00006
00007
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
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
00076
00077
00078 pthread_mutex_destroy( &m_Mutex );
00079
00080 }
00081
00082 int QuaternionEKFObserver::Initialize( )
00083 {
00084
00085
00086 cerr << "Start Quaternion EKF Routine" << endl;
00087 StartEKF( );
00088 usleep( 500000 );
00089
00090
00091 return( 0 );
00092 }
00093
00094
00095
00096
00097 void QuaternionEKFObserver::Parse( TiXmlHandle handle )
00098 {
00099
00100 int response;
00101
00102
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
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
00115 normalize( m_magnetometerInertial );
00116
00117
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
00126 normalize( m_accelerometerInertial );
00127
00128
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
00140
00141 (m_R)(1,1) = 2.324*1e7;
00142 (m_R)(2,2) = 3.226*1e7;
00143 (m_R)(3,3) = 2.394*1e7;
00144 (m_R)(4,4) = 0.000106;
00145 (m_R)(5,5) = 0.000105;
00146 (m_R)(6,6) = 0.000102;
00147
00148
00149 m_sigmav = sqrt( 0.00004 );
00150 m_sigmau = 2e-5;
00151
00152
00153
00154 m_P0a= 8.46e-6;
00155 m_P0b = 9.4018e-13;
00156
00157
00158
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
00170 pthread_create( &m_EKFThreadID, NULL, QuaternionEKFOriginal, (void*) this );
00171 }
00172
00173 void* QuaternionEKF( void* arg )
00174 {
00175 QuaternionEKFObserver *EKFObserver = (QuaternionEKFObserver*) arg;
00176
00177 EKFObserver->InitializeFilter( );
00178
00179
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
00189 EKFObserver->GetInitialGuessTriad( );
00190
00191
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
00207 EKFObserver->GetCurrentMeasurements( );
00208
00209
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
00219 EKFObserver->MurrellAlgorithm( );
00220
00221 pthread_testcancel( );
00222
00223
00224
00225
00226
00227 EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime;
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
00242 pthread_mutex_lock(&m_Mutex);
00243 m_exitCondition = 0;
00244
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
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
00269 (m_measurementsBody)( _(1,3) ) = m_whorl->GetMagnetometer() -> GetVectorMeasurement( );
00270
00271 string axis;
00272 for( int i =0; i < 3; i++ )
00273 {
00274
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
00291 (m_angularRates)(i+1) = m_whorl->GetRateGyro( "RATE_GYRO_" + axis ) -> GetMeasurement().GetAsDouble();
00292
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
00304 double condition = norm2( (m_previousMeasurement)( _(1,3) ) ) - norm2( (m_measurementsBody)( _(1,3) ) );
00305 if ( fabs(condition) > 50 )
00306 {
00307
00308 m_magnetometerCondition = 1;
00309 m_initialRange = 4;
00310 m_finalRange = 6;
00311
00312 }
00313 else
00314 {
00315 m_magnetometerCondition = 0;
00316 m_previousMeasurement = m_measurementsBody;
00317 }
00318 return;
00319 }
00320
00321 void QuaternionEKFObserver::GetInitialGuessTriad( )
00322 {
00323
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
00339 Quaternion qminus( m_qminus );
00340 Matrix estimatedAttitude(3,3);
00341 estimatedAttitude = DirectionCosineMatrix( qminus );
00342
00343
00344 Vector dXhatMinus(6);
00345
00346
00347 Vector dXhatPlus(6);
00348
00349
00350 if( m_magnetometerCondition )
00351 { cerr << "no magnetomter measurement" << endl; }
00352 else
00353 {
00354 dXhatPlus = SingleMeasurement( m_magnetometerInertial, (m_measurementsBody)(_(1,3)), dXhatMinus, estimatedAttitude, (m_R)( _(1,3), _(1,3) ) );
00355 }
00356
00357
00358 dXhatMinus = dXhatPlus;
00359 (m_Pminus) = (m_Pplus);
00360
00361 dXhatPlus = SingleMeasurement( m_accelerometerInertial, (m_measurementsBody)(_(4,6)), dXhatMinus, estimatedAttitude, (m_R)( _(4,6), _(4,6) ) );
00362
00363
00364 StateCovarianceUpdate( dXhatPlus );
00365
00366 return;
00367 }
00368
00369 Vector QuaternionEKFObserver::SingleMeasurement( Vector _inertial, Vector _measurement, Vector _dXhatMinus, Matrix _estimatedAttitude, Matrix _sensorNoise )
00370 {
00371
00372 Vector h(3);
00373 h( _(1,3) ) = _estimatedAttitude * (_inertial);
00374
00375 Matrix H(3,6);
00376 H( _(1,3),_(1,3) ) = skew( h );
00377
00378
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 ) ;
00384 K = (m_Pminus)*~(H)*denominator;
00385
00386
00387 m_Pplus = ( eye(6) - K*H )*(m_Pminus);
00388
00389
00390
00391 Vector E(3);
00392 E = ( _measurement - h );
00393
00394
00395 Vector dXhatPlus(6);
00396 dXhatPlus = _dXhatMinus + K*( E-H*_dXhatMinus );
00397
00398 return ( dXhatPlus );
00399 }
00400
00401
00402
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
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 );
00416
00417
00418 Vector biasPlus(3);
00419 biasPlus = m_BM + dBetaPlus;
00420 m_BM = biasPlus;
00421
00422
00423 m_angularRatehat = m_angularRates - biasPlus;
00424
00425
00426 pthread_mutex_lock(&m_Mutex);
00427
00428
00429 (m_outputState)( _(1,4) ) = m_qplus;
00430 (m_outputState)( _(5,7) ) = m_angularRates;
00431
00432
00433
00434 pthread_mutex_unlock(&m_Mutex);
00435
00436
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
00452 m_Pminus = m_phi*(m_Pplus)*~(m_phi) + Gm*Q*~Gm;
00453
00454 return;
00455 }
00456
00457
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)
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);
00474 }
00475 else
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
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
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
00520 pthread_mutex_lock(&m_Mutex);
00521
00522 m_whorl->SetState( m_outputState );
00523
00524
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
00539
00540
00541
00542 EKFObserver->InitializeFilter( );
00543
00544
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
00554 EKFObserver->GetInitialGuessTriad( );
00555
00556 EKFObserver->MeasurementUpdate( );
00557
00558
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
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
00589 EKFObserver->StateCovarianceUpdate( );
00590
00591 pthread_testcancel( );
00592
00593 EKFObserver->m_previousMeasurementTime = EKFObserver->m_currentMeasurementTime;
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
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
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 );
00622
00623
00624 Vector biasPlus(3);
00625 biasPlus = m_BM + dBetaPlus;
00626 m_BM = biasPlus;
00627
00628
00629 m_angularRatehat = m_angularRates - biasPlus;
00630
00631
00632 pthread_mutex_lock(&m_Mutex);
00633
00634
00635 (m_outputState)( _(1,4) ) = m_qplus;
00636 (m_outputState)( _(5,7) ) = m_angularRates;
00637
00638
00639
00640 pthread_mutex_unlock(&m_Mutex);
00641
00642
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
00658 m_Pminus = m_phi*(m_Pplus)*~(m_phi) + Gm*Q*~Gm;
00659
00660 return;
00661 }
00662
00663 void QuaternionEKFObserver::MeasurementUpdate( )
00664 {
00665
00666 Matrix estimatedAttitude(3,3);
00667 estimatedAttitude = DirectionCosineMatrix( (Quaternion)(m_qminus) );
00668
00669
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( ) ;
00679 (m_K)( _, _(m_initialRange,m_finalRange) ) = (m_Pminus)*~(m_H)( _(m_initialRange,m_finalRange), _ )*denominator;
00680
00681 return;
00682 }
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720