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 #include "Devices/Scorbot.H"
00039 #include "Component/OptionManager.H"
00040 #include "Util/MathFunctions.H"
00041 #include "Util/Assert.H"
00042 #include "Util/Timer.H"
00043 #include "rutz/compat_snprintf.h"
00044
00045
00046
00047 void* Scorbot_Control(void *obj)
00048 {
00049 Scorbot *scorbot = (Scorbot*)obj;
00050 scorbot->controlLoop();
00051 return NULL;
00052 }
00053
00054
00055
00056
00057 Scorbot::Scorbot(OptionManager& mgr, const std::string& descrName,
00058 const std::string& tagName,
00059 const char *defdev) :
00060 RobotArm(mgr, descrName, tagName),
00061 itsSerial(new Serial(mgr)),
00062 pidBase(0.05, 0.001, 0.02, -10, 10, 1, BASE_POS_THRESH, BASE_NEG_THRESH),
00063 pidSholder(0.05, 0.001, 0.01,-50, 50, 1, SHOLDER_POS_THRESH, SHOLDER_NEG_THRESH),
00064 pidElbow(0.05, 0.001, 0.03, -50, 50, 1, ELBOW_POS_THRESH, ELBOW_NEG_THRESH),
00065 pidWrist1(0.055, 0.01, 0.01,-50, 50, 1, WRIST_PITCH_POS_THRESH, WRIST_PITCH_NEG_THRESH),
00066 pidWrist2(0.055, 0.01, 0.01,-50, 50, 1, WRIST_ROLL_POS_THRESH, WRIST_ROLL_NEG_THRESH),
00067 pidGripper(0.025, 0.01, 0.01,-50, 50, 1, GRIPPER_POS_THRESH, GRIPPER_NEG_THRESH),
00068 pidEx1(0.010, 0, 0.009,-50, 50, 1, EX1_POS_THRESH, EX1_NEG_THRESH),
00069 pidEx2(0.0, 0, 0.0,-40, 40),
00070 itsUpperarmLength(222.0),
00071 itsForearmLength(222.0),
00072 itsUpperarmCOM(110),
00073 itsUpperarmMass(80),
00074 itsForearmCOM(200),
00075 itsForearmMass(200),
00076 itsRadPerSholderEncoder(M_PI/(10128.0*2.0)),
00077 itsRadPerElbowEncoder(M_PI/(10128.0*2.0)),
00078 itsMMPerSlideEncoder(500.0/139520.0),
00079 itsBaseXOffset(0),
00080 itsBaseZOffset(0),
00081 itsHomeBaseOffset(0),
00082 itsHomeSholderOffset(0),
00083 itsHomeElbowOffset(0),
00084 itsHomeWristRollBaseOffset(-1320),
00085 itsHomeWristPitchBaseOffset(-578),
00086 itsBasePos("BasePos", this, 0, ALLOW_ONLINE_CHANGES),
00087 itsSholderPos("SholderPos", this, 0, ALLOW_ONLINE_CHANGES),
00088 itsElbowPos("ElbowPos", this, 0, ALLOW_ONLINE_CHANGES),
00089 itsWrist1Pos("Wrist1Pos", this, 0, ALLOW_ONLINE_CHANGES),
00090 itsWrist2Pos("Wrist2Pos", this, 0, ALLOW_ONLINE_CHANGES),
00091 itsGripperPos("GripperPos", this, 0, ALLOW_ONLINE_CHANGES),
00092 itsEX1Pos("EX1Pos", this, 0, ALLOW_ONLINE_CHANGES),
00093 itsEX2Pos("EX2Pos", this, 0, ALLOW_ONLINE_CHANGES),
00094 itsArmXPos("ArmXPos", this, 0, ALLOW_ONLINE_CHANGES),
00095 itsArmYPos("ArmYPos", this, 0, ALLOW_ONLINE_CHANGES),
00096 itsArmZPos("ArmZPos", this, 0, ALLOW_ONLINE_CHANGES),
00097 itsMoveTo3D("MoveTo3D", this, 0, ALLOW_ONLINE_CHANGES),
00098 itsDuration("Duration", this, 2000, ALLOW_ONLINE_CHANGES),
00099 itsInternalPIDen("InternalPID", this, false, ALLOW_ONLINE_CHANGES),
00100 itsRunControl(false),
00101 itsStopControl(true),
00102 itsReadEncoders(false),
00103 itsShutdownMotorsOff(true)
00104 {
00105 itsSerial->configure (defdev, 115200, "8N1", false, false, 10000);
00106
00107 addSubComponent(itsSerial);
00108
00109 itsRunControl = false;
00110 pthread_mutex_init(&itsLock, NULL);
00111 pthread_mutex_init(&itsSerialLock, NULL);
00112 pthread_mutex_init(&itsPosLock, NULL);
00113
00114 itsDesiredPos.base = (int)itsHomeBaseOffset;
00115 itsDesiredPos.sholder = -7036;
00116 itsDesiredPos.elbow = 10958;
00117 itsDesiredPos.wristRoll = -1930;
00118 itsDesiredPos.wristPitch = 4748;
00119 itsDesiredPos.ex1 = 54000;
00120
00121 itsArmVelParams.ex1.a = itsDesiredPos.ex1;
00122 itsArmVelParams.ex1.b = 0;
00123 itsArmVelParams.ex1.c = 0;
00124 itsArmVelParams.ex1.d = 0;
00125
00126
00127 }
00128
00129
00130 void Scorbot::start2()
00131 {
00132
00133
00134
00135
00136 }
00137
00138
00139 void Scorbot::stop1()
00140 {
00141
00142 while(itsRunControl == true)
00143 usleep(10000);
00144 itsRunControl = false;
00145
00146 if (itsShutdownMotorsOff)
00147 motorsOff();
00148 }
00149
00150
00151 Scorbot::~Scorbot()
00152 {
00153 pthread_mutex_destroy(&itsLock);
00154 }
00155
00156
00157 double Scorbot::gravityComp(int sholderPos, int elbowPos)
00158 {
00159
00160
00161
00162 double sholderAng = (double)sholderPos*M_PI/20000.0;
00163 double elbowAng = -1*(double)elbowPos*M_PI/20000.0;
00164
00165 double c1x = cos(sholderAng)*itsUpperarmCOM;
00166 double c1y = sin(sholderAng)*itsUpperarmCOM;
00167
00168 double c2x = cos(sholderAng)*itsUpperarmLength + cos(elbowAng)*itsForearmCOM;
00169 double c2y = sin(sholderAng)*itsUpperarmLength + sin(elbowAng)*itsForearmCOM;
00170
00171 double MvCv_x = (itsUpperarmMass*c1x + itsForearmMass*c2x)/2.0;
00172 double MvCv_y = (itsUpperarmMass*c1y + itsForearmMass*c2y)/2.0;
00173
00174 double torque = sqrt(squareOf(MvCv_x) + squareOf(MvCv_y))*9.81*1000*sin(atan(MvCv_y/MvCv_x)+M_PI/2);
00175
00176 return torque;
00177 }
00178
00179
00180 int Scorbot::mm2enc(double mm)
00181 {
00182 return (int)(mm*69.39);
00183 }
00184
00185 double Scorbot::enc2mm(int encoderTicks)
00186 {
00187 return double(encoderTicks) / 69.39;
00188 }
00189
00190 double Scorbot::enc2ang(int encoderTicks)
00191 {
00192 return 90.0/10234.0*double(encoderTicks);
00193 }
00194
00195 int Scorbot::ang2enc(double degrees)
00196 {
00197 return int(10234.0 / 90.0 * degrees);
00198 }
00199
00200 void Scorbot::controlLoop()
00201 {
00202 itsRunControl = true;
00203
00204 pidBase.setSpeed(50);
00205 pidSholder.setSpeed(40);
00206 pidElbow.setSpeed(40);
00207 pidGripper.setSpeed(50);
00208 pidWrist1.setSpeed(35);
00209 pidWrist2.setSpeed(35);
00210 pidEx1.setSpeed(30);
00211 pidEx2.setSpeed(30);
00212
00213 int moveDoneCounter = 0;
00214 int thresh = 250;
00215
00216
00217
00218 while(itsRunControl)
00219 {
00220 if (!itsStopControl)
00221 {
00222 pthread_mutex_lock(&itsPosLock);
00223 double time = itsTimer.getSecs();
00224 printf("%f %i\n", time, itsTemp);
00225 itsTemp = false;
00226 if (time > itsDesiredPos.duration)
00227 time = itsDesiredPos.duration;
00228
00229
00230 int basePos = getEncoder(BASE);
00231
00232 int basePwm = (int)pidBase.update(itsDesiredPos.base, basePos);
00233 int baseErr = abs(itsDesiredPos.base - basePos);
00234
00235 int sholderPos =getEncoder(SHOLDER);
00236 int sholderPwm = (int)pidSholder.update(itsDesiredPos.sholder, sholderPos);
00237 int sholderErr = abs(itsDesiredPos.sholder - sholderPos);
00238
00239 int elbowPos = getEncoder(ELBOW);
00240 int elbowPwm = (int)pidElbow.update(itsDesiredPos.elbow, elbowPos);
00241 int elbowErr = abs(itsDesiredPos.elbow - elbowPos);
00242
00243
00244 int desiredWrist1Pos = (itsDesiredPos.wristRoll + itsDesiredPos.wristPitch)/2;
00245 int desiredWrist2Pos = (itsDesiredPos.wristRoll - itsDesiredPos.wristPitch)/2;
00246
00247 int wrist1Pos = getEncoder(WRIST1);
00248 int wrist1Pwm = (int)pidWrist1.update(desiredWrist1Pos, wrist1Pos);
00249 int wrist1Err = abs(desiredWrist1Pos - wrist1Pos);
00250
00251 int wrist2Pos = getEncoder(WRIST2);
00252 int wrist2Pwm = (int)pidWrist2.update(desiredWrist2Pos, wrist2Pos);
00253 int wrist2Err = abs(desiredWrist2Pos - wrist2Pos);
00254
00255 int gripperPos = getEncoder(GRIPPER);
00256 int gripperPwm = (int)pidGripper.update(itsDesiredPos.gripper, gripperPos);
00257 int gripperErr = abs(itsDesiredPos.gripper - gripperPos);
00258
00259 int ex1Pos = getEncoder(EX1);
00260 float ex1DesiredPos = itsArmVelParams.ex1.a + itsArmVelParams.ex1.c*(time*time) + itsArmVelParams.ex1.d*(time*time*time);
00261 float ex1DesiredVel = 2*itsArmVelParams.ex1.c*(time) + 3*itsArmVelParams.ex1.d*(time*time);
00262 int ex1Pwm = (int)pidEx1.update(ex1DesiredPos, ex1DesiredVel, ex1Pos);
00263 int ex1Err = abs(itsDesiredPos.ex1 - ex1Pos);
00264
00265 int ex2Pos = getEncoder(EX2);
00266 int ex2Pwm = (int)pidEx2.update(itsDesiredPos.ex2, ex2Pos);
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283 printf("%i %f %f %i\n", ex1Pos, ex1DesiredPos, ex1DesiredVel, ex1Pwm);
00284 fflush(stdout);
00285 pthread_mutex_unlock(&itsPosLock);
00286
00287
00288
00289 pthread_mutex_lock(&itsLock);
00290 itsCurrentPos.base = basePos;
00291 itsCurrentPos.sholder = sholderPos;
00292 itsCurrentPos.elbow = elbowPos;
00293 itsCurrentPos.gripper = gripperPos;
00294 itsCurrentPos.wrist1 = wrist1Pos;
00295 itsCurrentPos.wrist2 = wrist2Pos;
00296 itsCurrentPos.wristRoll = wrist1Pos + wrist2Pos;
00297 itsCurrentPos.wristPitch = wrist1Pos - wrist2Pos;
00298 itsCurrentPos.ex1 = ex1Pos;
00299 itsCurrentPos.ex2 = ex2Pos;
00300 pthread_mutex_unlock(&itsLock);
00301
00302 if (moveDoneCounter > 3)
00303 itsMoveDone = true;
00304 else
00305 itsMoveDone = false;
00306
00307 if (baseErr < thresh &&
00308 sholderErr < thresh &&
00309 elbowErr < thresh &&
00310 gripperErr < thresh &&
00311 wrist1Err < thresh &&
00312 wrist2Err < thresh &&
00313 ex1Err < 1500)
00314 moveDoneCounter++;
00315 else
00316 moveDoneCounter = 0;
00317
00318
00319
00320
00321 setMotor(BASE, (int)basePwm);
00322 setMotor(SHOLDER, (int)sholderPwm);
00323 setMotor(ELBOW, (int)elbowPwm);
00324 setMotor(GRIPPER, (int)gripperPwm);
00325 setMotor(WRIST1, wrist1Pwm);
00326 setMotor(WRIST2, wrist2Pwm);
00327 setMotor(EX1, (int)ex1Pwm);
00328 setMotor(EX2, (int)ex2Pwm);
00329
00330
00331 } else {
00332 if (itsReadEncoders)
00333 {
00334 pthread_mutex_lock(&itsLock);
00335 itsCurrentPos = readArmState();
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347 pthread_mutex_unlock(&itsLock);
00348 }
00349 }
00350
00351 usleep(10000);
00352 }
00353
00354 pthread_exit(0);
00355
00356 }
00357
00358
00359 void Scorbot::setArmPos(ArmPos &armPos)
00360 {
00361 LINFO("Setting arm to: b:%i s:%i e:%i g:%i e1:%i e2:%i duration: %i",
00362 armPos.base, armPos.sholder, armPos.elbow, armPos.gripper,
00363 armPos.ex1, armPos.ex2, armPos.duration);
00364
00365 unsigned char cmd[100];
00366
00367 cmd[0] = 20;
00368
00369 cmd[1] = (armPos.base >> 24) & 0xFF;
00370 cmd[2] = (armPos.base >> 16) & 0xFF;
00371 cmd[3] = (armPos.base >> 8) & 0xFF;
00372 cmd[4] = (armPos.base >> 0) & 0xFF;
00373
00374 cmd[5] = (armPos.sholder >> 24) & 0xFF;
00375 cmd[6] = (armPos.sholder >> 16) & 0xFF;
00376 cmd[7] = (armPos.sholder >> 8) & 0xFF;
00377 cmd[8] = (armPos.sholder >> 0) & 0xFF;
00378
00379 cmd[9] = (armPos.elbow >> 24) & 0xFF;
00380 cmd[10] = (armPos.elbow >> 16) & 0xFF;
00381 cmd[11] = (armPos.elbow >> 8) & 0xFF;
00382 cmd[12] = (armPos.elbow >> 0) & 0xFF;
00383
00384 cmd[13] = (armPos.wrist1 >> 24) & 0xFF;
00385 cmd[14] = (armPos.wrist1 >> 16) & 0xFF;
00386 cmd[15] = (armPos.wrist1 >> 8) & 0xFF;
00387 cmd[16] = (armPos.wrist1 >> 0) & 0xFF;
00388
00389 cmd[17] = (armPos.wrist2 >> 24) & 0xFF;
00390 cmd[18] = (armPos.wrist2 >> 16) & 0xFF;
00391 cmd[19] = (armPos.wrist2 >> 8) & 0xFF;
00392 cmd[20] = (armPos.wrist2 >> 0) & 0xFF;
00393
00394
00395 cmd[21] = (armPos.gripper >> 24) & 0xFF;
00396 cmd[22] = (armPos.gripper >> 16) & 0xFF;
00397 cmd[23] = (armPos.gripper >> 8) & 0xFF;
00398 cmd[24] = (armPos.gripper >> 0) & 0xFF;
00399
00400
00401 cmd[25] = (armPos.ex1 >> 24) & 0xFF;
00402 cmd[26] = (armPos.ex1 >> 16) & 0xFF;
00403 cmd[27] = (armPos.ex1 >> 8) & 0xFF;
00404 cmd[28] = (armPos.ex1 >> 0) & 0xFF;
00405
00406 cmd[29] = (armPos.ex2 >> 24) & 0xFF;
00407 cmd[30] = (armPos.ex2 >> 16) & 0xFF;
00408 cmd[31] = (armPos.ex2 >> 8) & 0xFF;
00409 cmd[32] = (armPos.ex2 >> 0) & 0xFF;
00410
00411
00412 cmd[33] = (armPos.duration >> 24) & 0xFF;
00413 cmd[34] = (armPos.duration >> 16) & 0xFF;
00414 cmd[35] = (armPos.duration >> 8) & 0xFF;
00415 cmd[36] = (armPos.duration >> 0) & 0xFF;
00416
00417 cmd[37] = 0xFF;
00418 cmd[38] = 0x00;
00419 cmd[39] = 0xFF;
00420 cmd[40] = 0x00;
00421
00422 printf("Sending: ");
00423 for(int i=0; i<41; i++)
00424 printf("%u ", (unsigned char)cmd[i]);
00425 printf("\n");
00426
00427 itsSerial->write(cmd, 41);
00428
00429 usleep(50000);
00430 unsigned char buff[1024];
00431
00432 int ret= itsSerial->read(buff, 1024);
00433 printf("Got %i: ", ret);
00434 for(int i=0; i<ret; i++)
00435 printf("%3d ", buff[i]);
00436 printf("\n");
00437
00438
00439 }
00440
00441
00442 Scorbot::ArmPos Scorbot::getArmPos()
00443 {
00444 return Scorbot::readArmState();
00445 }
00446
00447 Scorbot::ArmPos Scorbot::getDesiredArmPos()
00448 {
00449 return itsDesiredPos;
00450 }
00451
00452
00453 void Scorbot::getEF_pos(float &x, float &y, float &z)
00454 {
00455
00456 float th1 = -1*getEncoderAng(RobotArm::SHOLDER) + (M_PI/2);
00457 float th2 = getEncoderAng(RobotArm::ELBOW) - th1;
00458
00459 x = 0.220*cos(th1) + 0.220*cos(th1+th2);
00460 y = 0;
00461 z = 0.220*sin(th1) + 0.220*sin(th1+th2);
00462 }
00463
00464 Point3D<float> Scorbot::getEFPos(const ArmPos& armPos)
00465 {
00466 Point3D<float> efPos;
00467
00468
00469 float sholderAng = -1*(armPos.sholder-itsHomeSholderOffset)*itsRadPerSholderEncoder;
00470 float elbowAng = -1*(armPos.elbow-itsHomeElbowOffset)*itsRadPerElbowEncoder;
00471
00472
00473 efPos.x = armPos.ex1*itsMMPerSlideEncoder;
00474 efPos.y = itsBaseXOffset +
00475 itsUpperarmLength*sin(sholderAng+M_PI/2) +
00476 itsForearmLength*sin(-elbowAng+M_PI/2);
00477 efPos.z = itsBaseZOffset +
00478 itsUpperarmLength*cos(sholderAng+M_PI/2) +
00479 itsForearmLength*cos(-elbowAng+M_PI/2);
00480
00481
00482 return efPos;
00483
00484 }
00485
00486 Scorbot::ArmPos Scorbot::getIKArmPos(const Point3D<float>& efPos)
00487 {
00488
00489 double y = efPos.y + itsUpperarmLength+itsForearmLength;
00490 double z = efPos.z;
00491
00492
00493 double c2 = ( squareOf(y) +
00494 squareOf(z) -
00495 squareOf(itsUpperarmLength) -
00496 squareOf(itsForearmLength) ) /
00497 ( 2 * itsUpperarmLength * itsForearmLength );
00498 double s2 = sqrt(1 - squareOf(c2));
00499
00500
00501
00502
00503
00504 double hatElbowAng = 1*atan2(s2, c2);
00505
00506 double beta = M_PI/2 - atan2(z,y);
00507
00508 double k1 = itsUpperarmLength+(itsForearmLength*c2);
00509 double k2 = itsForearmLength*s2;
00510
00511 double sholderAng = 0;
00512 if (hatElbowAng > 0)
00513 {
00514 sholderAng = M_PI/2 - beta + atan2(k2,k1);
00515 } else {
00516 sholderAng = M_PI/2 - beta - atan2(k2,k1);
00517 }
00518
00519 double elbowAng = -1*sholderAng + hatElbowAng;
00520
00521 LINFO("Ang Shoulder: %f Elbow: %f %f", sholderAng*180/M_PI, elbowAng*180/M_PI, itsRadPerElbowEncoder);
00522
00523 ArmPos armPos;
00524 armPos.base =(int) itsHomeBaseOffset;
00525 armPos.sholder = ((int)(sholderAng/itsRadPerSholderEncoder));
00526 armPos.elbow = ((int)(elbowAng/itsRadPerElbowEncoder));
00527 armPos.wristRoll = (int)itsCurrentPos.wristRoll;
00528 armPos.wristPitch = (int)itsCurrentPos.wristPitch;
00529 armPos.gripper = (int)itsCurrentPos.gripper;
00530 armPos.ex1 = (int)(((float)efPos.x)/itsMMPerSlideEncoder);
00531 armPos.ex2 = itsCurrentPos.ex2;
00532
00533 return armPos;
00534
00535 }
00536
00537 bool Scorbot::set3DPos(bool relative, int duration )
00538 {
00539
00540 Point3D<float> efPos(itsArmXPos.getVal(), itsArmYPos.getVal(), itsArmZPos.getVal());
00541 Scorbot::ArmPos armPos = getIKArmPos(efPos);
00542 armPos.duration = duration;
00543
00544 LINFO("3D Pos %f %f %f", efPos.x, efPos.y, efPos.z);
00545
00546 LINFO("Encoders: B:%d S:%d E:%d WR:%d WP:%d W1:%i W2:%i G:%d E1:%d E2:%d",
00547 armPos.base,
00548 armPos.sholder,
00549 armPos.elbow,
00550 armPos.wristRoll,
00551 armPos.wristPitch,
00552 armPos.wrist1,
00553 armPos.wrist2,
00554 armPos.gripper,
00555 armPos.ex1,
00556 armPos.ex2);
00557
00558 setArmPos(armPos);
00559 return true;
00560 }
00561
00562 Scorbot::ArmPos Scorbot::readArmState()
00563 {
00564
00565 unsigned char command = 22;
00566 itsSerial->write(&command, 1);
00567 std::vector<unsigned char> serialData = itsSerial->readFrame(command);
00568
00569 if(serialData.size() != 16)
00570 {
00571 LERROR("Bad Serial Size!");
00572 return itsCurrentPos;
00573 }
00574
00575 ArmPos currPos;
00576
00577 currPos.base = (short int) ((int(0x00FF & serialData[0]) << 8) | (0x00FF & serialData[1]));
00578 currPos.sholder = (short int) ((int(0x00FF & serialData[2]) << 8) | (0x00FF & serialData[3]));
00579 currPos.elbow = (short int) ((int(0x00FF & serialData[4]) << 8) | (0x00FF & serialData[5]));
00580 currPos.wrist1 = (short int) ((int(0x00FF & serialData[6]) << 8) | (0x00FF & serialData[7]));
00581 currPos.wrist2 = (short int) ((int(0x00FF & serialData[8]) << 8) | (0x00FF & serialData[9]));
00582 currPos.gripper = (short int) ((int(0x00FF & serialData[10]) << 8) | (0x00FF & serialData[11]));
00583 currPos.ex1 = (unsigned int) ((int(0x00FF & serialData[12]) << 8) | (0x00FF & serialData[13]))*4;
00584 currPos.ex2 = (unsigned int) ((int(0x00FF & serialData[14]) << 8) | (0x00FF & serialData[15]))*4;
00585
00586 currPos.wristRoll = currPos.wrist1 + currPos.wrist2;
00587 currPos.wristPitch = currPos.wrist1 - currPos.wrist2;
00588
00589 currPos.baseMS = 0;
00590 currPos.sholderMS = 0;
00591 currPos.elbowMS = 0;
00592 currPos.wrist1MS = 0;
00593 currPos.wrist2MS = 0;
00594 currPos.gripperMS = 0;
00595 currPos.duration=0;
00596
00597
00598 return currPos;
00599 }
00600
00601 bool Scorbot::enableInternalPID()
00602 {
00603 LINFO("Enable PID");
00604 unsigned char cmd = 16;
00605 itsSerial->write(&cmd, 1);
00606 return true;
00607 }
00608
00609 bool Scorbot::disableInternalPID()
00610 {
00611 LINFO("Disable PID");
00612 unsigned char cmd = 17;
00613 itsSerial->write(&cmd, 1);
00614 return true;
00615 }
00616
00617 bool Scorbot::setJointPos(MOTOR joint, int position, bool relative, int duration)
00618 {
00619 unsigned char cmd[14];
00620
00621 LINFO("Joint %i position %i duration %i",
00622 joint, position, duration);
00623 cmd[0] = 19;
00624 cmd[1] = joint;
00625
00626 cmd[2] = (position >> 24) & 0xFF;
00627 cmd[3] = (position >> 16) & 0xFF;
00628 cmd[4] = (position >> 8) & 0xFF;
00629 cmd[5] = (position >> 0) & 0xFF;
00630
00631 cmd[6] = (duration >> 24) & 0xFF;
00632 cmd[7] = (duration >> 16) & 0xFF;
00633 cmd[8] = (duration >> 8) & 0xFF;
00634 cmd[9] = (duration >> 0) & 0xFF;
00635
00636 cmd[10] = 0xFF;
00637 cmd[11] = 0x00;
00638 cmd[12] = 0xFF;
00639 cmd[13] = 0x00;
00640
00641 printf("Sending: ");
00642 for(int i=0; i<14; i++)
00643 printf("%u ", (unsigned char)cmd[i]);
00644 printf("\n");
00645
00646 itsSerial->write(&cmd, 14);
00647
00648 sleep(1);
00649 char buff[1024];
00650
00651 int ret= itsSerial->read(buff, 1024);
00652 printf("Got %i: ", ret);
00653 for(int i=0; i<ret; i++)
00654 printf("%u ", buff[i]);
00655 printf("\n");
00656
00657
00658 return true;
00659 }
00660
00661 void Scorbot::paramChanged(ModelParamBase* const param,
00662 const bool valueChanged,
00663 ParamClient::ChangeStatus* status)
00664 {
00665 ModelComponent::paramChanged(param, valueChanged, status);
00666
00667 if (param == &itsBasePos ) { setJointPos(BASE, itsBasePos.getVal(), false, itsDuration.getVal()); }
00668 else if (param == &itsSholderPos ) { setJointPos(SHOLDER, itsSholderPos.getVal(), false, itsDuration.getVal()); }
00669 else if (param == &itsElbowPos ) { setJointPos(ELBOW, itsElbowPos.getVal(), false, itsDuration.getVal()); }
00670 else if (param == &itsWrist1Pos ) { setJointPos(WRIST1, itsWrist1Pos.getVal(), false, itsDuration.getVal()); }
00671 else if (param == &itsWrist2Pos ) { setJointPos(WRIST2, itsWrist2Pos.getVal(), false, itsDuration.getVal()); }
00672 else if (param == &itsGripperPos ) { setJointPos(GRIPPER, itsGripperPos.getVal(), false, itsDuration.getVal()); }
00673 else if (param == &itsEX1Pos ) { setJointPos(EX1, itsEX1Pos.getVal(), false, itsDuration.getVal()); }
00674 else if (param == &itsEX2Pos ) { setJointPos(EX2, itsEX2Pos.getVal(), false, itsDuration.getVal()); }
00675 else if (param == &itsMoveTo3D ) { set3DPos(false, itsDuration.getVal()); }
00676 else if (param == &itsInternalPIDen ) {
00677 if (itsInternalPIDen.getVal())
00678 enableInternalPID();
00679 else
00680 disableInternalPID();
00681 }
00682
00683 }
00684
00685
00686 bool Scorbot::setInternalPIDGain(MOTOR m, int P, int I, int D)
00687 {
00688 unsigned char cmd[14];
00689
00690 cmd[0] = 16;
00691 cmd[1] = m;
00692
00693 cmd[2] = 0x00FF & (P >> 24);
00694 cmd[3] = 0x00FF & (P >> 16);
00695 cmd[4] = 0x00FF & (P >> 8);
00696 cmd[5] = 0x00FF & (P >> 0);
00697
00698 cmd[6] = 0x00FF & (I >> 24);
00699 cmd[7] = 0x00FF & (I >> 16);
00700 cmd[8] = 0x00FF & (I >> 8);
00701 cmd[9] = 0x00FF & (I >> 0);
00702
00703 cmd[10] = 0x00FF & (D >> 24);
00704 cmd[11] = 0x00FF & (D >> 16);
00705 cmd[12] = 0x00FF & (D >> 8);
00706 cmd[13] = 0x00FF & (D >> 0);
00707
00708 itsSerial->write(&cmd, 14);
00709 return true;
00710 }
00711
00712 bool Scorbot::setInternalPos(ArmPos pos)
00713 {
00714 unsigned char cmd[15];
00715 LINFO("Setting Pos: %d", pos.ex1);
00716
00717 cmd[0] = 19;
00718 cmd[1] = 6;
00719 cmd[2] = 0x00FF & (pos.ex1 >> 24);
00720 cmd[3] = 0x00FF & (pos.ex1 >> 16);
00721 cmd[4] = 0x00FF & (pos.ex1 >> 8);
00722 cmd[5] = 0x00FF & (pos.ex1 >> 0);
00723
00724 unsigned char buf[256];
00725 itsSerial->write(&cmd, 14);
00726 usleep(1000000);
00727
00728 int bytes_read = itsSerial->read(buf, 4);
00729
00730 if(bytes_read == 4)
00731 {
00732 int d = ((0x00FF & buf[3]) << 24) |
00733 ((0x00FF & buf[2]) << 16) |
00734 ((0x00FF & buf[1]) << 8) |
00735 ((0x00FF & buf[0]) << 0);
00736
00737 int us = 80000000/1000000;
00738 int p = (-200*d)/(64*us) - 100;
00739
00740
00741 LINFO("MOTOR: %d", p);
00742 }
00743 else
00744 LINFO("ERROR! Read %d Bytes", bytes_read);
00745
00746
00747
00748 return true;
00749 }
00750
00751 bool Scorbot::setMotor(MOTOR m, int pwm)
00752 {
00753 unsigned char cmd[6];
00754
00755
00756 LINFO("Set motor %i pwm %i", m, pwm);
00757 if (pwm > MAX_PWM) pwm = MAX_PWM;
00758 if (pwm < -MAX_PWM) pwm = -MAX_PWM;
00759
00760 cmd[0] = 10;
00761
00762 if (m == WRIST_ROLL || m == WRIST_PITCH)
00763 {
00764 cmd[1] = WRIST1;
00765 cmd[3] = 10;
00766 cmd[4] = WRIST2;
00767
00768
00769 if (pwm >= 0)
00770 {
00771 cmd[2] = (short int)pwm&0x7F;
00772 }
00773 else
00774 {
00775 cmd[2] = (abs((short int)pwm)&0x7F) | 0x80;
00776 }
00777
00778 if (m == WRIST_ROLL)
00779 {
00780 if (pwm >= 0)
00781 {
00782 cmd[5] = (short int)pwm&0x7F;
00783 }
00784 else
00785 {
00786 cmd[5] = (abs((short int)pwm)&0x7F) | 0x80;
00787 }
00788 } else {
00789 if (pwm <= 0)
00790 {
00791 cmd[5] = abs((short int)pwm)&0x7F;
00792 }
00793 else
00794 {
00795 cmd[5] = (abs((short int)pwm)&0x7F) | 0x80;
00796 }
00797 }
00798
00799 itsSerial->write(cmd, 6);
00800 usleep(10000);
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812 return true;
00813
00814 } else {
00815 cmd[1] = m;
00816 if (pwm >= 0)
00817 cmd[2] = (short int)pwm&0x7F;
00818 else
00819 cmd[2] = (abs((short int)pwm)&0x7F) | 0x80;
00820
00821 itsSerial->write(cmd, 3);
00822 usleep(10000);
00823
00824 char buf[100];
00825 int bytes_read = itsSerial->read(buf, 1);
00826 while(bytes_read != 1)
00827 {
00828 bytes_read = itsSerial->read(buf, 1);
00829 usleep(10000);
00830 }
00831 LINFO("Got %i", bytes_read);
00832 for(int i=0; i<bytes_read; i++)
00833 LINFO("Bytes %i %u", i, buf[i]);
00834
00835
00836
00837
00838 return true;
00839 }
00840
00841 return false;
00842
00843
00844 }
00845
00846 bool Scorbot::motorsOff()
00847 {
00848 unsigned char cmd[1];
00849
00850
00851 LINFO("Turning motors off");
00852 cmd[0] = 15;
00853 itsSerial->write(cmd, 1);
00854
00855
00856
00857
00858
00859 return true;
00860 }
00861
00862 bool Scorbot::motorsOn()
00863 {
00864 unsigned char cmd[1];
00865
00866
00867 LINFO("Turning motors on");
00868 cmd[0] = 14;
00869 itsSerial->write(cmd, 1);
00870 usleep(50000);
00871
00872 itsSerial->read(cmd, 1);
00873 if (cmd[0] != 255)
00874 return false;
00875 else
00876 return true;
00877 }
00878
00879
00880
00881 bool Scorbot::stopAllMotors()
00882 {
00883 unsigned char cmd[1];
00884
00885
00886 cmd[0] = 11;
00887 itsSerial->write(cmd, 1);
00888
00889
00890
00891
00892
00893 return true;
00894 }
00895
00896
00897
00898 int Scorbot::getMicroSwitch()
00899 {
00900 unsigned char cmd;
00901 unsigned char buf = 11;
00902
00903
00904 int bytes_read;
00905
00906 std::vector<unsigned char> serialIn;
00907
00908 cmd = 21;
00909
00910 itsSerial->write(&cmd, 1);
00911
00912 while(1)
00913 {
00914 bytes_read = itsSerial->read(&buf, 1);
00915
00916 if(bytes_read > 0)
00917 {
00918 serialIn.push_back(buf);
00919
00920 if(serialIn.size() > 3)
00921 serialIn.erase(serialIn.begin());
00922
00923 if(serialIn.size() == 3)
00924 {
00925 if(serialIn.at(1) == 255 && serialIn.at(2) == 99)
00926 return serialIn.at(0);
00927 }
00928 }
00929 }
00930 return buf;
00931 }
00932
00933 char* Scorbot::getMicroSwitchByte()
00934 {
00935 return int2byte(getMicroSwitch());
00936 }
00937 bool Scorbot::getMicroSwitchMotor(RobotArm::MOTOR m)
00938 {
00939 int axis = -1;
00940 if(m == BASE)
00941 axis = 1;
00942 if(m == SHOLDER)
00943 axis = 2;
00944 if(m == ELBOW)
00945 axis = 3;
00946 if(m == WRIST_ROLL)
00947 axis = 5;
00948 if(m == WRIST_PITCH)
00949 axis = 4;
00950
00951 return !((getMicroSwitch() >> (8-axis)) & 0x01);
00952
00953 }
00954
00955 int Scorbot::getEncoder(MOTOR m)
00956 {
00957 std::vector<char> serialIn;
00958 unsigned char cmd[2];
00959 unsigned char buf[255];
00960
00961
00962 while(itsSerial->read(&buf, 255) > 0);
00963
00964 if (m == WRIST_ROLL || m == WRIST_PITCH)
00965 {
00966 int wrist1 = getEncoder(WRIST1);
00967 int wrist2 = getEncoder(WRIST2);
00968
00969 if (m==WRIST_PITCH)
00970 return wrist1-wrist2;
00971 else
00972 return wrist1+wrist2;
00973
00974 } else {
00975
00976 unsigned char axis = 0;
00977 switch(m)
00978 {
00979 case BASE:
00980 axis = 0;
00981 break;
00982 case SHOLDER:
00983 axis = 1;
00984 break;
00985 case ELBOW:
00986 axis = 2;
00987 break;
00988 case WRIST1:
00989 axis = 4;
00990 break;
00991 case WRIST2:
00992 axis = 3;
00993 break;
00994 case GRIPPER:
00995 axis = 5;
00996 break;
00997 case EX1:
00998 axis = 6;
00999 break;
01000 case EX2:
01001 axis = 7;
01002 break;
01003 default:
01004 LFATAL("UNKOWN axis: %d", axis);
01005 break;
01006 }
01007
01008 cmd[0] = 12;
01009
01010 cmd[1] = axis;
01011
01012 short val = 0;
01013 itsSerial->write(cmd, 2);
01014
01015
01016
01017 usleep(10000);
01018 int bytes_read = itsSerial->read(buf, 3);
01019
01020 while (bytes_read < 3)
01021 {
01022 bytes_read += itsSerial->read(buf+bytes_read, 3-bytes_read);
01023 usleep(10000);
01024 }
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047 val = (int(0x00FF & buf[0]) << 8) | (0x00FF & buf[1]);
01048
01049 if (m == EX1)
01050 return (unsigned short)val;
01051 else
01052 return (short int)val;
01053
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067
01068
01069
01070
01071
01072
01073
01074
01075 }
01076
01077 return 0;
01078 }
01079
01080 float Scorbot::getEncoderAng(MOTOR m)
01081 {
01082
01083 return 0;
01084
01085 }
01086
01087 void Scorbot::setSafety(bool val)
01088 {
01089 unsigned char cmd[2];
01090 cmd[0] = SAFE_MODE;
01091 if (val)
01092 cmd[1] = 1;
01093 else
01094 cmd[1] = 0;
01095
01096 itsSerial->write(cmd, 2);
01097 }
01098
01099 bool Scorbot::resetEncoders()
01100 {
01101 unsigned char cmd[1];
01102
01103 cmd[0] = 13;
01104 itsSerial->write(cmd, 1);
01105 usleep(50000);
01106
01107 itsSerial->read(cmd, 1);
01108 if (cmd[0] != 255)
01109 return false;
01110 else
01111 return true;
01112
01113 }
01114
01115 int Scorbot::getPWM(MOTOR m)
01116 {
01117 unsigned char cmd[2];
01118 unsigned char buf[2];
01119 cmd[0] = GET_PWM;
01120 cmd[1] = m;
01121 itsSerial->write(cmd, 2);
01122
01123 int i = itsSerial->read(buf, 1);
01124 if (i < 1) return -1;
01125 return buf[0];
01126 }
01127
01128 void Scorbot::setMotorPos(MOTOR m, int pos)
01129 {
01130
01131
01132 }
01133 void Scorbot::resetMotorPos(void)
01134 {
01135 }
01136
01137 void Scorbot::tunePID(MOTOR m, float p, float i, float d, bool relative)
01138 {
01139
01140 PID<float> *pid = 0;
01141
01142 switch(m)
01143 {
01144 case BASE:
01145 pid = &pidBase;
01146 break;
01147 case SHOLDER:
01148 pid = &pidSholder;
01149 break;
01150 case ELBOW:
01151 pid = &pidElbow;
01152 break;
01153 case GRIPPER:
01154 pid = &pidGripper;
01155 break;
01156 case EX1:
01157 pid = &pidEx1;
01158 break;
01159 case EX2:
01160 pid = &pidEx2;
01161 break;
01162 default:
01163 LERROR("INVALID TUNEPID MOTOR (%d)", m);
01164 return;
01165 }
01166
01167 if (relative)
01168 {
01169 pid->setPIDPgain(pid->getPIDPgain() + p);
01170 pid->setPIDIgain(pid->getPIDIgain() + i);
01171 pid->setPIDDgain(pid->getPIDDgain() + d);
01172 } else {
01173 pid->setPIDPgain(p);
01174 pid->setPIDIgain(i);
01175 pid->setPIDDgain(d);
01176 }
01177 LINFO("Setting PID p=%f i=%f d=%f",
01178 pid->getPIDPgain(),
01179 pid->getPIDIgain(),
01180 pid->getPIDDgain());
01181 }
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220
01221
01222
01223
01224
01225
01226
01227
01228
01229
01230
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241
01242
01243
01244
01245
01246
01247
01248
01249
01250
01251
01252
01253
01254
01255
01256
01257
01258
01259
01260
01261
01262
01263
01264
01265
01266
01267
01268
01269
01270
01271
01272
01273
01274
01275
01276
01277
01278
01279
01280
01281
01282
01283
01284
01285
01286
01287
01288
01289
01290
01291
01292
01293
01294
01295
01296
01297
01298
01299
01300
01301
01302
01303
01304
01305
01306
01307
01308
01309
01310
01311
01312
01313
01314 void Scorbot::homeMotors()
01315 {
01316 int EX1_LimitSeekSpeed = 40;
01317
01318 int Base_LimitSeekSpeed = -50;
01319 int Base_MSJumpSpeed = 100;
01320 float Base_MSJumpDelay = 3.5;
01321 int Base_MSSeekSpeed = 15;
01322
01323 int Sholder_LimitSeekSpeed = -25;
01324 int Sholder_MSJumpSpeed = 70;
01325 float Sholder_MSJumpDelay = 3.6;
01326 int Sholder_MSSeekSpeed = 10;
01327
01328 int Elbow_LimitSeekSpeed = -35;
01329 int Elbow_MSJumpSpeed = 90;
01330 float Elbow_MSJumpDelay = 1.8;
01331 int Elbow_MSSeekSpeed = 25;
01332
01333 int WristPitch_LimitSeekSpeed = 20;
01334 int WristPitch_MSJumpSpeed = 0;
01335 float WristPitch_MSJumpDelay = 0.0;
01336 int WristPitch_MSSeekSpeed = 20;
01337
01338 int WristRoll1_MSSeekSpeed = 25;
01339
01340 int WristRoll2_MSJumpSpeed = 15;
01341 float WristRoll2_MSJumpDelay = .1;
01342 int WristRoll2_MSSeekSpeed = 20;
01343
01344 int Gripper_LimitSeekSpeed = 40;
01345
01346 itsReadEncoders = false;
01347
01348 LINFO("Homing Slide");
01349 homeMotor(EX1, EX1_LimitSeekSpeed, 0, 0, 0, true, false);
01350
01351 LINFO("Homing Base");
01352 homeMotor(BASE, Base_LimitSeekSpeed, Base_MSJumpSpeed, Base_MSJumpDelay, Base_MSSeekSpeed, true, true);
01353
01354 LINFO("Homing Shoulder");
01355 homeMotor(SHOLDER, Sholder_LimitSeekSpeed, Sholder_MSJumpSpeed, Sholder_MSJumpDelay, Sholder_MSSeekSpeed, true, true);
01356
01357 LINFO("Homing Elbow");
01358 homeMotor(ELBOW, Elbow_LimitSeekSpeed, Elbow_MSJumpSpeed, Elbow_MSJumpDelay, Elbow_MSSeekSpeed, true, true);
01359
01360 LINFO("Homing Wrist Pitch");
01361 homeMotor(WRIST_PITCH, WristPitch_LimitSeekSpeed, WristPitch_MSJumpSpeed, WristPitch_MSJumpDelay, WristPitch_MSSeekSpeed, true, true);
01362
01363 LINFO("Homing Wrist Roll");
01364 homeMotor(WRIST_ROLL, 0, 0, 0, WristRoll1_MSSeekSpeed, true, true);
01365 homeMotor(WRIST_ROLL, 0, WristRoll2_MSJumpSpeed, WristRoll2_MSJumpDelay, WristRoll2_MSSeekSpeed, false, true);
01366
01367 LINFO("Homing Gripper");
01368 homeMotor(GRIPPER, Gripper_LimitSeekSpeed, 0, 0, 0, true, false);
01369
01370 stopAllMotors();
01371 resetEncoders();
01372 itsReadEncoders = true;
01373 LINFO("Finished Homing");
01374 }
01375
01376
01377
01378 void Scorbot::homeMotor(RobotArm::MOTOR axis, int LimitSeekSpeed, int MSJumpSpeed, float MSJumpDelay, int MSSeekSpeed, bool MSStopCondition, bool checkMS)
01379 {
01380 int lastPos = -1;
01381 int currPos = -1;
01382
01383
01384
01385
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398 if(checkMS)
01399 {
01400
01401
01402
01403
01404
01405
01406 setMotor(axis, MSSeekSpeed);
01407 LINFO("Looking for MS");
01408 while(getMicroSwitchMotor(axis) != MSStopCondition);
01409 } else {
01410 LINFO("Finding Limit");
01411 lastPos = getEncoder(axis);
01412 setMotor(axis, LimitSeekSpeed);
01413 usleep(500000);
01414 currPos = getEncoder(axis);
01415 while(abs(currPos - lastPos) > 0)
01416 {
01417 lastPos = currPos;
01418 currPos = getEncoder(axis);
01419 LINFO("Speed: %i", abs(currPos - lastPos));
01420 usleep(90000);
01421 }
01422 }
01423
01424 setMotor(axis,0);
01425 }
01426
01427 int Scorbot::getJointPos(MOTOR m)
01428 {
01429 switch(m)
01430 {
01431 case BASE: return itsCurrentPos.base;
01432 case SHOLDER: return itsCurrentPos.sholder;
01433 case ELBOW: return itsCurrentPos.elbow;
01434 case GRIPPER: return itsCurrentPos.gripper;
01435 case WRIST_ROLL: return itsCurrentPos.wristRoll;
01436 case WRIST_PITCH: return itsCurrentPos.wristPitch;
01437 case EX1: return itsCurrentPos.ex1;
01438 case EX2: return itsCurrentPos.ex2;
01439 default:
01440 LFATAL("UNKOWN axis: %d", m);
01441 break;
01442 }
01443
01444 return 999999;
01445 }
01446
01447 int Scorbot::write(const void* buffer, const int nbytes)
01448 {
01449 return itsSerial->write(buffer, nbytes);
01450 }
01451
01452 int Scorbot::read(void* buffer, const int nbytes)
01453 {
01454 return itsSerial->read(buffer, nbytes);
01455 }
01456
01457
01458
01459
01460
01461