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

Magnetometer.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file Magnetometer.cpp
00003 *  \brief Implementation of the Magnetometer class
00004 *  \author $Author: jayhawk_hokie $
00005 *  \version $Revision: 1.12 $
00006 *  \date    $Date: 2007/07/24 09:41:47 $
00007 *//////////////////////////////////////////////////////////////////////////////////////////////////
00008 /*! 
00009 */
00010 //////////////////////////////////////////////////////////////////////////////////////////////////
00011 
00012 
00013 #include "Magnetometer.h"
00014 
00015 //////////////////////////////////////////////////////////////////////
00016 // Construction/Destruction
00017 //////////////////////////////////////////////////////////////////////
00018 
00019 /*! \brief Default Constructor
00020 */
00021 
00022 Magnetometer::Magnetometer( )
00023 {
00024 }
00025 
00026 /*! \brief Primary constructor
00027         * @param handle XML handle with current simulator as starting node
00028 */
00029 Magnetometer::Magnetometer( TiXmlHandle handle ): m_magCountsBody(3) 
00030 {
00031         m_magCountsSensor.initialize(3);
00032 
00033         char* magfn;
00034         magfn = (char*)malloc(50);
00035 
00036         buffer = (char*) malloc(100);
00037         magread = (char*) malloc(7);
00038 
00039         TiXmlHandle magHandle = handle.FirstChild("HARDWARE_PROPERTIES").FirstChild("MAGNETOMETER");
00040 
00041         magfn = (char *)magHandle.Child("PORT",0).Element() -> Attribute("value");
00042 
00043         int response; // error check for parsing
00044         Vector mtob(3);
00045 
00046         response = magHandle.Child("SENSOR_2_BODY_VECTOR", 0).Element() -> QueryDoubleAttribute("value1", &mtob(1));
00047         checkResponse(response);
00048         response = magHandle.Child("SENSOR_2_BODY_VECTOR", 0).Element() -> QueryDoubleAttribute("value2", &mtob(2));
00049         checkResponse(response);
00050         response = magHandle.Child("SENSOR_2_BODY_VECTOR", 0).Element() -> QueryDoubleAttribute("value3", &mtob(3));
00051         checkResponse(response);
00052 
00053         response = magHandle.Child("X_OFFSET", 0).Element() -> QueryDoubleAttribute("value", &m_xOff);
00054         checkResponse(response);
00055         response = magHandle.Child("Y_OFFSET", 0).Element() -> QueryDoubleAttribute("value", &m_yOff);
00056         checkResponse(response);
00057         response = magHandle.Child("MAJOR_AXIS", 0).Element() -> QueryDoubleAttribute("value", &m_majorA);
00058         checkResponse(response);
00059         response = magHandle.Child("MINOR_AXIS", 0).Element() -> QueryDoubleAttribute("value", &m_minorA);
00060         checkResponse(response);
00061         response = magHandle.Child("PHI", 0).Element() -> QueryDoubleAttribute("value", &m_phi);
00062         checkResponse(response);
00063 
00064         // convert mtob to radians
00065         mtob(1) = Deg2Rad(mtob(1));
00066         mtob(2) = Deg2Rad(mtob(2));
00067         mtob(3) = Deg2Rad(mtob(3));
00068 /*
00069         cout << "mtob: " << mtob << endl;
00070         Matrix temp1(3,3);
00071         temp1(1,1) = cos(mtob(1));
00072         temp1(1,2) = sin(mtob(1));
00073         temp1(2,1) = -sin(mtob(1));
00074         temp1(2,2) = cos(mtob(1));
00075         temp1(3,3) = 1;
00076         
00077         cout << temp1 << endl;
00078         
00079         Matrix temp2(3,3);
00080         temp2(1,1) = cos(mtob(2));
00081         temp2(1,3) = -sin(mtob(2));
00082         temp2(3,1) = sin(mtob(2));
00083         temp2(3,3) = cos(mtob(2));
00084         temp2(2,2) = 1;
00085         cout << temp2 << endl;
00086         
00087         Matrix temp3(3,3);
00088         temp3(1,1) = 1;
00089         temp3(2,2) = cos(mtob(3));
00090         temp3(2,3) = sin(mtob(3));
00091         temp3(3,2) = -sin(mtob(3));
00092         temp3(3,3) = cos(mtob(3));
00093         
00094         cout << temp3 << endl;
00095 
00096         cout << "mult: " << temp1*temp2*temp3 << endl;
00097         
00098         cout << R3(mtob(1)) << endl;
00099         cout << DirectionCosineMatrix(mtob(1),mtob(2),mtob(3),321) << endl;
00100 */
00101         m_Rmb.initialize(3,3);
00102         m_Rmb( _(1,3), _(1,3) ) = DirectionCosineMatrix(mtob(1),mtob(2),mtob(3),321);
00103         
00104         Initialize( magfn );
00105 }
00106 
00107 /*! \brief Deinitialize
00108  */
00109 Magnetometer::~Magnetometer( )
00110 {
00111 
00112         cerr << "Deinitialize Magnetometer" << endl;
00113 
00114         // Set Magnetometer to factory defaults
00115         say(m_magfd,"*99WE\r"); // Write Enable
00116         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00117         say(m_magfd, "*99D\r");
00118         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00119         cerr << "Set Magnetometer to Factory Defaults - Response: " << endl << buffer << endl;
00120         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00121         cerr << buffer << endl;
00122 
00123         close(m_magfd);
00124 
00125 }
00126 
00127 
00128 /*! \brief Magnetometer initialization function
00129         * @param magfn magnetometer port file name
00130         * @param mtob vector containing magnetometer to body 3-2-1 Euler Angles
00131 */
00132 int Magnetometer::Initialize( const string& magfn ) 
00133 {
00134         // Open port
00135         if (init_serial((char*)magfn.c_str(), B9600, &(m_magfd)) < 0 )
00136         {
00137                 cerr << "ERROR: Magnetometer serial initialization failed.\n";
00138                 exit(1);
00139         }               
00140 
00141         cerr << "\nInitialization of Magnetometer" << endl;
00142 
00143         DefaultConfiguration( );        
00144 
00145         SetBaud19200Configuration( );
00146 
00147         close(m_magfd); // close port
00148 
00149         // re-open port with 19,200 baud rate
00150         if (init_serial((char*)magfn.c_str(), B19200, &(m_magfd)) < 0 )
00151         {
00152                 cerr << "ERROR: Magnetometer serial initialization failed.\n";
00153                 exit(1);
00154         }               
00155 
00156         PolledDataConfiguration( );
00157 
00158         SetBinaryConfiguration( );
00159         
00160         SetSampleRateConfiguration( );
00161         
00162         SetResetOnConfiguration( );
00163         //SetResetOffConfiguration( );
00164 
00165         SetAveragingOnConfiguration( );
00166         //SetAveragingOffConfiguration( );
00167 
00168         ReEnterOnConfiguration( );
00169         //ReEnterOffConfiguration( );
00170 
00171         QuerryConfiguration( );
00172         
00173         return( 0 );
00174 }
00175 
00176 
00177 /*! \brief Set Magnetometer to factory defaults */
00178 void Magnetometer::DefaultConfiguration( )
00179 {
00180         // Set Magnetometer to factory defaults
00181         say(m_magfd,"*99WE\r"); // Write Enable
00182         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00183         say(m_magfd, "*99D\r");
00184         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00185         cerr << "Set Magnetometer to Factory Defaults - Response: " << endl << buffer << endl;
00186         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00187         cerr << buffer << endl;
00188         usleep(1000000);
00189 }
00190 
00191 
00192 /*! \brief Set Baud Rate to 19,200 */
00193 void Magnetometer::SetBaud19200Configuration( )
00194 {
00195         // Set Baud Rate to 19,200.
00196         say(m_magfd,"*99WE\r"); // Write Enable
00197         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00198         say(m_magfd, "*99!BR=F\r");
00199         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00200         cerr << "Set Magnetometer Baud Rate to 19,200 - Response: " << endl << buffer << endl;
00201         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00202         cerr << buffer << endl;
00203         usleep(100000);
00204 }
00205 
00206 /*! \brief Set Magnetometer to Polled data */
00207 void Magnetometer::PolledDataConfiguration( )
00208 {
00209         // Output polled data: Note: only implemenation
00210         say(m_magfd, "*99P\r");
00211         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00212         cerr << "Set Magnetometer to polled data mode - Response: " << buffer << endl;
00213         usleep(100000);
00214 }       
00215 
00216 /*! \brief Set Magnetometer to Continuous data */
00217 void Magnetometer::ContinuousDataConfiguration( )
00218 {
00219         say(m_magfd, "*99C\r");
00220         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00221         cerr << "Set Magnetometer to polled data mode - Response: " << buffer << endl;
00222         usleep(100000);
00223 }       
00224 
00225 void Magnetometer::SetBinaryConfiguration( )
00226 {
00227         // Set to Binary. Note: parser code written for binary mode only.
00228         say(m_magfd,"*99WE\r"); // Write Enable
00229         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00230         say(m_magfd, "*99B\r");
00231         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00232         cerr << "Set Magnetometer to Binary mode - Response: " << buffer << endl;
00233         usleep(100000);
00234 }
00235 
00236 /*! \brief Set to Ascii. Note: code not setup for Ascii parsing. */
00237 void Magnetometer::SetAsciiConfiguration( )
00238 {
00239         say(m_magfd,"*99WE\r"); // Write Enable
00240         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00241         say(m_magfd,"*99A\r");
00242         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00243         cerr << "Set Magnetometer to Ascii mode - Response: " << buffer << endl;
00244         usleep(100000);
00245 }
00246 
00247 /*! \brief  Set Sample Rate ( 10, 20 , 25, 30, 40, 50, 60, 100, 123, 154 )
00248  *   Note: Check HMR2300 manual for Output Sample rate restrictions. Recommended < 60 sps. */
00249 void Magnetometer::SetSampleRateConfiguration( )
00250 {
00251         say(m_magfd, "*99R=154\r");
00252         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00253         cerr << "Set Magnetometer sample rate - Response: " << buffer << endl;
00254         usleep(100000);
00255 }
00256                 
00257 /*! \brief  Set/Reset ON */
00258 void Magnetometer::SetResetOnConfiguration( )
00259 {       
00260         say(m_magfd,"*99WE\r"); // Write Enable
00261         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00262         say(m_magfd, "*99TN\r");
00263         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00264         cerr << "Set Magnetometer to Set/Reset On - Response: " << buffer << endl;
00265         usleep(100000);
00266 }       
00267 
00268 /*! \brief Set/Reset Off */
00269 void Magnetometer::SetResetOffConfiguration( )
00270 {       
00271         say(m_magfd,"*99WE\r"); // Write Enable
00272         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00273         say(m_magfd, "*99TF\r");
00274         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00275         cerr << "Set Magnetometer to Set/Reset OFF - Response: " << buffer << endl;
00276         usleep(100000);
00277 }
00278 
00279 /*! \brief Set Averaging On */
00280 void Magnetometer::SetAveragingOnConfiguration( )
00281 {
00282         say(m_magfd,"*99WE\r"); // Write Enable
00283         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00284         say(m_magfd, "*99VN\r");
00285         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00286         cerr << "Set Magnetometer to Averaging On - Response: " << buffer << endl;
00287         usleep(100000);
00288 }
00289 
00290 /*! \brief Set Averaging OFF */
00291 void Magnetometer::SetAveragingOffConfiguration( )
00292 {
00293         say(m_magfd,"*99WE\r"); // Write Enable
00294         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00295         say(m_magfd, "*99VF\r");
00296         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00297         cerr << "Set Magnetometer to Averaging OFF - Response: " << buffer << endl;
00298         usleep(100000);
00299 }
00300         
00301 /*! \brief Re-Enter Response On */
00302 void Magnetometer::ReEnterOnConfiguration( )
00303 {
00304         say(m_magfd,"*99WE\r"); // Write Enable
00305         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00306         say(m_magfd, "*99Y\r");
00307         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00308         cerr << "Set Magnetometer to Re-Enter On - Response: " << buffer << endl;
00309         usleep(100000);
00310 }       
00311 
00312 /*! \brief Re-Enter Response OFF */
00313 void Magnetometer::ReEnterOffConfiguration( )
00314 {
00315         say(m_magfd,"*99WE\r"); // Write Enable
00316         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00317         say(m_magfd, "*99N\r");
00318         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00319         cerr << "Set Magnetometer to Re-Enter OFF - Response: " << buffer << endl;
00320         usleep(100000);
00321 }       
00322 
00323 /*! \brief  Querry parameters */
00324 void Magnetometer::QuerryConfiguration( )
00325 {
00326         say(m_magfd, "*99Q\r");
00327         hear(m_magfd, buffer, 100, 0, 300000, '\r');
00328         cerr << "Magnetometer Setting Parameters: " << buffer << endl;
00329 }
00330 
00331 
00332 /*! \brief Function to return scalar measurement (not currently used)
00333 */
00334 Measurement Magnetometer::GetMeasurement( )
00335 {
00336         Measurement unintializedMeasurement;
00337         return( unintializedMeasurement );
00338 }
00339 
00340 
00341 /*! \brief Function to return magnetometer measurement in the form of a vector in the Sensor Frame
00342         * @return m_magCountsSensor vector containing magnetometer measurements in counts
00343 */
00344 Vector Magnetometer::GetRawVectorMeasurement( ) 
00345 {
00346         //AsciiParser( );
00347         
00348         BinaryParser( );
00349 
00350         return ( m_magCountsSensor );
00351 } 
00352 
00353 /*! \brief Parse the ascii magnetometer string into x, y, z components.
00354  *  The magnetometer does not seem to always return the correct format. 
00355  *  Recommend using binary parser.
00356  */
00357 void Magnetometer::AsciiParser( )
00358 {
00359         say(m_magfd, "*99P\r");                 
00360         
00361         // read data from magnetometer
00362         hear(m_magfd, magread, 7, 0, 300000, '\r'); // binary return string is 7 bytes
00363         
00364         stringstream os(magread);       
00365 
00366         char* number;
00367         number = (char*) malloc(5);
00368         
00369         // parse the magnetometer output string and dump into m_magCountsSensor vector
00370         // ASCII parser (not currently being used)
00371         for (int i=1;os >> buffer;i++)
00372         {
00373                 if (i<4) m_magCountsSensor(i) = 1;
00374                 if (buffer[0] == '-')
00375                 {                               
00376                         os >> buffer;                           
00377                         if(i<4) m_magCountsSensor(i) = -1;
00378                 }                               
00379                                 
00380                 if (strchr(buffer,','))
00381                 {                               
00382                         strcpy(number, strtok(buffer, ","));    
00383                         //cerr << "Number before cat: " << number << endl;                      
00384                         strcat(number,strtok(NULL,"\r"));
00385                         //sprintf(buffer, "%s%s", number, strtok(NULL,"\r"));
00386                         //cerr << "Buffer after cat: " << buffer << endl;
00387                         strcpy(buffer, number);
00388                         bzero(number, sizeof(number));
00389                 }
00390                 
00391                 // write if using correct index #
00392                 if (i <4) m_magCountsSensor(i) *= atoi(buffer);                 
00393         }               
00394 }
00395 
00396 
00397 
00398 /*! \brief  Binary parser- return string has the following format
00399  *   return = Xh | Xl | Yh | Yl | Zh | Zl | CR
00400  *   where h and l are high and low bytes respectively and CR
00401  *   is a carriage return. The high byte is a signed int, the low unsigned.
00402  *   output is parsed by converting each byte to integer, left shifting
00403  *   the high byte 8 times and adding the two together. 
00404  *   The high byte is left shifted since the high and low byte comprise
00405  *   a single 16 bit integer and the first bit of the high byte must be multiplied
00406  *   by 2^8 instead of 2^0, and so on for the other bits
00407  *   The high byte is casted straight to an int, but for the low byte,
00408  *   the char must first be casted to unsigned char, then to int since that
00409  *   byte is unsigned
00410  */     
00411 void Magnetometer::BinaryParser( )
00412 {
00413         say(m_magfd, "*99P\r");                 
00414         
00415         // read data from magnetometer
00416         hear(m_magfd, magread, 7, 0, 300000, '\r'); // binary return string is 7 bytes
00417         
00418         m_magCountsSensor(1) = ((static_cast<int>(magread[0])) << 8) + static_cast
00419                                 <int>(static_cast<unsigned char>(magread[1]));  
00420 
00421         m_magCountsSensor(2) = ((static_cast<int>(magread[2])) << 8) + static_cast
00422                                 <int>(static_cast<unsigned char>(magread[3]));  
00423 
00424         m_magCountsSensor(3) = ((static_cast<int>(magread[4])) << 8) + static_cast
00425                                 <int>(static_cast<unsigned char>(magread[5]));  
00426         return;
00427 } 
00428 
00429 
00430 /*! \brief Function to return magnetometer measurement in the form of a vector in Body frame
00431         * @return m_magCountsBody vector containing magnetometer measurements in counts
00432 */
00433 Vector Magnetometer::GetVectorMeasurement( ) 
00434 {
00435         static double xtmp, ytmp, xtmp2, ytmp2;
00436 
00437         GetRawVectorMeasurement( );
00438         
00439         // rotate from magnetometer to body frame       
00440         m_magCountsBody = m_Rmb*(m_magCountsSensor);
00441         
00442         // correct for measurement calibration
00443         
00444         xtmp = m_magCountsBody(1);
00445         ytmp = m_magCountsBody(2);
00446 
00447         // subtract offset
00448         xtmp = xtmp - m_xOff;
00449         ytmp = ytmp - m_yOff;
00450 
00451         // rotate ellipse
00452         xtmp2 = xtmp*cos(m_phi) + ytmp*sin(m_phi);      
00453         ytmp2 = -xtmp*sin(m_phi) + ytmp*cos(m_phi);
00454 
00455         // scale results for x
00456         xtmp2 = xtmp2*m_minorA/m_majorA;
00457         
00458         // rotate back to get final result
00459         m_magCountsBody(1) = xtmp2*cos(m_phi) - ytmp2*sin(m_phi);
00460         m_magCountsBody(2) = xtmp2*sin(m_phi) + ytmp2*cos(m_phi);
00461 
00462         return( m_magCountsBody );
00463 }
00464 
00465 // Do not change the comments below - they will be added automatically by CVS
00466 /*****************************************************************************
00467 *       $Log: Magnetometer.cpp,v $
00468 *       Revision 1.12  2007/07/24 09:41:47  jayhawk_hokie
00469 *       Removed matrix and vector pointers.
00470 *       
00471 *       Revision 1.11  2007/05/30 20:37:09  bwilliam
00472 *       Updated to include x-y calibration.
00473 *       
00474 *       Revision 1.10  2007/05/22 18:20:33  jayhawk_hokie
00475 *       *** empty log message ***
00476 *       
00477 *       Revision 1.9  2007/05/22 16:39:35  jayhawk_hokie
00478 *       Modified output status commands during initialization phase.
00479 *       
00480 *       Revision 1.8  2007/05/08 22:28:58  jayhawk_hokie
00481 *       Added functions for configuration parameters. Changed Baud to 19,200. Still have random spike points on the Z sensor.
00482 *       
00483 *       Revision 1.7  2007/03/27 19:40:35  jayhawk_hokie
00484 *       Resolved non void function warnings.
00485 *       
00486 *       Revision 1.6  2007/01/12 22:18:42  bwilliam
00487 *       Modified to use XML parser.
00488 *       
00489 *       Revision 1.5  2006/07/20 20:37:30  bwilliam
00490 *       Removed the transpose (oops).
00491 *       
00492 *       Revision 1.4  2006/07/20 20:19:51  bwilliam
00493 *       Transposed Rmb in sensor to body rotation equation to properly rotate measurement into body frame.
00494 *       
00495 *       Revision 1.3  2006/07/10 21:47:00  bwilliam
00496 *       Altered class structure and added code for magnetometer implementation.
00497 *       
00498 *       Revision 1.2  2003/07/04 14:13:01  simpliciter
00499 *       Added newline at end of file.
00500 *       
00501 *       Revision 1.1.1.1  2003/06/06 18:44:15  simpliciter
00502 *       Initial submission.
00503 *       
00504 *
00505 ******************************************************************************/
00506 

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