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
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051 #include <youbot_driver/youbot/YouBotJoint.hpp>
00052 namespace youbot
00053 {
00054
00055 YouBotJoint::YouBotJoint(const unsigned int jointNo, const std::string& configFilePath)
00056 {
00057
00058 this->storage.jointNumber = jointNo;
00059 timeTillNextMailboxUpdate = 1;
00060 mailboxMsgRetries = 100;
00061 this->storage.inverseMovementDirection = false;
00062 this->storage.lowerLimit = 0;
00063 this->storage.upperLimit = 0;
00064 this->storage.areLimitsActive = false;
00065 std::stringstream jointNameStream;
00066 jointNameStream << "Joint " << this->storage.jointNumber << " ";
00067 this->storage.jointNumberStr = jointNameStream.str();
00068 ethercatMaster = &(EthercatMaster::getInstance("youbot-ethercat.cfg", configFilePath));
00069
00070
00071 }
00072
00073 YouBotJoint::~YouBotJoint()
00074 {
00075
00076
00077 }
00078
00079 void YouBotJoint::setConfigurationParameter(const JointParameter& parameter)
00080 {
00081
00082 throw std::runtime_error("Please use YouBotJointParameters");
00083
00084 }
00085
00086 void YouBotJoint::getConfigurationParameter(JointParameter& parameter)
00087 {
00088
00089 throw std::runtime_error("Please use YouBotJointParameters");
00090
00091 }
00092
00093 void YouBotJoint::getConfigurationParameter(YouBotJointParameterReadOnly& parameter)
00094 {
00095
00096
00097 if (parameter.getType() == MOTOR_CONTOLLER_PARAMETER)
00098 {
00099
00100 YouBotSlaveMailboxMsg message;
00101 parameter.getYouBotMailboxMsg(message, GAP, storage);
00102
00103 message.parameterName = parameter.getName();
00104 if (retrieveValueFromMotorContoller(message))
00105 {
00106 parameter.setYouBotMailboxMsg(message, storage);
00107 }
00108 else
00109 {
00110 throw JointParameterException(
00111 "Unable to get parameter: " + parameter.getName() + " from joint: " + this->storage.jointName);
00112 }
00113 }
00114 else
00115 {
00116 throw JointParameterException(
00117 "Parameter " + parameter.getName() + " is not a motor controller parameter of a joint");
00118 }
00119
00120 }
00121
00122 void YouBotJoint::getConfigurationParameter(YouBotJointParameter& parameter)
00123 {
00124
00125 if (parameter.getType() == MOTOR_CONTOLLER_PARAMETER)
00126 {
00127
00128 YouBotSlaveMailboxMsg message;
00129 parameter.getYouBotMailboxMsg(message, GAP, storage);
00130
00131 message.parameterName = parameter.getName();
00132 if (retrieveValueFromMotorContoller(message))
00133 {
00134 parameter.setYouBotMailboxMsg(message, storage);
00135 }
00136 else
00137 {
00138 throw JointParameterException(
00139 "Unable to get parameter: " + parameter.getName() + " from joint: " + this->storage.jointName);
00140 }
00141 }
00142 else
00143 {
00144 throw JointParameterException(
00145 "Parameter " + parameter.getName() + " is not a motor controller parameter of a joint");
00146 }
00147
00148 }
00149
00150 void YouBotJoint::setConfigurationParameter(const YouBotJointParameter& parameter)
00151 {
00152
00153 if (parameter.getType() == MOTOR_CONTOLLER_PARAMETER)
00154 {
00155
00156 YouBotSlaveMailboxMsg message;
00157 parameter.getYouBotMailboxMsg(message, SAP, storage);
00158
00159 message.parameterName = parameter.getName();
00160 if (!setValueToMotorContoller(message))
00161 {
00162 throw JointParameterException(
00163 "Unable to set parameter: " + parameter.getName() + " to joint: " + this->storage.jointName);
00164 }
00165 }
00166 else
00167 {
00168 throw JointParameterException(
00169 "Parameter " + parameter.getName() + " is not a motor controller parameter of a joint");
00170 }
00171
00172 }
00173
00174 void YouBotJoint::getConfigurationParameter(JointName& parameter)
00175 {
00176
00177 parameter.value = this->storage.jointName;
00178
00179 }
00180
00181 void YouBotJoint::setConfigurationParameter(const JointName& parameter)
00182 {
00183
00184 this->storage.jointName = parameter.value;
00185
00186 }
00187
00188 void YouBotJoint::getConfigurationParameter(GearRatio& parameter)
00189 {
00190
00191 parameter.setParameter(this->storage.gearRatio);
00192
00193 }
00194
00195 void YouBotJoint::setConfigurationParameter(const GearRatio& parameter)
00196 {
00197
00198 if (parameter.value == 0)
00199 {
00200 throw std::out_of_range("A Gear Ratio of zero is not allowed");
00201 }
00202 this->storage.gearRatio = parameter.value;
00203
00204 }
00205
00206 void YouBotJoint::getConfigurationParameter(EncoderTicksPerRound& parameter)
00207 {
00208
00209 parameter.setParameter(this->storage.encoderTicksPerRound);
00210
00211 }
00212
00213 void YouBotJoint::setConfigurationParameter(const EncoderTicksPerRound& parameter)
00214 {
00215
00216 if (parameter.value == 0)
00217 {
00218 throw std::out_of_range("Zero Encoder Ticks per Round are not allowed");
00219 }
00220 this->storage.encoderTicksPerRound = parameter.value;
00221
00222 }
00223
00224 void YouBotJoint::setConfigurationParameter(const CalibrateJoint& parameter)
00225 {
00226
00227 if (parameter.doCalibration)
00228 {
00229 LOG(info) << "Calibrate Joint: " << this->storage.jointName;
00230
00231 int calibrationVel = 0;
00232
00233 messageBuffer.stctOutput.controllerMode = VELOCITY_CONTROL;
00234 if (parameter.calibrationDirection == POSITIV)
00235 {
00236 calibrationVel = 1.0 / storage.gearRatio;
00237 }
00238 else if (parameter.calibrationDirection == NEGATIV)
00239 {
00240 calibrationVel = -1.0 / storage.gearRatio;
00241 }
00242 else
00243 {
00244 throw std::runtime_error("No calibration direction for joint: " + this->storage.jointName);
00245 }
00246
00247 if (this->storage.inverseMovementDirection == true)
00248 {
00249 calibrationVel *= -1;
00250 }
00251
00252 JointSensedCurrent sensedCurrent;
00253
00254 messageBuffer.stctOutput.controllerMode = VELOCITY_CONTROL;
00255 messageBuffer.stctOutput.value = calibrationVel;
00256 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00257
00258 sensedCurrent.current = 0;
00259
00260 while (abs(sensedCurrent.current) < abs(parameter.maxCurrent))
00261 {
00262 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
00263 this->getData(sensedCurrent);
00264 }
00265
00266
00267 messageBuffer.stctOutput.controllerMode = VELOCITY_CONTROL;
00268 messageBuffer.stctOutput.value = 0;
00269
00270 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00271
00272
00273 SLEEP_MILLISEC(500);
00274 messageBuffer.stctOutput.controllerMode = SET_POSITION_TO_REFERENCE;
00275 messageBuffer.stctOutput.value = 0;
00276 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00277
00278
00279 SLEEP_MILLISEC(100);
00280 messageBuffer.stctOutput.controllerMode = POSITION_CONTROL;
00281 messageBuffer.stctOutput.value = 0;
00282
00283 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00284
00285
00286 }
00287
00288
00289 }
00290
00291 void YouBotJoint::setConfigurationParameter(const InverseMovementDirection& parameter)
00292 {
00293
00294 this->storage.inverseMovementDirection = parameter.value;
00295
00296 }
00297
00298 void YouBotJoint::getConfigurationParameter(InverseMovementDirection& parameter)
00299 {
00300
00301 parameter.setParameter(this->storage.inverseMovementDirection);
00302
00303 }
00304
00305 void YouBotJoint::setConfigurationParameter(const JointLimits& parameter)
00306 {
00307
00308
00309 this->storage.lowerLimit = parameter.lowerLimit;
00310 this->storage.upperLimit = parameter.upperLimit;
00311 this->storage.areLimitsActive = parameter.areLimitsActive;
00312 MotorAcceleration acc;
00313 quantity<angular_acceleration> accValue;
00314
00315 if (this->storage.areLimitsActive)
00316 {
00317 this->getConfigurationParameter(acc);
00318 acc.getParameter(accValue);
00319 this->limitMonitor.reset(new JointLimitMonitor(this->storage, accValue));
00320 ethercatMaster->registerJointLimitMonitor(this->limitMonitor.get(), this->storage.jointNumber);
00321 }
00322 else
00323 {
00324 this->limitMonitor.reset(NULL);
00325 }
00326
00327
00328
00329 }
00330
00331 void YouBotJoint::getConfigurationParameter(JointLimits& parameter)
00332 {
00333
00334 parameter.setParameter(this->storage.lowerLimit, this->storage.upperLimit, this->storage.areLimitsActive);
00335
00336 }
00337
00338 void YouBotJoint::getConfigurationParameter(JointLimitsRadian& parameter)
00339 {
00340
00341 quantity<plane_angle> lowlimit = ((double)this->storage.lowerLimit / storage.encoderTicksPerRound) * storage.gearRatio
00342 * (2.0 * M_PI) * radian;
00343 quantity<plane_angle> uplimit = ((double)this->storage.upperLimit / storage.encoderTicksPerRound) * storage.gearRatio
00344 * (2.0 * M_PI) * radian;
00345 parameter.setParameter(lowlimit, uplimit, this->storage.areLimitsActive);
00346
00347 }
00348
00350 void YouBotJoint::setConfigurationParameter(const InitializeJoint& parameter)
00351 {
00352
00353 if (parameter.value)
00354 {
00355 messageBuffer.stctOutput.controllerMode = INITIALIZE;
00356 messageBuffer.stctOutput.value = 0;
00357
00358 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00359 }
00360
00361 }
00362
00363 void YouBotJoint::getConfigurationParameter(FirmwareVersion& parameter)
00364 {
00365
00366
00367 YouBotSlaveMailboxMsg message;
00368 parameter.getYouBotMailboxMsg(message, GAP, storage);
00369
00370 bool unvalid = true;
00371 unsigned int retry = 0;
00372
00373 ethercatMaster->setMailboxMsgBuffer(message, this->storage.jointNumber);
00374
00375 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
00376
00377 do
00378 {
00379 if (ethercatMaster->getMailboxMsgBuffer(message, this->storage.jointNumber))
00380 {
00381 unvalid = false;
00382 }
00383 else
00384 {
00385 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
00386 retry++;
00387 }
00388 } while (retry < mailboxMsgRetries && unvalid);
00389
00390 if (unvalid)
00391 {
00392 this->parseMailboxStatusFlags(message);
00393 throw std::runtime_error("Unable to get firmware version for joint: " + this->storage.jointName);
00394 return;
00395 }
00396
00397 char versionString[9] = {0};
00398 versionString[0] = message.stctInput.replyAddress;
00399 versionString[1] = message.stctInput.moduleAddress;
00400 versionString[2] = message.stctInput.status;
00401 versionString[3] = message.stctInput.commandNumber;
00402 versionString[4] = message.stctInput.value >> 24;
00403 versionString[5] = message.stctInput.value >> 16;
00404 versionString[6] = message.stctInput.value >> 8;
00405 versionString[7] = message.stctInput.value & 0xff;
00406
00407 int controllerType = 0;
00408 char firmwareVersion[9] = {0};
00409 sscanf(versionString, "%dV%s", &controllerType, firmwareVersion);
00410 std::string version(firmwareVersion);
00411 size_t founddot = version.find(".");
00412 while (founddot != std::string::npos)
00413 {
00414 version.erase(founddot, 1);
00415 founddot = version.find(".");
00416 }
00417 parameter.setParameter(controllerType, version);
00418 return;
00419
00420 }
00421
00423 void YouBotJoint::setConfigurationParameter(const YouBotSlaveMailboxMsg& parameter)
00424 {
00425
00426 if (!setValueToMotorContoller(parameter))
00427 {
00428 throw JointParameterException("Unable to set parameter at joint: " + this->storage.jointName);
00429 }
00430
00431 }
00432
00434 void YouBotJoint::getConfigurationParameter(YouBotSlaveMailboxMsg& parameter)
00435 {
00436
00437 if (!retrieveValueFromMotorContoller(parameter))
00438 {
00439 throw JointParameterException("Unable to get parameter from joint: " + this->storage.jointName);
00440 }
00441 this->parseMailboxStatusFlags(parameter);
00442
00443 }
00444
00445 void YouBotJoint::getConfigurationParameter(TorqueConstant& parameter)
00446 {
00447
00448 parameter.setParameter(this->storage.torqueConstant);
00449
00450 }
00451
00452 void YouBotJoint::setConfigurationParameter(const TorqueConstant& parameter)
00453 {
00454
00455 parameter.getParameter(this->storage.torqueConstant);
00456
00457 }
00458
00461 void YouBotJoint::storeConfigurationParameterPermanent(const YouBotJointParameter& parameter)
00462 {
00463
00464 if (parameter.getType() == MOTOR_CONTOLLER_PARAMETER)
00465 {
00466
00467 this->setConfigurationParameter(parameter);
00468
00469 YouBotSlaveMailboxMsg message;
00470 parameter.getYouBotMailboxMsg(message, STAP, storage);
00471
00472 if (!setValueToMotorContoller(message))
00473 {
00474 throw JointParameterException(
00475 "Unable to store parameter: " + parameter.getName() + " to joint: " + this->storage.jointName);
00476 }
00477 }
00478 else
00479 {
00480 throw JointParameterException(
00481 "Parameter " + parameter.getName() + " is not a motor controller parameter of a joint");
00482 }
00483
00484 }
00485
00487 void YouBotJoint::restoreConfigurationParameter(YouBotJointParameter& parameter)
00488 {
00489
00490 if (parameter.getType() == MOTOR_CONTOLLER_PARAMETER)
00491 {
00492
00493 YouBotSlaveMailboxMsg message;
00494 parameter.getYouBotMailboxMsg(message, RSAP, storage);
00495
00496 if (!setValueToMotorContoller(message))
00497 {
00498 throw JointParameterException(
00499 "Unable to restore parameter: " + parameter.getName() + " at joint: " + this->storage.jointName);
00500 }
00501
00502 this->getConfigurationParameter(parameter);
00503 }
00504 else
00505 {
00506 throw JointParameterException(
00507 "Parameter " + parameter.getName() + " is not a motor controller parameter of a joint");
00508 }
00509
00510 }
00511
00512 void YouBotJoint::setData(const JointDataSetpoint& data)
00513 {
00514
00515 LOG(info) << "Nothing to do";
00516
00517 }
00518
00519 void YouBotJoint::getData(JointData& data)
00520 {
00521
00522 LOG(info) << "Nothing to do";
00523
00524 }
00525
00528 void YouBotJoint::setData(const JointAngleSetpoint& data)
00529 {
00530
00531
00532 if (!ethercatMaster->isEtherCATConnectionEstablished())
00533 {
00534 throw EtherCATConnectionException("No EtherCAT connection");
00535 }
00536
00537
00538 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00539 this->parseYouBotErrorFlags(messageBuffer);
00540
00541 if (storage.gearRatio == 0)
00542 {
00543 throw std::out_of_range("A Gear Ratio of zero is not allowed");
00544 }
00545
00546 if (storage.encoderTicksPerRound == 0)
00547 {
00548 throw std::out_of_range("Zero Encoder Ticks per Round are not allowed");
00549 }
00550
00551 if (this->limitMonitor != 0)
00552 this->limitMonitor->checkLimitsPositionControl(data.angle);
00553
00554 messageBuffer.stctOutput.controllerMode = POSITION_CONTROL;
00555 messageBuffer.stctOutput.value = (int32)round(
00556 (data.angle.value() * ((double)storage.encoderTicksPerRound / (2.0 * M_PI))) / storage.gearRatio);
00557
00558 if (storage.inverseMovementDirection)
00559 {
00560 messageBuffer.stctOutput.value *= -1;
00561 }
00562
00563 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00564
00565 }
00566
00569 void YouBotJoint::setData(const JointEncoderSetpoint& data)
00570 {
00571
00572
00573 if (!ethercatMaster->isEtherCATConnectionEstablished())
00574 {
00575 throw EtherCATConnectionException("No EtherCAT connection");
00576 }
00577
00578
00579 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00580 this->parseYouBotErrorFlags(messageBuffer);
00581
00582 if (this->limitMonitor != 0)
00583 this->limitMonitor->checkLimitsEncoderPosition(data.encoderTicks);
00584
00585 messageBuffer.stctOutput.controllerMode = POSITION_CONTROL;
00586 messageBuffer.stctOutput.value = data.encoderTicks;
00587
00588 if (storage.inverseMovementDirection)
00589 {
00590 messageBuffer.stctOutput.value *= -1;
00591 }
00592
00593 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00594
00595 }
00596
00599 void YouBotJoint::getData(JointSensedAngle& data)
00600 {
00601
00602
00603 if (!ethercatMaster->isEtherCATConnectionEstablished())
00604 {
00605 throw EtherCATConnectionException("No EtherCAT connection");
00606 }
00607
00608 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00609 this->parseYouBotErrorFlags(messageBuffer);
00610
00611 if (storage.gearRatio == 0)
00612 {
00613 throw std::out_of_range("A Gear Ratio of zero is not allowed");
00614 }
00615 if (storage.encoderTicksPerRound == 0)
00616 {
00617 throw std::out_of_range("Zero Encoder Ticks per Round are not allowed");
00618 }
00619
00620 data.angle = ((double)messageBuffer.stctInput.actualPosition / storage.encoderTicksPerRound) * storage.gearRatio
00621 * (2.0 * M_PI) * radian;
00622
00623 if (storage.inverseMovementDirection)
00624 {
00625 data.angle = -data.angle;
00626 }
00627
00628 }
00629
00632 void YouBotJoint::setData(const JointVelocitySetpoint& data)
00633 {
00634
00635 if (!ethercatMaster->isEtherCATConnectionEstablished())
00636 {
00637 throw EtherCATConnectionException("No EtherCAT connection");
00638 }
00639
00640
00641 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00642 this->parseYouBotErrorFlags(messageBuffer);
00643
00644 messageBuffer.stctOutput.controllerMode = VELOCITY_CONTROL;
00645
00646 if (storage.gearRatio == 0)
00647 {
00648 throw std::out_of_range("A Gear Ratio of 0 is not allowed");
00649 }
00650
00651 messageBuffer.stctOutput.value = (int32)round(
00652 (data.angularVelocity.value() / (storage.gearRatio * 2.0 * M_PI)) * 60.0);
00653 if (storage.inverseMovementDirection)
00654 {
00655 messageBuffer.stctOutput.value *= -1;
00656 }
00657
00658
00659 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00660
00661 }
00662
00665 void YouBotJoint::getData(JointSensedVelocity& data)
00666 {
00667
00668 if (!ethercatMaster->isEtherCATConnectionEstablished())
00669 {
00670 throw EtherCATConnectionException("No EtherCAT connection");
00671 }
00672
00673
00674 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00675 this->parseYouBotErrorFlags(messageBuffer);
00676
00677 if (storage.gearRatio == 0)
00678 {
00679 throw std::out_of_range("A Gear Ratio of 0 is not allowed");
00680 }
00681 double motorRPM = messageBuffer.stctInput.actualVelocity;
00682
00683 data.angularVelocity = ((motorRPM / 60.0) * storage.gearRatio * 2.0 * M_PI) * radian_per_second;
00684
00685 if (storage.inverseMovementDirection)
00686 {
00687 data.angularVelocity *= -1;
00688 }
00689
00690 }
00691
00694 void YouBotJoint::getData(JointSensedRoundsPerMinute& data)
00695 {
00696
00697 if (!ethercatMaster->isEtherCATConnectionEstablished())
00698 {
00699 throw EtherCATConnectionException("No EtherCAT connection");
00700 }
00701
00702
00703 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00704 this->parseYouBotErrorFlags(messageBuffer);
00705
00706 data.rpm = messageBuffer.stctInput.actualVelocity;
00707
00708 if (storage.inverseMovementDirection)
00709 {
00710 data.rpm *= -1;
00711 }
00712
00713 }
00714
00717 void YouBotJoint::setData(const JointRoundsPerMinuteSetpoint& data)
00718 {
00719
00720 if (!ethercatMaster->isEtherCATConnectionEstablished())
00721 {
00722 throw EtherCATConnectionException("No EtherCAT connection");
00723 }
00724
00725
00726 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00727 this->parseYouBotErrorFlags(messageBuffer);
00728
00729 messageBuffer.stctOutput.controllerMode = VELOCITY_CONTROL;
00730 messageBuffer.stctOutput.value = data.rpm;
00731
00732 if (storage.inverseMovementDirection)
00733 {
00734 messageBuffer.stctOutput.value *= -1;
00735 }
00736
00737 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00738
00739 }
00740
00743 void YouBotJoint::getData(JointSensedCurrent& data)
00744 {
00745
00746 if (!ethercatMaster->isEtherCATConnectionEstablished())
00747 {
00748 throw EtherCATConnectionException("No EtherCAT connection");
00749 }
00750
00751
00752 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00753 this->parseYouBotErrorFlags(messageBuffer);
00754
00755 double current = messageBuffer.stctInput.actualCurrent;
00756 data.current = current / 1000.0 * ampere;
00757
00758 if (storage.inverseMovementDirection)
00759 {
00760 data.current *= -1;
00761 }
00762
00763 }
00764
00767 void YouBotJoint::setData(const JointCurrentSetpoint& data)
00768 {
00769
00770 if (!ethercatMaster->isEtherCATConnectionEstablished())
00771 {
00772 throw EtherCATConnectionException("No EtherCAT connection");
00773 }
00774
00775
00776 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00777 this->parseYouBotErrorFlags(messageBuffer);
00778
00779 messageBuffer.stctOutput.controllerMode = CURRENT_MODE;
00780 messageBuffer.stctOutput.value = (int32)(data.current.value() * 1000.0);
00781
00782 if (storage.inverseMovementDirection)
00783 {
00784 messageBuffer.stctOutput.value *= -1;
00785 }
00786 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00787
00788 }
00789
00792 void YouBotJoint::getData(JointSensedEncoderTicks& data)
00793 {
00794
00795 if (!ethercatMaster->isEtherCATConnectionEstablished())
00796 {
00797 throw EtherCATConnectionException("No EtherCAT connection");
00798 }
00799
00800
00801 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00802 this->parseYouBotErrorFlags(messageBuffer);
00803
00804
00805 data.encoderTicks = messageBuffer.stctInput.actualPosition;
00806
00807 if (storage.inverseMovementDirection)
00808 {
00809 data.encoderTicks *= -1;
00810 }
00811
00812
00813 }
00814
00818 void YouBotJoint::setData(const SlaveMessageOutput& data)
00819 {
00820
00821
00822 if (!ethercatMaster->isEtherCATConnectionEstablished())
00823 {
00824 throw EtherCATConnectionException("No EtherCAT connection");
00825 }
00826
00827 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00828 this->parseYouBotErrorFlags(messageBuffer);
00829
00830 messageBuffer.stctOutput = data;
00831
00832 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
00833
00834 }
00835
00839 void YouBotJoint::getData(YouBotSlaveMsg& data)
00840 {
00841
00842
00843 if (!ethercatMaster->isEtherCATConnectionEstablished())
00844 {
00845 throw EtherCATConnectionException("No EtherCAT connection");
00846 }
00847
00848 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00849 this->parseYouBotErrorFlags(messageBuffer);
00850
00851 data = messageBuffer;
00852
00853 }
00854
00857 void YouBotJoint::setData(const JointTorqueSetpoint& data)
00858 {
00859
00860 if (!ethercatMaster->isEtherCATConnectionEstablished())
00861 {
00862 throw EtherCATConnectionException("No EtherCAT connection");
00863 }
00864
00865 JointCurrentSetpoint currentSetpoint;
00866
00867 if (this->storage.torqueConstant == 0)
00868 {
00869 throw std::out_of_range("A torque constant of 0 is not allowed");
00870 }
00871
00872 currentSetpoint.current = ((data.torque.value() * this->storage.gearRatio) / this->storage.torqueConstant) * ampere;
00873 this->setData(currentSetpoint);
00874
00875 }
00876
00879 void YouBotJoint::getData(JointSensedTorque& data)
00880 {
00881
00882 if (!ethercatMaster->isEtherCATConnectionEstablished())
00883 {
00884 throw EtherCATConnectionException("No EtherCAT connection");
00885 }
00886
00887 JointSensedCurrent sensedCurrent;
00888 this->getData(sensedCurrent);
00889
00890 if (this->storage.gearRatio == 0)
00891 {
00892 throw std::out_of_range("A Gear Ratio of 0 is not allowed");
00893 }
00894 data.torque = ((sensedCurrent.current.value() * this->storage.torqueConstant) / this->storage.gearRatio)
00895 * newton_meter;
00896
00897 }
00898
00901 void YouBotJoint::getData(JointAngleSetpoint& data)
00902 {
00903
00904
00905 if (!ethercatMaster->isEtherCATConnectionEstablished())
00906 {
00907 throw EtherCATConnectionException("No EtherCAT connection");
00908 }
00909
00910 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00911 this->parseYouBotErrorFlags(messageBuffer);
00912
00913 if (storage.gearRatio == 0)
00914 {
00915 throw std::out_of_range("A Gear Ratio of zero is not allowed");
00916 }
00917 if (storage.encoderTicksPerRound == 0)
00918 {
00919 throw std::out_of_range("Zero Encoder Ticks per Round are not allowed");
00920 }
00921
00922 data.angle = ((double)messageBuffer.stctInput.targetPosition / storage.encoderTicksPerRound) * storage.gearRatio
00923 * (2.0 * M_PI) * radian;
00924
00925 if (storage.inverseMovementDirection)
00926 {
00927 data.angle = -data.angle;
00928 }
00929
00930 }
00931
00934 void YouBotJoint::getData(JointVelocitySetpoint& data)
00935 {
00936
00937 if (!ethercatMaster->isEtherCATConnectionEstablished())
00938 {
00939 throw EtherCATConnectionException("No EtherCAT connection");
00940 }
00941
00942
00943 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00944 this->parseYouBotErrorFlags(messageBuffer);
00945
00946 if (storage.gearRatio == 0)
00947 {
00948 throw std::out_of_range("A Gear Ratio of 0 is not allowed");
00949 }
00950 double motorRPM = messageBuffer.stctInput.targetVelocity;
00951
00952 data.angularVelocity = ((motorRPM / 60.0) * storage.gearRatio * 2.0 * M_PI) * radian_per_second;
00953
00954 if (storage.inverseMovementDirection)
00955 {
00956 data.angularVelocity *= -1;
00957 }
00958
00959 }
00960
00963 void YouBotJoint::getData(JointCurrentSetpoint& data)
00964 {
00965
00966 if (!ethercatMaster->isEtherCATConnectionEstablished())
00967 {
00968 throw EtherCATConnectionException("No EtherCAT connection");
00969 }
00970
00971
00972 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00973 this->parseYouBotErrorFlags(messageBuffer);
00974
00975 double current = messageBuffer.stctInput.targetCurrent;
00976 data.current = current / 1000.0 * ampere;
00977
00978 if (storage.inverseMovementDirection)
00979 {
00980 data.current *= -1;
00981 }
00982
00983 }
00984
00987 void YouBotJoint::getData(JointRampGeneratorVelocity& data)
00988 {
00989
00990 if (!ethercatMaster->isEtherCATConnectionEstablished())
00991 {
00992 throw EtherCATConnectionException("No EtherCAT connection");
00993 }
00994
00995
00996 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
00997 this->parseYouBotErrorFlags(messageBuffer);
00998
00999 if (storage.gearRatio == 0)
01000 {
01001 throw std::out_of_range("A Gear Ratio of 0 is not allowed");
01002 }
01003 double motorRPM = messageBuffer.stctInput.rampGeneratorVelocity;
01004
01005 data.angularVelocity = ((motorRPM / 60.0) * storage.gearRatio * 2.0 * M_PI) * radian_per_second;
01006
01007 if (storage.inverseMovementDirection)
01008 {
01009 data.angularVelocity *= -1;
01010 }
01011
01012 }
01013
01014 void YouBotJoint::getUserVariable(const unsigned int index, int& data)
01015 {
01016
01017
01018 if (index == 0 || index > 55)
01019 {
01020 throw JointParameterException("User variable index is out of range use 1-55 at: " + this->storage.jointName);
01021 }
01022
01023 YouBotSlaveMailboxMsg message;
01024 message.stctOutput.moduleAddress = DRIVE;
01025 message.stctOutput.commandNumber = GGP;
01026 message.stctOutput.typeNumber = index;
01027 message.stctOutput.motorNumber = USER_VARIABLE_BANK;
01028 message.stctOutput.value = 0;
01029
01030 if (!retrieveValueFromMotorContoller(message))
01031 {
01032 throw JointParameterException("Unable to get parameter from joint: " + this->storage.jointName);
01033 }
01034 this->parseMailboxStatusFlags(message);
01035
01036 data = message.stctInput.value;
01037
01038 }
01039
01040 void YouBotJoint::setUserVariable(const unsigned int index, const int data)
01041 {
01042
01043
01044 if (index < 17 || index > 55)
01045 {
01046 throw JointParameterException("User variable index is out of range use 17-55 at: " + this->storage.jointName);
01047 }
01048
01049 YouBotSlaveMailboxMsg message;
01050 message.stctOutput.moduleAddress = DRIVE;
01051 message.stctOutput.commandNumber = GGP;
01052 message.stctOutput.typeNumber = index;
01053 message.stctOutput.motorNumber = USER_VARIABLE_BANK;
01054 message.stctOutput.value = data;
01055
01056 if (!setValueToMotorContoller(message))
01057 {
01058 throw JointParameterException("Unable to set parameter at joint: " + this->storage.jointName);
01059 }
01060 this->parseMailboxStatusFlags(message);
01061
01062 }
01063
01065 void YouBotJoint::getStatus(std::vector<std::string>& statusMessages)
01066 {
01067
01068
01069 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
01070
01071 if (messageBuffer.stctInput.errorFlags & OVER_CURRENT)
01072 {
01073 statusMessages.push_back(this->storage.jointName + " got over current");
01074 }
01075
01076 if (messageBuffer.stctInput.errorFlags & UNDER_VOLTAGE)
01077 {
01078 statusMessages.push_back(this->storage.jointName + " got under voltage");
01079 }
01080
01081 if (messageBuffer.stctInput.errorFlags & OVER_VOLTAGE)
01082 {
01083 statusMessages.push_back(this->storage.jointName + " got over voltage");
01084 }
01085
01086 if (messageBuffer.stctInput.errorFlags & OVER_TEMPERATURE)
01087 {
01088 statusMessages.push_back(this->storage.jointName + " got over temperature");
01089 }
01090
01091 if (messageBuffer.stctInput.errorFlags & MOTOR_HALTED)
01092 {
01093 statusMessages.push_back(this->storage.jointName + " is halted");
01094 }
01095
01096 if (messageBuffer.stctInput.errorFlags & HALL_SENSOR_ERROR)
01097 {
01098 statusMessages.push_back(this->storage.jointName + " got hall sensor problem");
01099 }
01100
01101
01102
01103
01104
01105
01106
01107
01108
01109
01110
01111
01112
01113 if (messageBuffer.stctInput.errorFlags & VELOCITY_MODE)
01114 {
01115 statusMessages.push_back(this->storage.jointName + " has velocity mode active");
01116 }
01117
01118 if (messageBuffer.stctInput.errorFlags & POSITION_MODE)
01119 {
01120 statusMessages.push_back(this->storage.jointName + " has position mode active");
01121 }
01122
01123 if (messageBuffer.stctInput.errorFlags & TORQUE_MODE)
01124 {
01125 statusMessages.push_back(this->storage.jointName + " has torque mode active");
01126 }
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136 if (messageBuffer.stctInput.errorFlags & POSITION_REACHED)
01137 {
01138 statusMessages.push_back(this->storage.jointName + " has position reached");
01139 }
01140
01141 if (messageBuffer.stctInput.errorFlags & INITIALIZED)
01142 {
01143 statusMessages.push_back(this->storage.jointName + " is initialized");
01144 }
01145
01146 if (messageBuffer.stctInput.errorFlags & TIMEOUT)
01147 {
01148 statusMessages.push_back(this->storage.jointName + " has a timeout");
01149 }
01150
01151 if (messageBuffer.stctInput.errorFlags & I2T_EXCEEDED)
01152 {
01153 statusMessages.push_back(this->storage.jointName + " exceeded I2t");
01154 }
01155
01156
01157 }
01158
01178 void YouBotJoint::getStatus(unsigned int& statusFlags)
01179 {
01180
01181
01182 ethercatMaster->getMsgBuffer(this->storage.jointNumber, messageBuffer);
01183
01184 statusFlags = messageBuffer.stctInput.errorFlags;
01185
01186 }
01187
01189 void YouBotJoint::setEncoderToZero()
01190 {
01191
01192 if (!ethercatMaster->isEtherCATConnectionEstablished())
01193 {
01194 throw EtherCATConnectionException("No EtherCAT connection");
01195 }
01196
01197 YouBotSlaveMailboxMsg message;
01198 message.stctOutput.commandNumber = SAP;
01199 message.stctOutput.moduleAddress = DRIVE;
01200 message.stctOutput.typeNumber = 1;
01201 message.stctOutput.value = 0;
01202
01203 if (!setValueToMotorContoller(message))
01204 {
01205 throw JointParameterException("Unable to set the encoders to zero at joint: " + this->storage.jointName);
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215 }
01216
01217 void YouBotJoint::noMoreAction()
01218 {
01219
01220 if (!ethercatMaster->isEtherCATConnectionEstablished())
01221 {
01222 throw EtherCATConnectionException("No EtherCAT connection");
01223 }
01224
01225
01226 messageBuffer.stctOutput.controllerMode = NO_MORE_ACTION;
01227 messageBuffer.stctOutput.value = 0;
01228
01229 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
01230
01231 }
01232
01233 void YouBotJoint::stopJoint()
01234 {
01235
01236 if (!ethercatMaster->isEtherCATConnectionEstablished())
01237 {
01238 throw EtherCATConnectionException("No EtherCAT connection");
01239 }
01240
01241
01242 messageBuffer.stctOutput.controllerMode = MOTOR_STOP;
01243 messageBuffer.stctOutput.value = 0;
01244
01245 ethercatMaster->setMsgBuffer(messageBuffer, this->storage.jointNumber);
01246
01247 }
01248
01249 unsigned int YouBotJoint::getJointNumber()
01250 {
01251
01252 return this->storage.jointNumber;
01253
01254 }
01255
01256 void YouBotJoint::parseYouBotErrorFlags(const YouBotSlaveMsg& messageBuffer)
01257 {
01258
01259
01260 if (messageBuffer.stctInput.errorFlags & OVER_CURRENT)
01261 {
01262 LOG(warning) << this->storage.jointName << " over current";
01263
01264 }
01265
01266 if (messageBuffer.stctInput.errorFlags & UNDER_VOLTAGE)
01267 {
01268 LOG(warning) << this->storage.jointName << " under voltage";
01269
01270 }
01271
01272 if (messageBuffer.stctInput.errorFlags & OVER_VOLTAGE)
01273 {
01274 LOG(warning) << this->storage.jointName << " over voltage";
01275
01276 }
01277
01278 if (messageBuffer.stctInput.errorFlags & OVER_TEMPERATURE)
01279 {
01280 LOG(warning) << this->storage.jointName << " over temperature";
01281
01282 }
01283
01284 if (messageBuffer.stctInput.errorFlags & MOTOR_HALTED)
01285 {
01286
01287
01288 }
01289
01290 if (messageBuffer.stctInput.errorFlags & HALL_SENSOR_ERROR)
01291 {
01292 LOG(warning) << this->storage.jointName << " hall sensor problem";
01293
01294 }
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311 if (messageBuffer.stctInput.errorFlags & VELOCITY_MODE)
01312 {
01313
01314
01315 }
01316
01317 if (messageBuffer.stctInput.errorFlags & POSITION_MODE)
01318 {
01319
01320
01321 }
01322
01323 if (messageBuffer.stctInput.errorFlags & TORQUE_MODE)
01324 {
01325
01326
01327 }
01328
01329
01330
01331
01332
01333
01334
01335
01336
01337
01338
01339 if (messageBuffer.stctInput.errorFlags & POSITION_REACHED)
01340 {
01341
01342
01343 }
01344
01345 if (!(messageBuffer.stctInput.errorFlags & INITIALIZED))
01346 {
01347
01348
01349 }
01350
01351 if (messageBuffer.stctInput.errorFlags & TIMEOUT)
01352 {
01353 LOG(warning) << this->storage.jointName << " exceeded timeout";
01354
01355 }
01356
01357 if (messageBuffer.stctInput.errorFlags & I2T_EXCEEDED)
01358 {
01359 LOG(warning) << this->storage.jointName << " exceeded I2t";
01360
01361 }
01362
01363
01364 }
01365
01366 void YouBotJoint::parseMailboxStatusFlags(const YouBotSlaveMailboxMsg& mailboxMsg)
01367 {
01368
01369
01370 switch (mailboxMsg.stctInput.status)
01371 {
01372 case NO_ERROR:
01373 break;
01374 case INVALID_COMMAND:
01375 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName << "; Command no: "
01376 << mailboxMsg.stctOutput.commandNumber << " is an invalid command!";
01377
01378 break;
01379 case WRONG_TYPE:
01380 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName << " has a wrong type!";
01381
01382 break;
01383 case INVALID_VALUE:
01384 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName << " Value: "
01385 << mailboxMsg.stctOutput.value << " is a invalid value!";
01386
01387 break;
01388 case CONFIGURATION_EEPROM_LOCKED:
01389 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName
01390 << " - Configuration EEPROM locked";
01391
01392 break;
01393 case COMMAND_NOT_AVAILABLE:
01394 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName
01395 << " - Command is not available!";
01396
01397 break;
01398 case REPLY_WRITE_PROTECTED:
01399 LOG(error) << this->storage.jointName << "Parameter name: " << mailboxMsg.parameterName
01400 << " - Permissions denied!";
01401
01402 break;
01403 }
01404
01405
01406 }
01407
01408 bool YouBotJoint::retrieveValueFromMotorContoller(YouBotSlaveMailboxMsg& message)
01409 {
01410
01411
01412 bool unvalid = true;
01413 unsigned int retry = 0;
01414
01415 ethercatMaster->setMailboxMsgBuffer(message, this->storage.jointNumber);
01416
01417 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
01418
01419 do
01420 {
01421 ethercatMaster->getMailboxMsgBuffer(message, this->storage.jointNumber);
01422
01423
01424
01425
01426
01427
01428 if (message.stctOutput.commandNumber == message.stctInput.commandNumber && message.stctInput.status == NO_ERROR)
01429 {
01430 unvalid = false;
01431 }
01432 else
01433 {
01434 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
01435 retry++;
01436 }
01437 } while (retry < mailboxMsgRetries && unvalid);
01438
01439 if (unvalid)
01440 {
01441 this->parseMailboxStatusFlags(message);
01442 return false;
01443 }
01444 else
01445 {
01446 return true;
01447 }
01448
01449
01450 }
01451
01452 bool YouBotJoint::setValueToMotorContoller(const YouBotSlaveMailboxMsg& mailboxMsg)
01453 {
01454
01455
01456 YouBotSlaveMailboxMsg mailboxMsgBuffer;
01457 mailboxMsgBuffer = mailboxMsg;
01458 bool unvalid = true;
01459 unsigned int retry = 0;
01460
01461 ethercatMaster->setMailboxMsgBuffer(mailboxMsgBuffer, this->storage.jointNumber);
01462
01463 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
01464
01465 do
01466 {
01467 ethercatMaster->getMailboxMsgBuffer(mailboxMsgBuffer, this->storage.jointNumber);
01468
01469
01470
01471
01472
01473
01474 if (mailboxMsgBuffer.stctOutput.commandNumber == mailboxMsgBuffer.stctInput.commandNumber
01475 && mailboxMsgBuffer.stctOutput.value == mailboxMsgBuffer.stctInput.value
01476 && mailboxMsgBuffer.stctInput.status == NO_ERROR)
01477 {
01478 unvalid = false;
01479 }
01480 else
01481 {
01482 SLEEP_MILLISEC(timeTillNextMailboxUpdate);
01483 retry++;
01484 }
01485 } while (retry < mailboxMsgRetries && unvalid);
01486
01487 if (unvalid)
01488 {
01489 this->parseMailboxStatusFlags(mailboxMsgBuffer);
01490 return false;
01491 }
01492 else
01493 {
01494 return true;
01495 }
01496
01497
01498 }
01499
01500 }