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

PhysicalLinearActuator.cpp

Go to the documentation of this file.
00001 //////////////////////////////////////////////////////////////////////////////////////////////////
00002 /*! \file PhysicalLinearActuator.cpp
00003 *  \brief Implementation of the PhysicalLinearActuator class
00004 *  \author $Author: jayhawk_hokie $
00005 *  \version $Revision: 1.3 $
00006 *  \date    $Date: 2007/08/02 22:35:09 $
00007 *//////////////////////////////////////////////////////////////////////////////////////////////////
00008 /*! 
00009 */
00010 //////////////////////////////////////////////////////////////////////////////////////////////////
00011 
00012 
00013 
00014 #include "PhysicalLinearActuator.h"
00015 
00016 
00017     //////////////////////////////////////////////////
00018     // Contructors/Deconstructors                   //
00019     //////////////////////////////////////////////////
00020 
00021 PhysicalLinearActuator::PhysicalLinearActuator()
00022 {
00023 
00024         la.posvel = la.jogvel = 5;
00025         la.jogacc=la.posacc=la.posdec=20;       
00026         la.mtt=5000000;                         
00027         la.portfd= 0;
00028 }
00029 
00030 PhysicalLinearActuator::~PhysicalLinearActuator()
00031 {
00032 
00033         //Deinitialize();
00034 
00035 }
00036 
00037     //////////////////////////////////////////////////
00038     // Facilitators                                 //
00039     //////////////////////////////////////////////////
00040 
00041 int PhysicalLinearActuator::TravelDistance(double param_distance)
00042 {
00043 
00044         char *buffer;
00045         buffer = (char *) malloc(256);
00046         int InchesToSteps=25400;
00047         int DistanceSteps=static_cast<int>(floor(param_distance
00048                                 *static_cast<double>(InchesToSteps)));
00049         say(la.portfd, "MR11");                         //portfd must be assigned       
00050         if (DistanceSteps < 0)
00051         
00052         {       sprintf(buffer, "DI%d\rFL\rSS-", -DistanceSteps); 
00053                 say(la.portfd, buffer);
00054         }
00055         
00056         else
00057         
00058         {       sprintf(buffer, "DI%d\rFL\rSS+", DistanceSteps); 
00059                 say(la.portfd, buffer);
00060         }
00061         return (0);
00062 }
00063 
00064 int PhysicalLinearActuator::TravelPosition(double param_position)
00065 {
00066         char buffer[256];
00067         const int InchesToSteps=25400;
00068 
00069         int PositionSteps= static_cast<int>(floor(param_position
00070                                 *static_cast<double>(InchesToSteps)));
00071         int LowerLimitSteps=static_cast<int>(floor(LowerLimit
00072                                 *static_cast<double>(InchesToSteps)));
00073         int TravelSteps=static_cast<int>(floor(Travel
00074                                 *static_cast<double>(InchesToSteps)));
00075         say(la.portfd, "MR11");
00076         sprintf(buffer, "DI%d\rFP", LowerLimitSteps+(TravelSteps/2)+PositionSteps); 
00077         say(la.portfd, buffer);
00078         
00079 return (0);
00080 
00081 }
00082 
00083 int PhysicalLinearActuator::SetVelocity(double velocity)
00084 {
00085         if (velocity < .025)
00086                 velocity = .025;        
00087         char buffer[256];
00088         say(la.portfd, "MR11\r");
00089         sprintf(buffer, "CS%f\r", velocity);
00090         //sprintf(buffer, "CS%d\r", velocity);
00091         say(la.portfd, buffer);
00092         
00093         return (0);
00094 }
00095 
00096 int PhysicalLinearActuator::StartJog(int direction)
00097 {
00098         if (direction != 0)
00099         {
00100                 char buffer[256];       
00101                 sprintf(buffer, "DI%d\r", direction);
00102                 say(la.portfd, buffer);         
00103                 say(la.portfd, "CJ\r");
00104                 hear(la.portfd,buffer, 80, 0, 300000,1);
00105                 return(0);
00106         }
00107         else  // use 0 for jog enable
00108         {               
00109                 say(la.portfd, "JE\r");
00110                 say(la.portfd, "JS1\r"); // set jog speed
00111                 return(0);
00112         }       
00113 }
00114 
00115 int PhysicalLinearActuator::Stop()
00116 {
00117         say(la.portfd, "ST\r");
00118         return (0);
00119 }
00120 
00121 /* This is pretty simply stuff.  We're going to open the port, play around
00122  * with the actuator as commanded, failing out if the error is critical
00123  * (like no comm, or hard faults), and return.  We DO NOT presume that
00124  * we're only called once, and we do not presume that the actuator is
00125  * is in an unknown state.  That's good and bad.  If the person who uses
00126  * this code doesn't know the actuator's state, a call to this will not
00127  * force them to actually do any initialization, as the bare minimum
00128  * that laInit() will do is open the port.  So as a minimum, if you're
00129  * actually initializing the LA for the first time in a program,
00130  * a minimum action flag of LAIT_COMM|LAIT_PRGP|LAIT_CTRA is recommended.
00131  * This will confirm a working link, program the presets, calculate the
00132  * real travel, and move the LA to a known position (LAIT_SLIM steps off the
00133  * farthest hard-limit).  If you don't do this, your program won't have
00134  * any way of knowing where the actuator is until it hits a hard-limit,
00135  * at which point you'll have to reset your counters and rescale, which
00136  * is exactly what the LAIT_PRGP and LAIT_CTRA flags are for in the
00137  * first place.  Of course, if you DO know where it is, you CAN set your
00138  * own counter and scale manually, and just use laInit to open the port
00139  * and do a comm check and not have to move the thing and possibly upset
00140  * your already stable system.  That's why we're not mandating travel checks.
00141  */
00142 int PhysicalLinearActuator::Initialize(int action, char *port) 
00143 {
00144   char *buffer,         /* R/W Buffer */
00145         *ptr;           /* A utlity pointer */
00146   int dir;              /* Direction of calc travel jog */
00147   int limflag=0;        /* Limit switch flag: 0 neither, 1 lo, 2 hi */
00148  
00149   la.portfn = port;
00150   buffer = (char *)malloc(256);
00151   init_serial(la.portfn, B9600, &(la.portfd));
00152   hear(la.portfd, buffer, 80, 0, 300000, 1);    /* Clear port buffer */
00153 
00154   // references to debug variable commented out since the compiler is unhappy
00155   //if (debug>4) printf("laInit(): action=%d\n", action);
00156   if (action&LAIT_COMM) {       /* Test controller comm */
00157     //if (debug) printf("laInit(): * * * LAIT_COMM * * *\n");
00158     say(la.portfd, "RS");       /* Get a status request */
00159     //if (debug>3) {
00160     //  printf("Set RS->\n");
00161     //  fflush(stdout);
00162     //}
00163     buffer[0] = 0;
00164     hear(la.portfd, buffer, 10, 0, 300000, '\r');
00165     //if (debug>3) {
00166     //  printf("Heard %s\n", buffer);
00167     //  fflush(stdout);
00168     //}
00169   
00170     switch(buffer[0]) {
00171       case 'M':                 /* Command in progress */
00172       case 'W':
00173       case 'T':
00174       close(la.portfd);
00175       return 1;
00176 
00177       case 'E':                 /* Servo error */
00178       close(la.portfd);
00179       return 2;
00180 
00181       case 'R':                 /* OK */
00182       break;
00183 
00184       default:                  /* Unknown or no response */
00185       close(la.portfd);
00186       return 3;
00187     }
00188   }
00189 
00190   if (action&LAIT_PRGP) {       /* Program presets into controller */
00191     //if (debug) printf("laInit(): * * * LAIT_PRGP * * *\n");
00192     sprintf(buffer,"VE%d", la.posvel);
00193     say(la.portfd, buffer);
00194     sprintf(buffer,"AC%d\r\nDE%d", la.posacc, la.posdec);
00195     say(la.portfd, buffer);
00196     sprintf(buffer,"JS%d\r\nJA%d", la.jogvel, la.jogacc);
00197     say(la.portfd, buffer);
00198   }
00199 
00200 
00201         say(la.portfd, "IS");
00202         hear(la.portfd, buffer, 30, 12, 300000, '\r');
00203         int old_position=atoi(buffer);
00204 
00205 
00206 
00207 
00208 
00209 
00210   if (action&LAIT_JPOS) {       /* Jog to positive end */
00211     //if (debug) printf("laInit(): * * * LAIT_JPOS * * *\n");
00212     say(la.portfd, "IS");
00213     hear(la.portfd, buffer, 30, 12, 300000, '\r');
00214     //if (debug>3) {
00215     //  printf("laInit(): ");
00216     //  printf("Got: %s\n", buffer);
00217     //}
00218     ptr = strstr(buffer, "IS=");
00219     //if (debug>3) printf("laInit(): Found: %s\n", ptr?ptr:"NULL");
00220     if (ptr?ptr[4] != '0':1) {  /* Reply mangled or not at limit */
00221       say(la.portfd, "DI1");
00222       say(la.portfd, "CJ");
00223       say(la.portfd, "SS+");
00224       hear(la.portfd, buffer, 5, 1, la.mtt, '\r');
00225     }
00226   }
00227 
00228   if (action&LAIT_JNEG) {       /* Jog to negative end */
00229     //if (debug) printf("laInit(): * * * LAIT_JNEG * * *\n");
00230     say(la.portfd, "IS");
00231     hear(la.portfd, buffer, 30, 12, 300000, '\r');
00232     ptr = strstr(buffer, "IS=");
00233     if (ptr?ptr[3] != '0':1) {  /* Reply mangled or not at limit */
00234       say(la.portfd, "DI-1");
00235       say(la.portfd, "CJ");
00236       say(la.portfd, "SS-");
00237       hear(la.portfd, buffer, 30, 1, la.mtt, '\r');
00238     }
00239   }
00240 
00241   /* This block is ugly, kludgy, hard to follow, but efficient.  The
00242    * latter is probably not a high priority since this is init code and
00243    * should not be performance critical.  A good programmer would rewrite
00244    * this to be longer, but easier to read.  Not me.  My apologies to anyone
00245    * trying to read this.  I've commented exhaustively to ease confusion.
00246    */
00247   if (action&LAIT_CTRA) {       /* Calc total travel, the fun stuff */
00248     //if (debug) printf("laInit(): * * * LAIT_CTRA * * *\n");
00249     say(la.portfd, "IS");                       /* Check limit switches */
00250     hear(la.portfd, buffer, 30, 12, 300000, '\r');
00251     ptr = strstr(buffer, "IS=");
00252     if (!ptr) {                         /* Mangled response */
00253       close(la.portfd);
00254       return(4);
00255     }
00256     if (ptr[3]=='0') limflag = 1;
00257     if (ptr[4]=='0') limflag = 2;
00258 
00259     /* First, we're going to check our current position (meaning check to
00260      * to see if either limit switch is tripped) and if so, do just one
00261      * full travel in the opposite direction.  If neither switch is tripped
00262      * we move to the closest one, if we know where we are.  If not, it
00263      * will just be random, so it won't matter that curpos, lo_l, and hi_l
00264      * are all uninitialized when we check them.
00265      */
00266     if (!limflag) {                     /* We're not at either limit */
00267       if ((la.curpos - la.lo_l) <       /* Current dist from low limit */
00268           (la.hi_l - la.curpos)) {      /* Current dist from hi limit */
00269         say(la.portfd, "DI-1"); /* We're nearer low limit, so... */
00270         limflag = 1;                    /* Manually set the limit flag */
00271       } else {                          /* We're nearer hi limit, so... */
00272         say(la.portfd, "DI1");          /* Move that way. */
00273         limflag = 2;                    /* Manually set the limit flag */
00274       }
00275       say(la.portfd, "CJ");             
00276       say(la.portfd, "SS-");
00277       hear(la.portfd, buffer, 30, 0, la.mtt, '\r');
00278     }
00279     /* By now, we're definitely AT ONE limit- so we'll do the measurement
00280      * travel based on which limit is tripped.
00281      */
00282     say(la.portfd, "SP");               /* Get pos- this is one lim pos */
00283     hear(la.portfd, buffer, 30, 12, 300000, '\r');  /* Record the response */
00284     /* So now, we're going to figure out which limit we're at, copy the
00285      * current position into that limit's marker, and set the direction
00286      * for the measurement travel accordingly.
00287      */
00288     if (limflag==2) {           /* We're at the positive limit */
00289       dir = 0;                          /* Set travel direction (0 is neg) */
00290       if (!(ptr = strstr(buffer, "SP="))) {
00291         close(la.portfd);
00292         return(4);
00293       }
00294       la.hi_l = atoi(ptr+3);            /* Record the high limit mark */
00295     } else {
00296       if (limflag==1) {         /* We're at the negative limit */
00297         dir = 1;                        /* Set travel direction (1 is pos) */
00298         if (!(ptr = strstr(buffer, "SP="))) {
00299           close(la.portfd);
00300           return(4);
00301         }
00302         la.lo_l = atoi(ptr+3);          /* Record the low limit mark */
00303       } else {
00304         close(la.portfd);               /* We shouldn't ever get here. */
00305         return(5);
00306       }
00307     }
00308 
00309     /* If originally at pos limit, dir=0, so go -, else dir=1, so go + ("") */
00310     sprintf(buffer, "DI%s1", ((char *)dir)?"":"-");
00311     say(la.portfd, buffer);     /* Now, let's jog away from the limit */
00312     say(la.portfd, "CJ");
00313     say(la.portfd, "SS.");
00314     hear(la.portfd, buffer, 10, 0, la.mtt, '\r');
00315     if (!buffer[0]) {           /* la.mtt passed but we're not at limit. */
00316       say(la.portfd, "SJ");     /* Kill the motor.  Safety demans that we not */
00317       close(la.portfd); /* press the issue here.  la.mtt is the user */
00318       return(5);                /* supplied limit-to-limit travel time.  It has */
00319     }                           /* passed, and we haven't tripped a switch.  Either */
00320                                 /* the motor is dead, or the switch is broken and */
00321                                 /* we've hit a stop.  Either case demands user */
00322                                 /* inspection of the actuator. */
00323     /* Ok, so now we're at the opposite limit.  Let's take a reading, record
00324      * it in the structure, calculate the travel, and move off the limit.
00325      */
00326     say(la.portfd, "SP");               /* Get position */
00327     hear(la.portfd, buffer, 30, 12, 300000, '\r');  /* Record the response */
00328     if (!(ptr = strstr(buffer, "SP="))) {       /* Mangled response */
00329       close(la.portfd);
00330       return(4);
00331     }
00332     if (dir) la.hi_l = atoi(ptr+3);     /* If dir, hi limit is second */
00333       else la.lo_l = atoi(ptr+3);
00334                                         /* Now we calc travel and move. */
00335     la.travel = la.hi_l - la.lo_l;
00336     sprintf(buffer, "DI%s%d", ((char*)dir)?"-":"", LAIT_SLIM);
00337                                         /* Move LAIT_SLIM steps off limit */
00338     say(la.portfd, buffer);
00339     if (dir) la.curpos = (la.hi_l - la.lo_l) - LAIT_SLIM;
00340         else la.curpos = LAIT_SLIM;
00341   }
00342 
00343   if (action&LAIT_MOLD) {       /* Move to beginning position */
00344     //if (debug) printf("laInit(): * * * LAIT_MOLD * * *\n");
00345     sprintf(buffer, "DI%d\rFP", old_position); 
00346     say(la.portfd, buffer);
00347     hear(la.portfd, buffer, 10, 2, la.mtt, '\r');
00348     la.curpos = old_position;
00349   }
00350 
00351   if (action&LAIT_MPOS) {       /* Move to positive end */
00352     //if (debug) printf("laInit(): * * * LAIT_MPOS * * * (%d&%d)\n", action,
00353         //LAIT_MPOS);
00354     sprintf(buffer, "DI%d\rFP\rSS+", la.hi_l - LAIT_SLIM); 
00355     say(la.portfd, buffer);
00356     hear(la.portfd, buffer, 10, 2, la.mtt, '\r');
00357     la.curpos = la.travel-LAIT_SLIM;
00358   }
00359 
00360   if (action&LAIT_MNEG) {       /* Move to negative end */
00361     //if (debug) printf("laInit(): * * * LAIT_MNEG * * *\n");
00362     sprintf(buffer, "DI%d\rFP\rSS-", la.lo_l + LAIT_SLIM); 
00363     say(la.portfd, buffer);
00364     hear(la.portfd, buffer, 10, 2, la.mtt, '\r');
00365     la.curpos = LAIT_SLIM;
00366   }
00367 
00368 
00369 
00370 
00371 
00372 UpperLimit=(static_cast <double>(la.hi_l))/25400.0;     //25400 is the number of steps in one inch, MR11
00373 LowerLimit=(static_cast <double>(la.lo_l))/25400.0;
00374 CurrentPosition=(static_cast <double>(la.curpos))/25400.0;
00375 Travel=(static_cast <double>(la.travel))/25400.0;
00376  
00377 return(0);
00378 
00379 }
00380 
00381 
00382 int PhysicalLinearActuator::Deinitialize() {
00383         //cout << "Serial Port Closing:\n";
00384         close(portfd);
00385         return 0;
00386 }
00387 
00388     //////////////////////////////////////////////////
00389     // Inspectors                                   //
00390     //////////////////////////////////////////////////
00391 
00392 double PhysicalLinearActuator::QueryCurrentPosition()
00393 {
00394         char *buffer;
00395         buffer = (char *) malloc(256);
00396         say(la.portfd, "SP");                           /* Get position */
00397         hear(la.portfd, buffer, 30, 12, 300000, '\r');  /* Record the response */
00398         int currentposition=atoi(buffer);
00399         CurrentPosition=currentposition/25400.0;
00400         return CurrentPosition;
00401 }
00402 // Do not change the comments below - they will be added automatically by CVS
00403 /*****************************************************************************
00404 *       $Log: PhysicalLinearActuator.cpp,v $
00405 *       Revision 1.3  2007/08/02 22:35:09  jayhawk_hokie
00406 *       Fixed Warning.
00407 *
00408 *       Revision 1.2  2006/06/27 15:27:12  bwilliam
00409 *       Added jog functions. Added port file name and removed references to debug variable in initialization function.
00410 *
00411 *
00412 *
00413 *
00414 *
00415 ****************************************************************************/
00416     
00417 
00418 
00419 

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