00001
00002
00003
00004
00005
00006 #include <threemxl/platform/hardware/dynamixel/dynamixel/Dynamixel.h>
00007 #include <threemxl/platform/hardware/dynamixel/CDxlPacketHandler.h>
00008
00009 #include <math.h>
00010 #include <sstream>
00011 #include <algorithm>
00012 #include <string.h>
00013
00014 using namespace std;
00015
00016
00017
00018
00019
00020
00021 CDynamixel::CDynamixel(): CDxlGeneric(), mLog("Dynamixel")
00022 {
00023 mLog.setLevel(llCrawl);
00024
00025 mID = -1;
00026 mPosition = 0;
00027 mSpeed = 0;
00028 mLoad = 0;
00029 mVoltage = 0;
00030 mTemperature = 45;
00031 mRetlevel = 0;
00032 mNullAngle = DXL_MAX_RAD_ANGLE/2.0;
00033
00034 mDirection = 1.0;
00035 mCWAngleLimit = 0;
00036 mCCWAngleLimit = DXL_MAX_POSITION;
00037 mEndlessTurnMode = false;
00038
00039 for (int i=0; i<DXL_NUM_POSITIONS; i++)
00040 mAngleLUT[i] = (double)i*DXL_STEPS_TO_RAD;
00041 }
00042
00043 CDynamixel::~CDynamixel()
00044 {
00045 }
00046
00047 void CDynamixel::setConfig(CDxlConfig* config)
00048 {
00049
00050 mConfig = *config;
00051
00052
00053 if (mConfig.mClockwiseIsPositive.isSet())
00054 {setPositiveDirection(mConfig.mClockwiseIsPositive);}
00055 else
00056 {setPositiveDirection(false);}
00057
00058
00059
00060 if (mConfig.mNullAngle.isSet())
00061 {setNullAngle(mConfig.mNullAngle);}
00062
00063
00064 if(!mConfig.mReturnDelay.isSet() ){setReturnDelayTime(INITIAL_RETURN_DELAY_TIME);}
00065 if(!mConfig.mAngleLowerLimit.isSet() ){setAngleLowerLimit(-DXL_MAX_RAD_ANGLE/2.0);}
00066 if(!mConfig.mAngleUpperLimit.isSet() ){setAngleUpperLimit(DXL_MAX_RAD_ANGLE/2.0);}
00067 if(!mConfig.mTempLimit.isSet() ){setTemperatureLimit(INITIAL_TEMPERATURE_LIMIT);}
00068 if(!mConfig.mLED.isSet() ){enableLED(false);}
00069 if(!mConfig.mTorqueLimit.isSet() ){setTorqueLimit(INITIAL_TORQUE_LIMIT);}
00070 if(!mConfig.mAlarmLED.isSet() ){setAlarmLEDMask(DXL_ERR_OVERHEATING | DXL_ERR_OVERLOAD);}
00071 if(!mConfig.mAlarmShutdown.isSet() ){setAlarmShutdownMask(DXL_ERR_OVERHEATING);}
00072 if(!mConfig.mPunch.isSet() ){setPunch(INITIAL_PUNCH);}
00073
00074
00075
00076 if(!(mConfig.mVoltageLowerLimit.isSet() && mConfig.mVoltageUpperLimit.isSet()) )
00077 {setVoltageLimits(INITIAL_VOLTAGE_LOWER_LIMIT, INITIAL_VOLTAGE_UPPER_LIMIT);}
00078 if(!(mConfig.mComplianceMargin.isSet() && mConfig.mComplianceSlope.isSet()) )
00079 {setCompliance(INITIAL_COMPLIENCE_MARGIN,INITIAL_COMPLIENCE_SLOPE);}
00080
00081
00082 if (config->mCalibType == dxlCtAuto)
00083 {
00084
00085 memcpy(mAngleLUT, config->mAngleLUT, DXL_NUM_POSITIONS*sizeof(mAngleLUT[0]));
00086 }
00087 else
00088 if (config->mCalibType == dxlCtManual)
00089 {
00090 int calibIndex = 1;
00091 for (int lutIndex=0; lutIndex<DXL_NUM_POSITIONS; lutIndex++)
00092 {
00093
00094 while ((config->mCalibData[calibIndex] <= (double)lutIndex) && (calibIndex < DXLCONFIG_NUM_CALIBPOINTS-1))
00095 calibIndex++;
00096
00097 double interpolfact = ((double)lutIndex - config->mCalibData[calibIndex-1])/(config->mCalibData[calibIndex] - config->mCalibData[calibIndex-1]);
00098
00099 mAngleLUT[lutIndex] = ((double)(calibIndex-1) + interpolfact)*M_PI/180.0;
00100
00101
00102 }
00103 }
00104 }
00105
00106 void CDynamixel::setSerialPort(LxSerial* serialPort)
00107 {
00108 mSerialPort = serialPort;
00109 }
00110
00111 void CDynamixel::setPositiveDirection(bool clockwiseIsPositive)
00112 {
00113 if (clockwiseIsPositive)
00114 mDirection = -1.0;
00115 else
00116 mDirection = 1.0;
00117 }
00118
00119 void CDynamixel::setNullAngle(double nullAngle)
00120 {
00121 mNullAngle = nullAngle;
00122 }
00123
00124 double CDynamixel::dxlPosToInternalPos(WORD pos)
00125 {
00126 int lutPos = clip(pos, 0, DXL_MAX_POSITION);
00127 if (mDirection > 0)
00128 return mAngleLUT[lutPos] - mNullAngle;
00129 else
00130 return DXL_MAX_RAD_ANGLE - mAngleLUT[lutPos] - mNullAngle;
00131 }
00132
00133 int CDynamixel::internalPosToDxlPos(double pos)
00134 {
00135
00136 double transpos;
00137 if (mDirection > 0)
00138 transpos = pos + mNullAngle;
00139 else
00140 transpos = DXL_MAX_RAD_ANGLE - (pos + mNullAngle);
00141
00142
00143
00144 int lutIndex = clip(round(transpos/DXL_STEPS_TO_RAD), 0, DXL_MAX_POSITION);
00145
00146 if (mAngleLUT[lutIndex] > transpos)
00147 {
00148
00149 while (mAngleLUT[lutIndex] > transpos)
00150 {
00151 if (lutIndex > 0)
00152 lutIndex--;
00153 else
00154 break;
00155 }
00156
00157 if ( fabs(transpos - mAngleLUT[lutIndex]) < fabs(mAngleLUT[lutIndex+1] - transpos) )
00158 return lutIndex;
00159 else
00160 return lutIndex+1;
00161 }
00162 else
00163 {
00164
00165 while (mAngleLUT[lutIndex] <= transpos)
00166 {
00167 if (lutIndex < DXL_NUM_POSITIONS-1)
00168 lutIndex++;
00169 else
00170 break;
00171 }
00172
00173 if ( fabs(mAngleLUT[lutIndex] - transpos) < fabs(transpos - mAngleLUT[lutIndex-1]) )
00174 return lutIndex;
00175 else
00176 return lutIndex-1;
00177 }
00178 }
00179
00180 double CDynamixel::dxlSpeedToInternalSpeed(WORD speed)
00181 {
00182 if (speed & 0x400)
00183
00184 return -mDirection*DXL_SPEED_TO_RAD_S*(double)(speed & 0x3FF);
00185 else
00186
00187 return mDirection*DXL_SPEED_TO_RAD_S*(double)(speed & 0x3FF);
00188 }
00189
00190 int CDynamixel::internalSpeedToDxlSpeed(double speed)
00191 {
00192 return round(mDirection*speed/DXL_SPEED_TO_RAD_S);
00193 }
00194
00195 double CDynamixel::dxlTorqueToInternalTorque(WORD torque)
00196 {
00197 if (torque & 0x400)
00198
00199 return -mDirection*DXL_TORQUE_TO_RATIO*(double)(torque & 0x3FF);
00200 else
00201
00202 return mDirection*DXL_TORQUE_TO_RATIO*(double)(torque & 0x3FF);
00203 }
00204
00205 WORD CDynamixel::internalTorqueToDxlTorque(double torqueRatio)
00206 {
00207 int rawTorque = round(mDirection*torqueRatio/DXL_TORQUE_TO_RATIO);
00208
00209
00210 if (rawTorque < 0)
00211 rawTorque = clip(-rawTorque, 1, 1023) | 0x400;
00212 else
00213 rawTorque = clip(rawTorque, 1, 1023);
00214
00215 return (WORD)rawTorque;
00216 }
00217
00218 double CDynamixel::presentAngleLowerLimit()
00219 {
00220 if (mDirection<0)
00221 return dxlPosToInternalPos(mCCWAngleLimit);
00222 else
00223 return dxlPosToInternalPos(mCWAngleLimit);
00224 }
00225
00226 double CDynamixel::presentAngleUpperLimit()
00227 {
00228 if (mDirection<0)
00229 return dxlPosToInternalPos(mCWAngleLimit);
00230 else
00231 return dxlPosToInternalPos(mCCWAngleLimit);
00232 }
00233
00234 int CDynamixel::init(bool sendConfigToMotor)
00235 {
00236 logCrawlLn(mLog,"INIT STARTED");
00237 if (mInitialized)
00238 return DXL_ALREADY_INITIALIZED;
00239
00240 int initResult = initPacketHandler();
00241 if (initResult != DXL_SUCCESS)
00242 {
00243 logDebugLn(mLog,"Error initializing packet handler!");
00244 return initResult;
00245 }
00246
00247
00248 if (mConfig.mID.isSet())
00249 {
00250 mID = mConfig.mID;
00251 }
00252 else
00253 {
00254 logErrorLn(mLog,"No ID set for this dynamixel");
00255 mInitialized = false;
00256 return DXL_NOT_INITIALIZED;
00257 }
00258
00259
00260 int pingResult = ping();
00261 if (pingResult != DXL_SUCCESS)
00262 {
00263 mInitialized = false;
00264 logErrorLn(mLog,"dynamixel with ID " << mID << " failed ping test");
00265 return pingResult;
00266 }
00267
00268
00269 BYTE retlevel;
00270 int result = readData(P_RETURN_LEVEL, 1, &retlevel);
00271 if (result == DXL_SUCCESS)
00272 {
00273 mRetlevel = retlevel;
00274 mInitialized = true;
00275 }
00276 else
00277 {
00278 if (result == DXL_PKT_RECV_TIMEOUT)
00279 {
00280 mRetlevel = 0;
00281 mInitialized = true;
00282 }
00283 else
00284
00285 mInitialized = false;
00286 }
00287
00288 if (sendConfigToMotor)
00289
00290 mConfig.configureDynamixel(this);
00291
00292 return result;
00293 }
00294
00295 int CDynamixel::changeID(const int newID)
00296 {
00297 BYTE bNewID = newID;
00298 int result = writeData(P_ID, 1, &bNewID);
00299 if (result == DXL_PKT_RECV_ID_ERR)
00300 {
00301
00302 mID = newID;
00303 return DXL_SUCCESS;
00304 }
00305 else
00306 if (result == DXL_SUCCESS)
00307 {
00308
00309
00310 mID = newID;
00311 return DXL_SUCCESS;
00312 }
00313 else
00314 return result;
00315 }
00316
00317 int CDynamixel::enableLED(int state)
00318 {
00319 int result=DXL_SUCCESS;
00320
00321 if (!mInitialized)
00322 return DXL_NOT_INITIALIZED;
00323
00324 BYTE ledStatus;
00325 switch(state)
00326 {
00327 case DXL_ON:
00328 ledStatus = 1;
00329 result = writeData(P_LED, 1, &ledStatus);
00330 break;
00331 case DXL_OFF:
00332 ledStatus = 0;
00333 result = writeData(P_LED, 1, &ledStatus);
00334 break;
00335 case DXL_TOGGLE:
00336 readData(P_LED, 1, &ledStatus);
00337 ledStatus = !ledStatus;
00338 result = writeData(P_LED, 1, &ledStatus);
00339 break;
00340 }
00341 return result;
00342 }
00343
00344 int CDynamixel::getState()
00345 {
00346 if (!mInitialized)
00347 {
00348 return DXL_NOT_INITIALIZED;
00349 }
00350 BYTE data[8];
00351 memset(data, 0, 8*sizeof(BYTE));
00352
00353 int result = readData(P_PRESENT_POSITION_L, 8, data);
00354 if (result != DXL_SUCCESS)
00355 {
00356 return result;
00357 }
00358
00359 mPosition = dxlPosToInternalPos(*(WORD*)(data));
00360 mSpeed = dxlSpeedToInternalSpeed((*(WORD*)(data+2)));
00361 mLoad = dxlTorqueToInternalTorque((*(WORD*)(data+4)));
00362 mVoltage = DXL_VOLTAGE_TO_VOLT*data[6];
00363 mTemperature = data[7];
00364
00365 return DXL_SUCCESS;
00366 }
00367
00368 int CDynamixel::getPos()
00369 {
00370 if (!mInitialized)
00371 return DXL_NOT_INITIALIZED;
00372
00373 BYTE data[2];
00374 int result = readData(P_PRESENT_POSITION_L, 2, data);
00375 if (result != DXL_SUCCESS)
00376 return result;
00377
00378 mPosition = dxlPosToInternalPos(*(WORD*)(data));
00379 return DXL_SUCCESS;
00380 }
00381
00382 int CDynamixel::getPosAndSpeed()
00383 {
00384 if (!mInitialized)
00385 {
00386 return DXL_NOT_INITIALIZED;
00387 }
00388 BYTE data[4];
00389 memset(data, 0, 4*sizeof(BYTE));
00390
00391 int result = readData(P_PRESENT_POSITION_L, 4, data);
00392 if (result != DXL_SUCCESS)
00393 return result;
00394
00395 mPosition = dxlPosToInternalPos(*(WORD*)(data));
00396 mSpeed = dxlSpeedToInternalSpeed((*(WORD*)(data+2)));
00397
00398 return DXL_SUCCESS;
00399 }
00400
00401 int CDynamixel::getTemp()
00402 {
00403 if (!mInitialized)
00404 return DXL_NOT_INITIALIZED;
00405
00406 BYTE data;
00407 int result = readData(P_PRESENT_TEMPERATURE, 1, &data);
00408 if (result != DXL_SUCCESS)
00409 return result;
00410
00411 mTemperature = data;
00412 return DXL_SUCCESS;
00413 }
00414
00415 int CDynamixel::setPos(double pos, double absSpeed,bool shouldSyncWrite)
00416 {
00417 if (!mInitialized)
00418 return DXL_NOT_INITIALIZED;
00419
00420 WORD data[2];
00421 data[0] = clip(internalPosToDxlPos(pos), 0, DXL_MAX_POSITION);
00422 if (absSpeed < 0)
00423 data[1] = 0;
00424 else
00425 data[1] = clip(abs(internalSpeedToDxlSpeed(absSpeed)), 1, 1023);
00426 return writeData(P_GOAL_POSITION_L, 4, (BYTE*)data, shouldSyncWrite);
00427 }
00428
00429 int CDynamixel::setSpeed(double speed,bool shouldSyncWrite)
00430 {
00431 if (!mInitialized)
00432 return DXL_NOT_INITIALIZED;
00433
00434 int dxlSpeed = internalSpeedToDxlSpeed(speed);
00435 WORD data[2];
00436 if (dxlSpeed > 0)
00437 {
00438 data[0] = mCCWAngleLimit;
00439 data[1] = clip(dxlSpeed, 1, 1023);
00440 }
00441 else
00442 {
00443 data[0] = mCWAngleLimit;
00444 data[1] = clip(-dxlSpeed, 1, 1023);
00445 }
00446
00447 return writeData(P_GOAL_POSITION_L, 4, (BYTE*)data, shouldSyncWrite);
00448 }
00449
00450 int CDynamixel::setRetlevel(const int returnlevel)
00451 {
00452 if (!mInitialized)
00453 return DXL_NOT_INITIALIZED;
00454
00455 BYTE bRetlevel = returnlevel;
00456 writeData(P_RETURN_LEVEL, 1, &bRetlevel);
00457 mRetlevel = returnlevel;
00458 return DXL_SUCCESS;
00459 }
00460
00461 int CDynamixel::setBaudRateIndex(const BYTE baudRateIndex)
00462 {
00463 if (!mInitialized)
00464 return DXL_NOT_INITIALIZED;
00465
00466 BYTE bBaudRateIndex = baudRateIndex;
00467 return writeData(P_BAUD_RATE, 1, &bBaudRateIndex);
00468 }
00469
00470 int CDynamixel::setBaudRate(const int baudRate)
00471 {
00472 if (!mInitialized)
00473 return DXL_NOT_INITIALIZED;
00474
00475 BYTE bBaudRateIndex = (int)2E6/baudRate - 1;
00476 return writeData(P_BAUD_RATE, 1, &bBaudRateIndex);
00477 }
00478
00479 int CDynamixel::setReturnDelayTime(const int microsecondsReturnDelay)
00480 {
00481 if (!mInitialized)
00482 return DXL_NOT_INITIALIZED;
00483
00484 BYTE bReturnDelayIndex = microsecondsReturnDelay/2;
00485 return writeData(P_RETURN_DELAY_TIME, 1, &bReturnDelayIndex);
00486 }
00487
00488 int CDynamixel::enableTorque(int state)
00489 {
00490 int result = DXL_SUCCESS;
00491 if (!mInitialized)
00492 return DXL_NOT_INITIALIZED;
00493
00494 BYTE torqueStatus;
00495 switch(state)
00496 {
00497 case DXL_ON:
00498 torqueStatus = 1;
00499 result = writeData(P_TORQUE_ENABLE, 1, &torqueStatus);
00500 break;
00501 case DXL_OFF:
00502 torqueStatus = 0;
00503 result = writeData(P_TORQUE_ENABLE, 1, &torqueStatus);
00504 break;
00505 case DXL_TOGGLE:
00506 readData(P_TORQUE_ENABLE, 1, &torqueStatus);
00507 torqueStatus = !torqueStatus;
00508 result = writeData(P_TORQUE_ENABLE, 1, &torqueStatus);
00509 break;
00510 }
00511 return result;
00512 }
00513
00514 int CDynamixel::setInitialTorqueLimit(double absMaxTorque)
00515 {
00516 if (!mInitialized)
00517 return DXL_NOT_INITIALIZED;
00518
00519 WORD data = clip(round(absMaxTorque/DXL_TORQUE_TO_RATIO), 1, 1023);
00520 return writeData(P_MAX_TORQUE_L, 2, (BYTE*)&data);
00521 }
00522
00523 int CDynamixel::setTorqueLimit(double absMaxTorque)
00524 {
00525 if (!mInitialized)
00526 return DXL_NOT_INITIALIZED;
00527
00528 WORD data = clip(round(absMaxTorque/DXL_TORQUE_TO_RATIO), 1, 1023);
00529 return writeData(P_TORQUE_LIMIT_L, 2, (BYTE*)&data);
00530 }
00531
00532 int CDynamixel::setAngleLowerLimit(double limit)
00533 {
00534 if (!mInitialized)
00535 return DXL_NOT_INITIALIZED;
00536
00537 WORD data = clip(internalPosToDxlPos(limit), 0, DXL_MAX_POSITION);
00538 BYTE dxlAddress;
00539 if (mDirection<0)
00540 dxlAddress = P_CCW_ANGLE_LIMIT_L;
00541 else
00542 dxlAddress = P_CW_ANGLE_LIMIT_L;
00543
00544 return writeData(dxlAddress, 2, (BYTE*)&data);
00545 }
00546
00547 int CDynamixel::setAngleUpperLimit(double limit)
00548 {
00549 if (!mInitialized)
00550 return DXL_NOT_INITIALIZED;
00551
00552 WORD data = clip(internalPosToDxlPos(limit), 0, DXL_MAX_POSITION);
00553 BYTE dxlAddress;
00554 if (mDirection<0)
00555 dxlAddress = P_CW_ANGLE_LIMIT_L;
00556 else
00557 dxlAddress = P_CCW_ANGLE_LIMIT_L;
00558
00559 return writeData(dxlAddress, 2, (BYTE*)&data);
00560 }
00561
00562 int CDynamixel::setTemperatureLimit(const int maxTemp)
00563 {
00564 if (!mInitialized)
00565 return DXL_NOT_INITIALIZED;
00566
00567 BYTE data = maxTemp;
00568 return writeData(P_LIMIT_TEMPERATURE, 1, &data);
00569 }
00570
00571 int CDynamixel::setVoltageLimits(double minVoltage, double maxVoltage)
00572 {
00573 if (!mInitialized)
00574 return DXL_NOT_INITIALIZED;
00575
00576 BYTE data[2];
00577 data[0] = round(minVoltage/DXL_VOLTAGE_TO_VOLT);
00578 data[1] = round(maxVoltage/DXL_VOLTAGE_TO_VOLT);
00579 return writeData(P_DOWN_LIMIT_VOLTAGE, 2, data);
00580 }
00581
00582 int CDynamixel::getAngleLimits()
00583 {
00584 if (!mInitialized)
00585 return DXL_NOT_INITIALIZED;
00586 if (mEndlessTurnMode)
00587 return -DXL_ERR_INSTRUCTION;
00588
00589 WORD data[2];
00590 int result = readData(P_CW_ANGLE_LIMIT_L, 4, (BYTE*)data);
00591 if (result != DXL_SUCCESS)
00592 return result;
00593
00594
00595 mCWAngleLimit = data[0];
00596 mCCWAngleLimit = data[1];
00597 return DXL_SUCCESS;
00598 }
00599
00600 int CDynamixel::setAngleLimits(double lowerLimit, double upperLimit)
00601 {
00602 if (!mInitialized)
00603 return DXL_NOT_INITIALIZED;
00604
00605 if (upperLimit < lowerLimit)
00606 return DXL_INVALID_PARAMETER;
00607
00608
00609 WORD data[2];
00610 if (mDirection<0)
00611 {
00612 data[0] = mCWAngleLimit = clip(internalPosToDxlPos(upperLimit), 0, DXL_MAX_POSITION);
00613 data[1] = mCCWAngleLimit = clip(internalPosToDxlPos(lowerLimit), 0, DXL_MAX_POSITION);
00614 }
00615 else
00616 {
00617 data[0] = mCWAngleLimit = clip(internalPosToDxlPos(lowerLimit), 0, DXL_MAX_POSITION);
00618 data[1] = mCCWAngleLimit = clip(internalPosToDxlPos(upperLimit), 0, DXL_MAX_POSITION);
00619 }
00620 return writeData(P_CW_ANGLE_LIMIT_L, 4, (BYTE*)data);
00621 }
00622
00623 int CDynamixel::setEndlessTurnMode(bool enabled,bool shouldSyncWrite)
00624 {
00625 if (!mInitialized)
00626 return DXL_NOT_INITIALIZED;
00627
00628 WORD data[2];
00629 int result = DXL_SUCCESS;
00630 if (enabled)
00631 {
00632 if (result != DXL_SUCCESS)
00633 return result;
00634
00635
00636 data[0] = 0;
00637 data[1] = 0;
00638 result = writeData(P_CW_ANGLE_LIMIT_L, 4, (BYTE*)data, shouldSyncWrite);
00639 if (result == DXL_SUCCESS)
00640 mEndlessTurnMode = true;
00641 }
00642 else
00643 {
00644 data[0] = mCWAngleLimit;
00645 data[1] = mCCWAngleLimit;
00646 result = writeData(P_CW_ANGLE_LIMIT_L, 4, (BYTE*)data, shouldSyncWrite);
00647 if (result == DXL_SUCCESS)
00648 mEndlessTurnMode = false;
00649 }
00650 return result;
00651 }
00652
00653 int CDynamixel::setEndlessTurnTorque(double torqueRatio,bool shouldSyncWrite)
00654 {
00655 if (!mInitialized)
00656 return DXL_NOT_INITIALIZED;
00657
00658
00659
00660
00661
00662
00663
00664
00665 WORD data = internalTorqueToDxlTorque(torqueRatio);
00666 return writeData(P_GOAL_SPEED_L, 2, (BYTE*)&data, shouldSyncWrite);
00667 }
00668
00669 int CDynamixel::setOperatingMode(const BYTE mode)
00670 {
00671 if (!mInitialized)
00672 return DXL_NOT_INITIALIZED;
00673
00674 BYTE data = mode;
00675 return writeData(P_OPERATING_MODE, 1, &data);
00676 }
00677
00678 int CDynamixel::setAlarmLEDMask(const BYTE mask)
00679 {
00680 if (!mInitialized)
00681 return DXL_NOT_INITIALIZED;
00682
00683 BYTE data = mask;
00684 return writeData(P_ALARM_LED, 1, &data);
00685 }
00686
00687 int CDynamixel::setAlarmShutdownMask(const BYTE mask)
00688 {
00689 if (!mInitialized)
00690 return DXL_NOT_INITIALIZED;
00691
00692 BYTE data = mask;
00693 return writeData(P_ALARM_SHUTDOWN, 1, &data);
00694 }
00695
00696 int CDynamixel::setCompliance(BYTE complianceMargin, BYTE complianceSlope)
00697 {
00698 if (!mInitialized)
00699 return DXL_NOT_INITIALIZED;
00700
00701 BYTE data[4];
00702 data[0] = complianceMargin;
00703 data[1] = complianceMargin;
00704 data[2] = complianceSlope;
00705 data[3] = complianceSlope;
00706 return writeData(P_CW_COMPLIANCE_MARGIN, 4, data);
00707 }
00708
00709 int CDynamixel::setPunch(WORD punch)
00710 {
00711 if (!mInitialized)
00712 return DXL_NOT_INITIALIZED;
00713
00714 WORD data = punch;
00715 return writeData(P_PUNCH_L, 2, (BYTE*)&data);
00716 }
00717
00718 int CDynamixel::printReport(FILE* fOut)
00719 {
00720 if (!mInitialized)
00721 return DXL_NOT_INITIALIZED;
00722
00723 BYTE data[50];
00724 memset(data, 0, 50*sizeof(BYTE));
00725
00726
00727
00728
00729
00730 for(int i=0; i<50 ; i++)
00731 {
00732 mLogInfoLn("checking adress "<<i);
00733 int result = readData(i, 1, &data[i]);
00734 if (result != DXL_SUCCESS)
00735 {
00736 return result;
00737 }
00738 }
00739
00740 fprintf(fOut, "Model=%d (v.%d), Ret.delay=%dus, Ret.level=%d, V=%.1f, T=%d°\n", (int)(*(unsigned short*)(data+P_MODEL_NUMBER_L)), (int)data[P_VERSION], 2*(int)data[P_RETURN_DELAY_TIME], data[P_RETURN_LEVEL], DXL_VOLTAGE_TO_VOLT*(double)data[P_PRESENT_VOLTAGE], data[P_PRESENT_TEMPERATURE]);
00741
00742 fprintf(fOut, "Pause time: %d, Torque: %s, LED: %s\n", (int)data[P_PAUSE_TIME], data[P_TORQUE_ENABLE]?"ON":"OFF", data[P_LED]?"ON":"OFF");
00743
00744 fprintf(fOut, "%.1f° <= angle <= %.1f°, torque <= %.0f%%\n", (300.0*(int)(*(unsigned short*)(data+P_CW_ANGLE_LIMIT_L)))/(double)DXL_MAX_POSITION, (300.0*((int)(*(unsigned short*)(data+P_CCW_ANGLE_LIMIT_L))))/(double)DXL_MAX_POSITION, 100.0*(int)(*(unsigned short*)(data+P_TORQUE_LIMIT_L))/1023.0);
00745
00746 fprintf(fOut, "Current Angle %.1f°\n",(300.0*(int)(*(unsigned short*)(data+P_PRESENT_POSITION_L)))/1023.0);
00747
00748 fprintf(fOut, "Control compliance: \\%d\\ -%d- |*%d*| -%d- \\%d\\\n", (int)data[P_CW_COMPLIANCE_SLOPE], (int)data[P_CW_COMPLIANCE_MARGIN], (int)(*(unsigned short*)(data+P_PUNCH_L)), (int)data[P_CCW_COMPLIANCE_MARGIN], (int)data[P_CCW_COMPLIANCE_SLOPE] );
00749 return DXL_SUCCESS;
00750 }
00751
00752
00753