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 }