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

realDMU.cpp

Go to the documentation of this file.
00001 /************************************************************************************************/
00002 /*! \file realDMU.h
00003 *  \brief The implementation file of the DMU class concerning the physical (real) DMU
00004 *  \author $Author: cakinli $
00005 *  \version $Revision: 1.9 $
00006 *  \date    $Date: 2005/04/26 17:20:38 $
00007 ************************************************************************************************/
00008 /*! 
00009 *
00010 ************************************************************************************************/
00011 
00012 #include <iostream>
00013 #include "DMU.h"
00014 
00015 using namespace O_SESSAME;
00016 using namespace std;
00017 
00018 DMU* DMU::s_instance = NULL;
00019 
00020 DMU::DMU(int _mode)
00021 {
00022         Initialize(_mode);
00023 }
00024 
00025 DMU* DMU::Instance(int _mode)
00026 {
00027         /* If first time being called, return a pointer 
00028          to an instance of a new DMU.  Otherwise return
00029          a pointer to an instance of a DMU which was made
00030          earlier.  Essentially, there can be only one DMU. 
00031         The _mode argument is passed through the constuctor 
00032         to the initialization funtion, since the DMU is initialized differently
00033         in analog and digital operation */
00034         if (s_instance==NULL)
00035         {
00036                 //cout << " you have an instance of a new dmu " << endl;
00037                 s_instance = new DMU(_mode);
00038         }
00039         return s_instance;
00040 }
00041 
00042 int DMU::Initialize(int _mode)
00043 {
00044         // this is temporary, just used because the parsing code 
00045         // is not ready yet
00046 
00047         // hmmm.. guess this should come from config stuff????
00048         Vector tempVector3(3);
00049         Vector tempQuat4(4);
00050 
00051         tempVector3(1) = 0.0;
00052         tempVector3(2) = 0.0;
00053         tempVector3(3) = 0.0;
00054 
00055         tempQuat4(1) = 0.0;
00056         tempQuat4(2) = 0.0;
00057         tempQuat4(3) = 0.0;
00058         tempQuat4(4) = 1.0;
00059 
00060         SetLocation(tempVector3);
00061         SetSensorToBodyQuaternions(tempQuat4);
00062         
00063         // NOTE: done outside of _mode check to assure that data members are initialized,
00064         // on the off chance they will be referenced despite not being in analog or digital mode.
00065         // this might look alittle different with config parsing stuff.
00066         
00067         m_prate = 200;  // this variable doesn't appear to be used for anything but an assignment check?  -jls
00068         m_tempBuffSize = 100; // this is likely excessively large
00069         m_timeToler = 31250; // in usecs, 32Hz is the max rate for *serial* comm.
00070 
00071         m_numread = 0;
00072         m_firstCall = 1;
00073 
00074         // allocate the memory that holds the temporary read data buffer 
00075         m_ptrToReadData = new adat_t[m_tempBuffSize];
00076         
00077         // Now perform initialization, which depends on MoPak mode
00078         switch(_mode)
00079         {
00080                 case 1:
00081                         if (dmuInit((long)1024, m_prate, 0)==-1) // the -1 from dmu.c
00082                         {
00083                                 cout << " oops, 'dmuInit()' failed " << endl;       
00084                                 // some error return condition?
00085                                 return 1;
00086                         }
00087                         break;
00088                 case 2:
00089                         // Note: there used to be code here to initialize the DAQ card,
00090                         // but now that is done in DAQCard::Initialize(), so it is totally separate,
00091                         // and this case doesn't really do anything.
00092                         break;
00093                 default:
00094                         cout << " bad mode! " << endl;
00095         }
00096         return 0;
00097 }
00098 
00099 void DMU::SetLocation(const Vector& _newDeviceLocation)
00100 {
00101         m_location = _newDeviceLocation;
00102 }
00103 
00104 Vector DMU::GetLocation()
00105 {       
00106         return m_location;
00107 }
00108 
00109 void DMU::SetSensorToBodyQuaternions(const Vector& _newDeviceQuaternion)
00110 {
00111         m_sensorToBodyQuaternion = _newDeviceQuaternion;
00112         
00113         // m_sensorToBodyQuaternion is given in config file,
00114         // where the frame of the DMU, F_dmu, is defined on the DMU itself,
00115         // the body-fixed frame, F_b, is defined elsewhere.
00116         
00117         // let each rate gyro (RG) have its own frame,
00118         // where the RG is defined as being located on the 1-axis,
00119         // and the other two axis are taken from F_dmu,
00120         // keeping the right-handedness
00121         //
00122         // likewise let each linear accelerometer (LAmeter) have its own frame,
00123         // where the LAmeter is defined as measuring positve acceleration along
00124         // the frame's 1-axis, and the other axes same as above.
00125         // (note: just "LA" by itself might be confused with linear actuator)
00126         
00127         // quaternion that describes both the 
00128         // orientation of "x" RG frame wrt F_dmu and the
00129         // orientation of "x" LAmeter frame wrt F_dmu
00130         Quaternion q1( 0.0, 0.0, 0.0, 1.0);
00131         
00132         // quaternion that describes both the
00133         // orientation of "y" RG frame wrt F_dmu and the
00134         // orientation of "y" LAmeter frame wrt F_dmu
00135         Quaternion q2( 0.5, 0.5, 0.5, -0.5);
00136         
00137         // quaternion that describes both the
00138         // orientation of "z" RG frame wrt F_dmu and the
00139         // orientation of "z" LAmeter frame wrt F_dmu
00140         Quaternion q3( 0.5, 0.5, 0.5, 0.5);
00141 
00142         // convert q1 into R_rg1_to_dmu
00143         Rotation R_rg1_to_dmu(q1);
00144         
00145         // convert q2 into R_rg2_to_dmu 
00146         Rotation R_rg2_to_dmu(q2);
00147         
00148         // convert q3 into R_rg3_to_dmu
00149         Rotation R_rg3_to_dmu(q3);
00150         
00151         // convert m_dmuToBodyQuaternion to R_dmu_to_b
00152         Quaternion q0(m_sensorToBodyQuaternion);
00153         Rotation R_dmu_to_b(q0);
00154         
00155         // calculate rotation from rg1 to body frame
00156         Rotation R_rg1_to_b;
00157          R_rg1_to_b = R_dmu_to_b * R_rg1_to_dmu;
00158         
00159         // calculate rotation from rg2 to body frame
00160         Rotation R_rg2_to_b;
00161         R_rg2_to_b = R_dmu_to_b * R_rg2_to_dmu;
00162         
00163         // calculate rotation from rg3 to body frame
00164         Rotation R_rg3_to_b;
00165         R_rg3_to_b = R_dmu_to_b * R_rg3_to_dmu;
00166         
00167         // convert R_rg1_to_b into q_rg1_to_b
00168         // and set as m_dmuXToBodyQuaternion
00169         Quaternion q_rg1_to_b;
00170         q_rg1_to_b = R_rg1_to_b.GetQuaternion();
00171         m_dmuXToBodyQuaternion = q_rg1_to_b;
00172          
00173         // convert R_rg2_to_b into q_rg2_to_b;
00174         // and set as m_dmuYToBodyQuaternion
00175         Quaternion q_rg2_to_b;
00176         q_rg2_to_b = R_rg2_to_b.GetQuaternion();
00177         m_dmuYToBodyQuaternion = q_rg2_to_b;
00178         
00179         // convert R_rg3_to_b into q_rg3_to_b; 
00180         // and set as m_dmuZToBodyQuaternion
00181         Quaternion q_rg3_to_b;
00182         q_rg3_to_b = R_rg3_to_b.GetQuaternion();
00183         m_dmuZToBodyQuaternion = q_rg3_to_b;
00184 }
00185         
00186 Vector DMU::GetSensorToBodyQuaternion( int id )
00187 {
00188         
00189         if ( id == 1 | id == 4 )
00190         {
00191                 // xRG or xLAmeter
00192                 return m_dmuXToBodyQuaternion;
00193         }
00194         else if ( id == 2 | id == 5 )
00195         {
00196                 // yRG or yLAmeter
00197                 return m_dmuYToBodyQuaternion;
00198         }
00199         else if ( id == 3 | id == 6 )
00200         {
00201                 // zRG or zLAmeter
00202                 return m_dmuZToBodyQuaternion;
00203         }
00204         // no default case.
00205         // what about error?
00206         //
00207         // do something more elegant and logical in future
00208         Vector errorQuat4;
00209         errorQuat4(1) = 0.0;
00210         errorQuat4(2) = 0.0;
00211         errorQuat4(3) = 0.0;
00212         errorQuat4(4) = 1.0;
00213         return errorQuat4;
00214 }
00215 
00216 void DMU::GetAnalogReading( int _channelID, DAQCard* _mycard, timeval& _timeStamp, double& _rateData )
00217 {
00218         // get current time. NOTE: Fix this time thing, as per Jana's email
00219         gettimeofday(&_timeStamp, NULL);
00220 
00221         _rateData = (double)ADscan(_mycard->m_cardData, (_channelID-1));
00222         
00223         // NOTE: this time stamp should also be fixed as per Jana's email.
00224         m_GetReadingTime = _timeStamp;
00225 }
00226                         
00227 void DMU::GetDigitalReading( int _channelID, timeval& _timeStamp, double& _rateData )
00228 {
00229         // get current time. NOTE: Fix this time thing, as per Jana's email
00230         gettimeofday(&_timeStamp, NULL);
00231 
00232         // If this is the first call of this function, get new data
00233         if (m_firstCall==1) // TRUE
00234         {
00235                 m_numread = dmuReadData(&m_ptrToReadData, m_tempBuffSize);
00236         }
00237         else if (m_firstCall==0) // FALSE
00238         {
00239                 // not the first call, so compare times
00240                 m_delta_t = _timeStamp.tv_usec - m_GetReadingTime.tv_usec;
00241                 if (m_delta_t < 0) m_delta_t += 1000000;
00242                 if (m_delta_t > m_timeToler)
00243                 {
00244                         // we have exceeded our time tolerance, so get new data
00245                         m_numread = dmuReadData(&m_ptrToReadData, m_tempBuffSize);
00246                 }
00247         }   
00248         // Otherwise m_ptrToReadData will still be pointing to the previous
00249         // data set, and since we are within the time tolerance, we'll use old data.
00250         // Note that dmuReadData will likely read more than one set of data for 
00251         // each call, so the 0 index in m_ptrToReadData[0] refers to the first set.
00252         switch (_channelID)
00253         {
00254                 case 1:
00255                         _rateData = m_ptrToReadData[0].xrate;
00256                         break;
00257                 case 2:
00258                         _rateData = m_ptrToReadData[0].yrate;
00259                         break;
00260                 case 3:
00261                         _rateData = m_ptrToReadData[0].zrate;
00262                         break;
00263                 case 4:
00264                         _rateData = m_ptrToReadData[0].xaccel;
00265                         break;
00266                 case 5:
00267                         _rateData = m_ptrToReadData[0].yaccel;
00268                         break;
00269                 case 6:
00270                         _rateData = m_ptrToReadData[0].zaccel;
00271                         break;
00272                 case 7:
00273                         _rateData = m_ptrToReadData[0].temp;
00274                         break;
00275                 default:
00276                         cout << " illegal channel value! " << endl;
00277                         // NOTE: should be something better here, like error condition
00278         }
00279         // set the time for this call to the new m_GetReadingTime
00280         m_GetReadingTime = _timeStamp;
00281         // NOTE: should add error condition that returns if numread = 0
00282 }
00283 
00284 DMU::~DMU()
00285 {
00286         // Deconstructor
00287         delete[] m_ptrToReadData; /* release the memory used for the temporary read data buffer */
00288 }
00289 
00290 // Do not change the comments below - they will be added automatically by CVS
00291 /*****************************************************************************
00292 *       $Log: realDMU.cpp,v $
00293 *       Revision 1.9  2005/04/26 17:20:38  cakinli
00294 *       Updated Makefiles to build a single libdsacss.a in the src directory to alleviate linking issues with the multiple, per-directory libraries.
00295 *       
00296 *       Revision 1.8  2005/03/16 18:08:18  cakinli
00297 *       *** empty log message ***
00298 *       
00299 *       Revision 1.7  2004/04/11 19:33:25  shoemaker
00300 *       Fixed bugs in analog code and cleaned up random messages
00301 *       
00302 *       Revision 1.6  2004/04/08 06:07:08  shoemaker
00303 *       Added analog MoPak calibration routines
00304 *       
00305 *       Revision 1.5  2004/03/29 16:43:11  shoemaker
00306 *       Added code to work with analog DAQ card code
00307 *       
00308 *       
00309 ******************************************************************************/
00310         

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