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

MWCMGController.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file DefaultController.cpp
00003 *  \brief Implementation of the DefaultController class.
00004 *  \author $Author: cakinli $
00005 *  \version $Revision: 1.6 $
00006 *  \date    $Date: 2005/02/25 18:40:53 $
00007 *//////////////////////////////////////////////////////////////////////////////////////////////////
00008 /*! 
00009 */
00010 //////////////////////////////////////////////////////////////////////////////////////////////////
00011 
00012 // This file implements the velocity feedback controller written by Eugene Skelton
00013 
00014 #include "MWCMGController.h"
00015 #include <fstream.h>
00016 
00017 int MWCMGController::Initialize() {
00018         
00019         LoadLUT("ReferenceMotion.txt");
00020         /** Set the contorl gain matrix */
00021         Matrix k(3,3);
00022         k(1,1) = 1;
00023         k(2,2) = 1;
00024         k(3,3) = 2;
00025         
00026         m_gainMatrix = k;
00027         A = FindA();
00028         MOI_sw = FindMOI_sw();
00029         gettimeofday(&InitialTime,NULL);
00030         
00031         return 0;
00032 }
00033 
00034 ofstream MRPoFile("MRPcurrent.txt",ios::out);
00035 
00036 
00037 
00038 
00039 int MWCMGController::Run()
00040 {
00041 
00042         /** Grabs the most recent parameters from the whorl object */
00043         Vector recentOmega_BL = m_whorl->GetOmegaBL();
00044         Matrix recentMOI = m_whorl->GetMOI();
00045         Vector Omega_s(3);
00046         double samplingTime;
00047         m_whorl->GetMomentumWheel("Wheel1")->GetWheelSpeed( Omega_s(1), samplingTime );
00048         m_whorl->GetMomentumWheel("Wheel2")->GetWheelSpeed( Omega_s(2), samplingTime );
00049         m_whorl->GetMomentumWheel("Wheel3")->GetWheelSpeed( Omega_s(3), samplingTime );
00050 //      cout<<"get Omega_s"<<Omega_s<<endl;
00051         cout<<"Omega_BL = "<<recentOmega_BL<<endl;
00052 
00053         Vector Qcurrent(4);
00054         Qcurrent = m_whorl->GetQuaternion();
00055         //cout<<"Q = "<<Qcurrent<<endl;
00056         
00057         //I need to convert the Current quaternion to MRPs
00058         Vector MRPcurrent(3);
00059         MRPcurrent(1) = Qcurrent(1)/(1+Qcurrent(4)); 
00060         MRPcurrent(2) = Qcurrent(2)/(1+Qcurrent(4)); 
00061         MRPcurrent(3) = Qcurrent(3)/(1+Qcurrent(4)); 
00062 
00063         double MRPnorm;
00064         MRPnorm = MRPcurrent(1)*MRPcurrent(1)+MRPcurrent(2)*MRPcurrent(2)+MRPcurrent(3)*MRPcurrent(3);
00065                 
00066         //cout<< "MRP^2 = "<<(MRPcurrent(1)*MRPcurrent(1)+MRPcurrent(2)*MRPcurrent(2)+MRPcurrent(3)*MRPcurrent(3)) << endl;
00067         if (MRPnorm > 1)
00068         {
00069                 MRPcurrent(1) = -MRPcurrent(1)/MRPnorm;
00070                 MRPcurrent(2) = -MRPcurrent(2)/MRPnorm;
00071                 MRPcurrent(3) = -MRPcurrent(3)/MRPnorm; 
00072         //cout<< "MRP^2 = "<<(MRPcurrent(1)*MRPcurrent(1)+MRPcurrent(2)*MRPcurrent(2)+MRPcurrent(3)*MRPcurrent(3)) << endl;
00073         }
00074                 
00075         //cout<<"MRPcurrent = "<<MRPcurrent<<endl;
00076         
00077         /**This is going to set the initial time if not already done. Then use difference to figure the current time*/
00078         gettimeofday(&CurrentTime,NULL);        //this line finds the current time in the maneuver
00079         
00080         double RunTime = static_cast<double>(CurrentTime.tv_sec - InitialTime.tv_sec) + (static_cast<double>(CurrentTime.tv_usec - InitialTime.tv_usec)) * 1e-6;
00081         cout<<"RunTime = "<<RunTime<<endl;
00082 
00083         /**Grabs the reference motion data for the most recent time*/
00084         double *myRow = tlu(RunTime);   //this line finds the vectors sigma,omega,and hdotref from the reference table.
00085         
00086 //      cout<<"get myRow"<<myRow[0]<<"  "<<myRow[1]<<"  "<<myRow[2]<<"  "<<myRow[3]<<"  "<<myRow[4]<<"  "<<myRow[5]<<"  "<<myRow[6]<<"  "<<myRow[7]<<"  "<<myRow[8]<<"  "<<myRow[9]<<endl;
00087 //      Vector MRPrefendl;
00088         Vector MRPRef(3);
00089         MRPRef(1) = myRow[3];
00090         MRPRef(2) = myRow[4];
00091         MRPRef(3) = myRow[5];
00092  // cout << "MRPRef = "<<MRPRef<<endl;
00093 
00094         Vector omegaRef(3);
00095         omegaRef(1) = myRow[0];
00096         omegaRef(2) = myRow[1];
00097         omegaRef(3) = myRow[2];
00098   //cout << "omegaRef"<<omegaRef<<endl;
00099         
00100         Vector hdotRef(3);
00101         hdotRef(1) = myRow[6];
00102         hdotRef(2) = myRow[7];
00103         hdotRef(3) = myRow[8];
00104   //cout << "hdotRef = "<<hdotRef<<endl;
00105         
00106         //cout<<"set stuff from myRow"<<MRPRef<<omegaRef<<hdotRef<<endl;
00107         /**Find the difference between the desired maneuver and the current*/
00108         Matrix RBR(3,3);  //RBR is the rotation between the body and reference frames
00109         Vector dMRP(3);
00110         Vector domega(3);
00111         
00112         dMRP = ((1-MRPcurrent(1)*MRPcurrent(1)-MRPcurrent(2)*MRPcurrent(2)-MRPcurrent(3)*MRPcurrent(3))*MRPRef +(1-MRPRef(1)*MRPRef(1)-MRPRef(2)*MRPRef(2)-MRPRef(3)*MRPRef(3))*MRPcurrent + 2*skew(MRPcurrent)*MRPRef)/(1+(MRPcurrent(1)*MRPcurrent(1)+MRPcurrent(2)*MRPcurrent(2)+MRPcurrent(3)*MRPcurrent(3))*(MRPRef(1)*MRPRef(1)+MRPRef(2)*MRPRef(2)+MRPRef(3)*MRPRef(3))+2*MRPcurrent(1)*MRPRef(1)+MRPcurrent(2)*MRPRef(2)+MRPcurrent(3)*MRPRef(3));
00113 
00114 cout<<"dMRP " << dMRP << endl;
00115 
00116 /**     We don't need this but I left it in to remind myself that it is not needed.
00117         if ((dMRP(1)*dMRP(1)+dMRP(2)*dMRP(2)+dMRP(3)*dMRP(3))>1)
00118         {
00119                 dMRP(1) = -dMRP(1)/(dMRP(1)*dMRP(1)+dMRP(2)*dMRP(2)+dMRP(3)*dMRP(3));
00120                 dMRP(2) = -dMRP(2)/(dMRP(1)*dMRP(1)+dMRP(2)*dMRP(2)+dMRP(3)*dMRP(3));
00121                 dMRP(3) = -dMRP(3)/(dMRP(1)*dMRP(1)+dMRP(2)*dMRP(2)+dMRP(3)*dMRP(3));   
00122         cout<<"dMRP = "<< dMRP <<endl;
00123         }
00124 */              
00125 
00126         //Make a rotation matrix from the dMRP
00127         SIGMA = 1 - (dMRP(1)*dMRP(1) + dMRP(2)*dMRP(2) + dMRP(3)*dMRP(3)); 
00128         
00129         // Column 1
00130         RBR(1,1) = 4*(dMRP(1)*dMRP(1) - dMRP(2)*dMRP(2) - dMRP(3)*dMRP(3)) + SIGMA*SIGMA;
00131         RBR(2,1) = 8*dMRP(2)*dMRP(1) - 4*dMRP(3)*SIGMA;
00132         RBR(3,1) = 8*dMRP(3)*dMRP(1) + 4*dMRP(2)*SIGMA;
00133         // Column 2
00134         RBR(1,2) = 8*dMRP(1)*dMRP(2) + 4*dMRP(3)*SIGMA;
00135         RBR(2,2) = 4*(-dMRP(1)*dMRP(1) + dMRP(2)*dMRP(2) - dMRP(3)*dMRP(3)) + SIGMA*SIGMA;
00136         RBR(3,2) = 8*dMRP(3)*dMRP(2) - 4*dMRP(1)*SIGMA;
00137         // Column 3
00138         RBR(1,3) = 8*dMRP(1)*dMRP(3) - 4*dMRP(2) * SIGMA;
00139         RBR(2,3) = 8*dMRP(2)*dMRP(3) + 4*dMRP(1)*SIGMA;
00140         RBR(3,3) = 4*(-dMRP(1)*dMRP(1) - dMRP(2)*dMRP(2) + dMRP(3)*dMRP(3)) + SIGMA*SIGMA;
00141 
00142         RBR=1/pow((1+(dMRP(1)*dMRP(1) + dMRP(2)*dMRP(2) + dMRP(3)*dMRP(3))),2) * RBR;
00143 
00144         //cout<<"RBR = "<< RBR << endl;
00145         
00146         domega = recentOmega_BL + RBR * omegaRef;
00147         cout<<"domega"<<domega<<endl;
00148         
00149         //Make some controller gain matricces
00150         Matrix k1(3,3);  //dMRP Gains
00151         k1(1,1) = 1;
00152         k1(2,2) = 1;
00153         k1(3,3) = 2;
00154         
00155         Matrix k2(3,3); //domega Gains
00156         k2(1,1) = 1;
00157         k2(2,2) = 1;
00158         k2(3,3) = 1;
00159         
00160 
00161 
00162         
00163         /** Calculate the desired control torque */
00164 //      m_controlTorque =-skew(recentOmega_BL)*(recentMOI*recentOmega_BL + MOI_sw*Omega_s) - recentMOI*skew(recentOmega_BL)*domega - RBR*(hdotRef) - m_gainMatrix*domega - m_gainMatrix*dMRP;
00165         m_controlTorque = - k1*dMRP - k2*domega ;
00166         cout<<"Control Torque = " << m_controlTorque<<endl;
00167 
00168         /** Set the desird contorl torque in the whorl object */
00169         m_whorl->SetControl(m_controlTorque);
00170 
00171         //hacking the controller to reject q drift
00172 //      m_controlTorque(1)=0;
00173 //      m_controlTorque(2)=0;
00174 //      m_controlTorque(3)=0;   
00175 
00176         /** Set the torque for the momentum wheels to produce */
00177         if ( norm2(m_controlTorque) < 0.5 )
00178                 SetWheelTorque(m_controlTorque); 
00179         else {
00180         m_controlTorque = 0.5 * ( m_controlTorque / norm2(m_controlTorque) );
00181         SetWheelTorque(m_controlTorque);
00182         };
00183 
00184         //      MRPoFile<<" " <<MRPcurrent<<" ";
00185 
00186         return 0;
00187 }
00188 
00189 
00190 // BUG: Will give crap data if it stops directly on the last line of data.
00191 
00192 double *MWCMGController::tlu(double curtime) {
00193   int i;
00194   double *row;
00195   const double TOL = 0.001;
00196 
00197   // The table has ascending times (column 0) with a negative time to
00198   // mark the end of the table.
00199 
00200   //cout << "tlu(): Debug 1\n"; cout.flush();
00201   // Find the time that is less than what we've been given.
00202   for (i = 0;
00203         (lut[i][0] >= 0.0) && (lut[i][0] <= curtime) && fabs(lut[i][0] - curtime) > TOL;
00204         i++);
00205 
00206   //cout << "tlu(): Debug 2\n"; cout.flush();
00207   // If time on the row where we stopped is negative, we're dead,
00208   // because that means we ran of the end of the table.
00209   if (lut[i][0] < 0.0)
00210     return NULL;
00211 
00212   // Allocate the returned array (which must be delete'd later
00213   row = new double[9];
00214 
00215   // If we're dead on (defined as the diff being less than TOL), we just copy
00216   //cout << "tlu(): Debug 3\n"; cout.flush();
00217   //printf("Table entry (%d): %.5f   Ref Time: %.5f\n", i, lut[i][0], curtime);
00218   if (fabs(lut[i][0] - curtime) < TOL) {
00219     for (int j = 1; j <= 9; j++)
00220       row[j-1] = lut[i][j];
00221   // Otherwise, we do interpolation...
00222   } else {
00223     for (int j = 1; j <= 9; j++)
00224       row[j-1] = (curtime-lut[i-1][0])/(lut[i][0]-lut[i-1][0]) *
00225             (lut[i][j] - lut[i-1][j]) + lut[i-1][j];
00226   }
00227         
00228 //cout<<"tlu(RunTime) makes myRow"<<row[1]<<endl;
00229 //cout << "tlu(): Debug 4\n"; cout.flush();
00230   // Finally, return the row we've built.
00231   return row;
00232 }
00233 
00234 
00235 int MWCMGController::LoadLUT(char *file) {
00236   FILE *fp;
00237   char *line, *ptr;
00238   int lc = 0;
00239   const char *DELIM = "\t";
00240   int i,j;
00241   line = new char[1024];
00242 
00243   if (!(fp = fopen(file, "r")))
00244     return -1;
00245 
00246 //  cout << "Debug 1\n";
00247 //  cout.flush();
00248   // Count the number of lines in the data file
00249   while (fgets(line, 1023, fp)) lc++;
00250 //  cout << "Debug 1.5\n";
00251 
00252   // Allocate lc rows and 10 columns
00253   lut = (double **)malloc(sizeof(double *)*(lc+1));
00254   for (int i = 0; i <= lc; i++)
00255     lut[i] = (double *)malloc(sizeof(double)*10);
00256 
00257 //  cout << "Debug 2\n";
00258   // Rewind the file, and...
00259   rewind(fp);
00260 
00261   // Do the magic...  There's no error-checking for the right number
00262   // of columns.  If there aren't, we'll crap out.
00263   for (i = 0; fgets(line, 1023, fp); i++) {
00264     for (j = 0, ptr = strtok(line, DELIM);
00265                     j < 10;
00266                     j++, ptr = strtok(NULL, DELIM)) {
00267       if (ptr)
00268         lut[i][j] = atof(ptr);
00269       else {
00270         printf("Error loading table.\n");
00271         lut[i][j] = 0.0;
00272       }
00273     }
00274 //  cout << "Debug loop: " << i << ' ' << j << endl;
00275   }
00276 //  cout << "Debug 3\n";
00277   lut[i][0] = -1.0;
00278   fclose(fp);
00279   delete [] line;
00280   return 0;
00281 }
00282 
00283 // Do not change the comments below - they will be added automatically by CVS
00284 /*****************************************************************************
00285 *       $Log: MWCMGController.cpp,v $
00286 *       Revision 1.6  2005/02/25 18:40:53  cakinli
00287 *       Created Makefiles and organized include directives to reduce the number of
00288 *       include paths.  Reorganized libraries so that there is now one per source
00289 *       directory.  Each directory is self-contained in terms of its Makefile.
00290 *       The local Makefile in each directory includes src/config.mk, which has all
00291 *       the definitions and general and pattern rules.  So at most, to see what
00292 *       goes into building a target, a person needs to examine the Makefile in
00293 *       that directory, and ../config.mk.
00294 *       
00295 *       Revision 1.5  2003/10/24 20:56:11  cskelton
00296 *       Modified for new GetWheelSpeed syntax.
00297 *       
00298 *       Revision 1.4  2003/08/21 23:32:33  cskelton
00299 *       It works. Lots of couts are included to aid in controller debugging. ReferenceMotion.txt has to be in the directory of the .exe with columns of time, omega,MRP,hdot. The ability to save data that the controller loop is calc-ing hs been added (see MRPoFile)
00300 *       
00301 *       Revision 1.3  2003/08/21 13:58:35  cskelton
00302 *       Controller updated. MRP shadow set added. TLU and LUT corrected.
00303 *       
00304 *       Revision 1.2  2003/08/15 16:12:07  cskelton
00305 *       *** empty log message ***
00306 *       
00307 *       Revision 1.1  2003/08/15 04:50:14  cskelton
00308 *       *** empty log message ***
00309 *       
00310 *       Revision 1.3  2003/08/14 18:10:41  mavandyk
00311 *       Added momentum wheel speed querying.
00312 *       
00313 *       Revision 1.2  2003/08/13 23:17:20  mavandyk
00314 *       Altered structure as outline in meeting.
00315 *       
00316 *       Revision 1.1  2003/07/31 20:43:14  mavandyk
00317 *       This is the default controller for Whorl.
00318 *       
00319 *       Revision 1.3  2003/07/07 14:11:24  simpliciter
00320 *       Removed GetWhorlObject() calls following Whorl pointers.
00321 *       
00322 *       
00323 *
00324 ******************************************************************************/

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