00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031  
00032  #include "controller.h"
00033  #include "log_wrapper.h"
00034  #include "ros_conversion.h"
00035  
00036 namespace motoman
00037 {
00038 namespace controller
00039 {
00040 
00041 
00042 
00043 
00044 
00045 
00046 const int MAX_CTRL_GROUPS = 8;
00047 ctrl_grp_param_t ctrl_grp_parameters_[MAX_CTRL_GROUPS];
00048 sys_param_t sys_parameters_;
00049 
00050 int Controller::active_ctrl_grp_ = 0;  
00051 
00052 Controller::Controller()
00053 {
00054   this->jobStarted = false;
00055   this->motionEnabled = false;
00056 }
00057 
00058 Controller::~Controller()
00059 {
00060   this->disableMotion();
00061   
00062 }
00063 
00064 bool Controller::initParameters(int ctrl_grp)
00065 {
00066   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00067   setCtrlGroup(ctrl_grp);
00068 
00069   UINT16 dummyUInt;
00070   int dummyInt, dummyIntAry[MAX_PULSE_AXES];
00071   float dummyFloat, dummyFloatAry[MAX_PULSE_AXES];
00072   FB_AXIS_CORRECTION dummyPulseCorrAry[MAX_PULSE_AXES];
00073 
00074   
00075   
00076   bool rslt = true;
00077   rslt &= getNumRobotAxes(ctrl_grp, &dummyInt);
00078   rslt &= getPulsesPerRadian(ctrl_grp, dummyFloatAry);
00079   rslt &= getFBPulseCorrection(ctrl_grp, dummyPulseCorrAry);
00080   rslt &= getNumTasks(&dummyInt, &dummyInt, &dummyInt);
00081   rslt &= getInterpPeriod(&dummyUInt);
00082   rslt &= getMaxIncrPerCycle(ctrl_grp, dummyIntAry);
00083   rslt &= getIncrMotionLimit(ctrl_grp, &dummyFloat);
00084   
00085   ctrl_grp_param_t& cp = ctrl_grp_parameters_[ctrl_grp];
00086   sys_param_t& sp = sys_parameters_;
00087 
00088   LOG_DEBUG("Controller Parameters retrieved for group #%d", ctrl_grp+1);
00089   LOG_DEBUG("  numAxes: %d", cp.num_axes);
00090   LOG_DEBUG("  pulse_per_rad: %8g", cp.pulses_per_rad[0]);
00091   for (int i=1; i<cp.num_axes; ++i)
00092     LOG_DEBUG(", %8g", cp.pulses_per_rad[i]);
00093     
00094   for (int i=0; i<MAX_PULSE_AXES; ++i)
00095   {
00096         FB_AXIS_CORRECTION& corr = cp.pulse_correction[i];
00097     if (!corr.bValid) continue;
00098 
00099     LOG_DEBUG("  pulseCorr[%d]: %d, %d, %8g", i, corr.ulSourceAxis, corr.ulCorrectionAxis, corr.fCorrectionRatio);
00100   }
00101   
00102   LOG_DEBUG("  numTasks: %d normal, %d highPrio, %d outFiles", sp.tasks.qtyOfNormalPriorityTasks,
00103             sp.tasks.qtyOfHighPriorityTasks, sp.tasks.qtyOfOutFiles);
00104   LOG_DEBUG("  interpPeriod: %d msec", sp.interp_period);
00105   LOG_DEBUG("  maxIncrPerCycle: %8g", cp.max_incr_per_cycle[0]);
00106   for (int i=01; i<cp.num_axes; ++i)
00107     LOG_DEBUG(", %8g", cp.max_incr_per_cycle[i]);
00108   LOG_DEBUG("  incrMotionLimit: %8g", cp.incr_motion_limit);
00109 
00110   return rslt;
00111 }
00112 
00113 void Controller::setInteger(int index, int value)
00114 {
00115         MP_VAR_DATA data;
00116         
00117         data.usType = MP_RESTYPE_VAR_I;
00118         data.usIndex = index;
00119         data.ulValue = value;
00120         
00121         while (mpPutVarData ( &data, 1 ) == MP_ERROR) 
00122         {
00123         LOG_ERROR("Failed to set integer varaible, index: %d, value: %d, retrying...", 
00124             data.usIndex, data.ulValue);
00125         mpTaskDelay(VAR_POLL_DELAY_);
00126     }
00127 }
00128 
00129 int Controller::getInteger(int index)
00130 {
00131     
00132         MP_VAR_INFO info;
00133         LONG rtn;
00134         
00135         info.usType = MP_RESTYPE_VAR_I;
00136         info.usIndex = index;
00137         
00138         while (mpGetVarData ( &info, &rtn, 1 ) == MP_ERROR) 
00139         {
00140         LOG_ERROR("Failed to retreive integer variable index: %d, retrying...", info.usIndex);
00141         mpTaskDelay(VAR_POLL_DELAY_);
00142     }
00143     return rtn;
00144 }
00145 
00146 bool Controller::setJointPositionVar(int index, industrial::joint_data::JointData ros_joints)
00147 {
00148     
00149     float mp_joints_radians[MAX_PULSE_AXES];
00150     ros_conversion::toMpJoint(ros_joints, mp_joints_radians);
00151 
00152     
00153     float pulses_per_rad[MAX_PULSE_AXES];
00154     if (!getPulsesPerRadian(pulses_per_rad)) return false;
00155 
00156     
00157     LONG mp_joints_pulses[MAX_PULSE_AXES];
00158         for (int i=0; i<MAX_PULSE_AXES; ++i)
00159         mp_joints_pulses[i] = (long)floor(mp_joints_radians[i] * pulses_per_rad[i]);
00160     
00161     
00162     const int MP_POSVAR_SIZE = 10;  
00163         MP_POSVAR_DATA local_posvar;
00164         local_posvar.usType = MP_RESTYPE_VAR_ROBOT;  
00165         local_posvar.usIndex = index;
00166         local_posvar.ulValue[0] = 0;   
00167         for (int i=0; i<MP_POSVAR_SIZE-2 && i<MAX_PULSE_AXES; ++i)
00168           local_posvar.ulValue[i+2] = mp_joints_pulses[i];  
00169         
00170         
00171         bool result = (mpPutPosVarData ( &local_posvar, 1 ) == OK);
00172         
00173         return result;
00174 }
00175 
00176 
00177  bool Controller::getStatus(industrial::robot_status::RobotStatus & status)
00178  {
00179         status.init();  
00180     status.setInMotion(getInMotionStatus());
00181  return true;
00182  }
00183  
00184  
00185  industrial::robot_status::TriState Controller::getInMotionStatus()
00186  {
00187           industrial::robot_status::TriState rtn = 
00188                 industrial::robot_status::TriStates::TS_UNKNOWN;
00189         
00190           
00191           LONG status = 0;
00192           MP_CTRL_GRP_SEND_DATA sData;
00193           MP_FB_SPEED_RSP_DATA pulse_speed;
00194           const int SPEED_THRESHOLD = 150; 
00195           
00196           
00197           sData.sCtrlGrp = getCtrlGroup();
00198           status = mpGetFBSpeed (&sData,&pulse_speed);
00199           if (MP_ERROR == status)
00200           {
00201             LOG_ERROR("Failed to get pulse feedback speed: %u", status);
00202           }
00203           else
00204           {
00205                   
00206                   
00207                   rtn = industrial::robot_status::TriStates::TS_FALSE;
00208                   
00209                   for (int i=0; i<MAX_PULSE_AXES; ++i)
00210                   {
00211                     if( abs(pulse_speed.lSpeed[i]) > SPEED_THRESHOLD )
00212                     {
00213                         LOG_DEBUG("Speed detected, joint speed: %d and threshold: %d", 
00214                                         pulse_speed.lSpeed[i], SPEED_THRESHOLD);
00215                         rtn = industrial::robot_status::TriStates::TS_TRUE;
00216                         break;
00217                     }
00218                   }
00219            }
00220           return rtn;
00221   }
00222 
00223 
00224 void Controller::enableMotion(void)
00225 {
00226   
00227   LOG_INFO("Enabling motion");
00228   this->motionEnabled = false;
00229 
00230   servo_power_data.sServoPower = ON;
00231   while(mpSetServoPower(&servo_power_data, &servo_power_error) == MP_ERROR)
00232   {
00233     LOG_ERROR("Failed to turn on servo power, error: %d, retrying...", servo_power_error.err_no);
00234     mpTaskDelay(this->VAR_POLL_DELAY_);
00235   };
00236   
00237   hold_data.sHold = OFF;
00238   while(mpHold(&hold_data, &hold_error) == MP_ERROR)
00239   {
00240     LOG_ERROR("Failed to turn off hold, error: %d, retrying...", hold_error.err_no);
00241     mpTaskDelay(this->VAR_POLL_DELAY_);
00242   };
00243   
00244   this->motionEnabled = true;
00245 }
00246 
00247 
00248 void Controller::disableMotion(void)
00249 {
00250   LOG_INFO("Disabling motion");
00251   servo_power_data.sServoPower = OFF;
00252   while(mpSetServoPower(&servo_power_data, &servo_power_error) == MP_ERROR)
00253   {
00254     LOG_ERROR("Failed to turn off servo power, error: %d, retrying...", servo_power_error.err_no);
00255     mpTaskDelay(this->VAR_POLL_DELAY_);
00256   };
00257   
00258   this->motionEnabled = false;
00259 }
00260 
00261 void Controller::startMotionJob(char* job_name)
00262 {
00263 
00264   this->jobStarted = false;
00265   
00266   this->enableMotion();
00267   
00268   
00269   job_start_data.sTaskNo = 0;
00270   strcpy(job_start_data.cJobName, job_name);
00271  
00272   
00273   LOG_INFO("Starting motion job");
00274   while(mpStartJob(&job_start_data, &job_error) == ERROR)
00275   {
00276     LOG_ERROR("Failed to start job, error: %d, retrying...", job_error.err_no);
00277     mpTaskDelay(this->VAR_POLL_DELAY_);
00278   }; 
00279   
00280   this->jobStarted = true;
00281 }
00282 
00283 
00284 void Controller::stopMotionJob(char* job_name)
00285 {  
00286   LOG_INFO("Stopping motion job");
00287   this->disableMotion();
00288   
00289   
00290   strcpy(job_delete_data.cJobName, job_name);
00291   
00292   while(mpDeleteJob(&job_delete_data, &job_error) == MP_ERROR)
00293   {
00294     LOG_ERROR("Failed to delete job, error: %d, retrying...", job_error.err_no);
00295     mpTaskDelay(this->VAR_POLL_DELAY_);
00296   };
00297   
00298   this->jobStarted = false;
00299 }       
00300 
00301 
00302 #define FILE_NAM_BUFFER_SIZE 100
00303 bool Controller::writeJob(char* path, char* job)
00304 {
00305     bool rtn = false;
00306     int fd = this->MP_ERROR;
00307     int status = this->MP_ERROR;
00308     char filename[FILE_NAM_BUFFER_SIZE];  
00309     
00310     memset(filename, '\0', FILE_NAM_BUFFER_SIZE);  
00311     strcpy(filename, "MPRAM1:\\");
00312     strcat(filename, path);
00313     
00314     LOG_DEBUG("writeJob: %s", filename);
00315     
00316     
00317     LOG_DEBUG("Trying to remove file, if it exists");
00318     status = mpRemove( filename );
00319     if (this->MP_ERROR == status)
00320     {
00321         LOG_WARN("Failed to remove job file: %s", filename);
00322     }
00323     
00324     
00325     
00326     fd = mpCreate( filename, O_WRONLY );
00327     if (this->MP_ERROR != fd)
00328     {
00329         status = mpWrite( fd, job, strlen(job) );
00330         if ( this->MP_ERROR != status )
00331         {
00332             LOG_INFO("Successfully loaded file: %s, bytes written: %d", filename, status);
00333             rtn = true;
00334         }
00335         else
00336         {
00337             LOG_ERROR("Failed to write file: %s", filename);
00338             rtn = false;
00339         }
00340         
00341         
00342         
00343         
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364                 
00365         
00366             status = mpClose(fd);
00367             if (this->MP_ERROR == status)
00368             {
00369                 LOG_WARN("Failed to close file: %s, ignoring failure", filename);
00370             }
00371     }
00372     else
00373     {
00374         LOG_ERROR("Failed to create job file: %s", filename);
00375         rtn = false;
00376     }
00377     
00378     
00379     return rtn;
00380 }
00381 #undef FILE_NAM_BUFFER_SIZE
00382 
00383 
00384 bool Controller::loadJob(char* path, char * job)
00385 {
00386     bool rtn = false;
00387     int status;    
00388     
00389     LOG_DEBUG("Refreshing file list");
00390     status = mpRefreshFileList(MP_EXT_ID_JBI);
00391     if (this->MP_OK != status)
00392     {
00393         LOG_WARN("Failed to refresh file list: %d, ignoring failure", status);
00394     }
00395     LOG_DEBUG("File count before file load: %d", mpGetFileCount());
00396     
00397     LOG_DEBUG("Attempting to load file, path: %s, job: %s", path, job);
00398     status = mpLoadFile (MP_DRV_ID_DRAM, path, job );
00399     if (this->MP_OK == status)
00400     {
00401         LOG_INFO("Loaded job file %s", job);
00402         rtn = true;
00403     }
00404     else
00405     {
00406         LOG_ERROR("Failed to load job file: %s, path: %s, returned error code: %d",
00407                     job, path, status);
00408         rtn = false;
00409     }
00410     
00411     LOG_DEBUG("Refreshing file list");
00412     status = mpRefreshFileList(MP_EXT_ID_JBI);
00413     if (this->MP_OK != status)
00414     {
00415         LOG_WARN("Failed to refresh file list: %d, ignoring failure", status);
00416     }
00417     LOG_DEBUG("File count after file load: %d", mpGetFileCount());
00418     
00419     return rtn;
00420 
00421 }
00422 
00423 
00424 void Controller::setDigitalOut(int bit_offset, bool value)
00425 {
00426   LOG_DEBUG("Setting digital out, Bit offset: %d, value: %d", bit_offset, value);
00427   if ( (bit_offset < this->UNIV_IO_DATA_SIZE_) && 
00428        ( bit_offset > 0) )
00429   {  
00430     MP_IO_DATA data;
00431     data.ulAddr = this->UNIV_OUT_DATA_START_ + bit_offset;
00432     data.ulValue = value;
00433     
00434     mpWriteIO(&data, 1);
00435   }
00436   else
00437   {
00438     LOG_ERROR("Bit offset: %d, is greater than size: %d", bit_offset, this->UNIV_IO_DATA_SIZE_);
00439   }
00440 }
00441 
00442  void Controller::waitDigitalIn(int bit_offset, bool wait_value)
00443  {
00444    LOG_DEBUG("Waiting for digital in, Bit offset: %d, Wait value: %d", bit_offset, wait_value);
00445    if ( (bit_offset < this->UNIV_IO_DATA_SIZE_) && 
00446        ( bit_offset > 0) )
00447   { 
00448     MP_IO_INFO info;
00449     info.ulAddr = this->UNIV_IN_DATA_START_ + bit_offset;
00450     
00451     USHORT readValue;
00452     do
00453     {
00454       readValue = !wait_value;  
00455       
00456       mpReadIO (&info, &readValue, 1);
00457       mpTaskDelay(VAR_POLL_DELAY_);
00458     } while ( ((bool)readValue) != wait_value);
00459   }
00460   else
00461   {
00462     LOG_ERROR("Bit offset: %d, is greater than size: %d", bit_offset, this->UNIV_IO_DATA_SIZE_);
00463   }
00464  }
00465  
00466 bool Controller::getActJointPos(float* pos)
00467 {
00468   int num_axes;
00469   LONG status = 0;
00470   MP_CTRL_GRP_SEND_DATA sData;
00471   MP_FB_PULSE_POS_RSP_DATA pulse_data;
00472   FB_AXIS_CORRECTION pulse_corr[MAX_PULSE_AXES];
00473   float pulses_per_rad[MAX_PULSE_AXES];
00474 
00475   memset(pos, 0, MAX_PULSE_AXES*sizeof(float));  
00476   
00477   
00478   if (!getFBPulseCorrection(pulse_corr)) return false;
00479   if (!getNumRobotAxes(&num_axes)) return false;
00480   if (!getPulsesPerRadian(pulses_per_rad)) return false;
00481   
00482   
00483   sData.sCtrlGrp = getCtrlGroup();
00484   status = mpGetFBPulsePos (&sData,&pulse_data);
00485   if (0 != status)
00486   {
00487     LOG_ERROR("Failed to get pulse feedback position: %u", status);
00488     return false;
00489   }
00490   
00491   
00492   for (int i=0; i<MAX_PULSE_AXES; ++i)
00493   {
00494     FB_AXIS_CORRECTION corr = pulse_corr[i];
00495     if (corr.bValid)
00496     {
00497       int src_axis = corr.ulSourceAxis;
00498       int dest_axis = corr.ulCorrectionAxis;
00499       pulse_data.lPos[dest_axis] -= (int)(pulse_data.lPos[src_axis] * corr.fCorrectionRatio);
00500     }
00501   }
00502   
00503   
00504   for (int i=0; i<num_axes; ++i)
00505     pos[i] = pulse_data.lPos[i] / pulses_per_rad[i];
00506     
00507   return true;
00508 }
00509 
00510 bool Controller::is_valid_ctrl_grp(int ctrl_grp)
00511 {
00512   bool valid = ((ctrl_grp >= 0) && (ctrl_grp < MAX_CTRL_GROUPS));
00513   if (!valid)
00514     LOG_ERROR("Invalid ctrl_grp (%d)", ctrl_grp);
00515   return valid;
00516 }
00517 
00518 bool Controller::getNumRobotAxes(int ctrl_grp, int* numAxes)
00519 {
00520   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00521  
00522   ctrl_grp_param_t& p = ctrl_grp_parameters_[ctrl_grp];
00523   
00524   
00525   if (!is_bit_set(p.initialized, GP_GETNUMBEROFAXES))
00526   {
00527     p.num_axes = GP_getNumberOfAxes(ctrl_grp);
00528     set_bit(&p.initialized, GP_GETNUMBEROFAXES);
00529   }
00530 
00531   *numAxes = p.num_axes;
00532   return (*numAxes >= 0);
00533 }
00534 
00535 bool Controller::getPulsesPerRadian(int ctrl_grp, float* pulses_per_radian)
00536 {
00537   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00538 
00539   ctrl_grp_param_t& p = ctrl_grp_parameters_[ctrl_grp];
00540   
00541   
00542   if (!is_bit_set(p.initialized, GP_GETPULSETORAD))
00543   {
00544     GB_PULSE_TO_RAD rData;
00545 
00546     if (GP_getPulseToRad(ctrl_grp, &rData) != OK)
00547     {
00548       LOG_ERROR("Failed to retrieve PulseToRadian parameters.");
00549       return false;
00550     }
00551     
00552     for (int i=0; i<MAX_PULSE_AXES; ++i)
00553       p.pulses_per_rad[i] = rData.PtoR[i];
00554     set_bit(&p.initialized, GP_GETPULSETORAD);
00555   }
00556 
00557   for (int i=0; i<MAX_PULSE_AXES; ++i)
00558     pulses_per_radian[i] = p.pulses_per_rad[i];
00559 
00560   return true;
00561 }
00562 
00563 bool Controller::getFBPulseCorrection(int ctrl_grp, FB_AXIS_CORRECTION* pulse_correction)
00564 {
00565   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00566 
00567   ctrl_grp_param_t& p = ctrl_grp_parameters_[ctrl_grp];
00568 
00569   
00570   if (!is_bit_set(p.initialized, GP_GETFBPULSECORRECTION))
00571   {
00572     FB_PULSE_CORRECTION_DATA rData;
00573 
00574     if (GP_getFBPulseCorrection(ctrl_grp, &rData) != OK)
00575     {
00576       LOG_ERROR("Failed to retrieve FBPulseCorrection parameters.");
00577       return false;
00578     }
00579     
00580     for (int i=0; i<MAX_PULSE_AXES; ++i)
00581       p.pulse_correction[i] = rData.correction[i];
00582     set_bit(&p.initialized, GP_GETFBPULSECORRECTION);
00583   }
00584 
00585   for (int i=0; i<MAX_PULSE_AXES; ++i)
00586     pulse_correction[i] = p.pulse_correction[i];
00587 
00588   return true;
00589 }
00590 
00591 bool Controller::getNumTasks(int* num_normal_tasks, int* num_highPrio_tasks, int* num_out_files)
00592 {
00593   sys_param_t& p = sys_parameters_;
00594 
00595   
00596   if (!is_bit_set(p.initialized, GP_GETQTYOFALLOWEDTASKS))
00597   {
00598     TASK_QTY_INFO rData;
00599 
00600     if (GP_getQtyOfAllowedTasks(&rData) != OK)
00601     {
00602       LOG_ERROR("Failed to retrieve QtyOfAllowedTasks parameters.");
00603       return false;
00604     }
00605     
00606     p.tasks = rData;
00607     set_bit(&p.initialized, GP_GETQTYOFALLOWEDTASKS);
00608   }
00609 
00610   *num_normal_tasks   = p.tasks.qtyOfNormalPriorityTasks;
00611   *num_highPrio_tasks = p.tasks.qtyOfHighPriorityTasks;
00612   *num_out_files      = p.tasks.qtyOfOutFiles;
00613 
00614   return true;
00615 }
00616 
00617 bool Controller::getInterpPeriod(UINT16* interp_period)
00618 {
00619   sys_param_t& p = sys_parameters_;
00620 
00621   
00622   if (!is_bit_set(p.initialized, GP_GETINTERPOLATIONPERIOD))
00623   {
00624     if (GP_getInterpolationPeriod(&(p.interp_period)) != OK)
00625     {
00626       LOG_ERROR("Failed to retrieve InterpolationPeriod parameters.");
00627       return false;
00628     }
00629     
00630     set_bit(&p.initialized, GP_GETINTERPOLATIONPERIOD);
00631   }
00632 
00633   *interp_period = p.interp_period;
00634   return true;
00635 }
00636 
00637 bool Controller::getMaxIncrPerCycle(int ctrl_grp, int* max_incr)
00638 {
00639   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00640 
00641   ctrl_grp_param_t& p = ctrl_grp_parameters_[ctrl_grp];
00642 
00643   
00644   if (!is_bit_set(p.initialized, GP_GETMAXINCPERIPCYCLE))
00645   {
00646     MAX_INCREMENT_INFO rData;
00647     UINT16 interp_period;
00648     if (!getInterpPeriod(&interp_period)) return false;
00649 
00650     if (GP_getMaxIncPerIpCycle(ctrl_grp, interp_period, &rData) != OK)
00651     {
00652       LOG_ERROR("Failed to retrieve MaxIncPerIpCycle parameters.");
00653       return false;
00654     }
00655     
00656     for (int i=0; i<MAX_PULSE_AXES; ++i)
00657       p.max_incr_per_cycle[i] = rData.maxIncrement[i];
00658     set_bit(&p.initialized, GP_GETMAXINCPERIPCYCLE);
00659   }
00660 
00661   for (int i=0; i<MAX_PULSE_AXES; ++i)
00662     max_incr[i] = p.max_incr_per_cycle[i];
00663 
00664   return true;
00665 }
00666 
00667 bool Controller::getIncrMotionLimit(int ctrl_grp, float* limit)
00668 {
00669   if (!is_valid_ctrl_grp(ctrl_grp)) return false;
00670 
00671   ctrl_grp_param_t& p = ctrl_grp_parameters_[ctrl_grp];
00672 
00673   
00674   if (!is_bit_set(p.initialized, GP_GETGOVFORINCMOTION))
00675   {
00676     p.incr_motion_limit = GP_getGovForIncMotion(ctrl_grp);
00677     set_bit(&p.initialized, GP_GETGOVFORINCMOTION);
00678   }
00679 
00680   *limit = p.incr_motion_limit;
00681   return (*limit >= 0);
00682 }
00683 
00684 
00685 } 
00686 }