00001 #include "Shared/RobotInfo.h"
00002 #include "Behaviors/Controller.h"
00003
00004 #ifndef TGT_HAS_ARMS
00005 class ArmController : public BehaviorBase {
00006 virtual void doStart() {
00007
00008 std::vector<std::string> errmsg;
00009 errmsg.push_back("The selected robot doesn't have an arm...");
00010 Controller::loadGUI("org.tekkotsu.mon.ControllerErr","",0,errmsg);
00011 stop();
00012 }
00013 };
00014 #else
00015
00016 #include "ArmController.h"
00017 #include "Motion/MMAccessor.h"
00018 #include "Motion/ArmMC.h"
00019 #include "Shared/RobotInfo.h"
00020 #include "Motion/PIDMC.h"
00021
00022 ArmController* ArmController::theOne = NULL;
00023
00024 void ArmController::doStart() {
00025
00026 SharedObject<ArmMC> arm;
00027 arm->setHold(false);
00028 arm_id = motman->addPersistentMotion(arm);
00029 SharedObject<PIDMC> pid;
00030 pidMCID = motman->addPersistentMotion(pid,MotionManager::kHighPriority);
00031
00032
00033 gripperFrameKJ->getRoot()->buildChildMap(KJjoints, ArmOffset, NumArmJoints);
00034
00035 int counter = 0;
00036 float alphaCum = 0;
00037 for (unsigned int i = 0; i < NumArmJoints; i++) {
00038 if (KJjoints[i] == NULL) break;
00039 if ( counter > 0
00040 && KJjoints[i]->theta != 0 )
00041 break;
00042
00043 alphaCum += KJjoints[i]->alpha;
00044 if ( std::abs(alphaCum) < 1e-5 && KJjoints[i]->jointType.get() == "revolute" ) {
00045 numYawJoints++;
00046 armConfig[counter++] = 'H';
00047 }
00048 else if ( std::abs(alphaCum) > 0.99*(M_PI/2) && KJjoints[i]->jointType.get() == "revolute" ) {
00049 numPitchJoints++;
00050 armConfig[counter++] = 'V';
00051 }
00052 }
00053 linksToDisplay = numPitchJoints + numYawJoints;
00054
00055 #ifdef TGT_LYNXARM6
00056 horScale = 20;
00057 #endif
00058
00059
00060
00061
00062 fmat::Column<3> armDims;
00063 fmat::Transform gripperToArm;
00064 const KinematicJoint* armJ = kine->getKinematicJoint(ArmOffset);
00065 const KinematicJoint* tmpJ = kine->getKinematicJoint(GripperFrameOffset);
00066 if ( armJ == NULL || tmpJ == NULL )
00067 std::cout << "Error in Arm Controller: can't find arm or gripper frame!\n";
00068 else
00069 while (tmpJ != armJ && tmpJ != NULL) {
00070 tmpJ = tmpJ->getParent();
00071 gripperToArm *= tmpJ->getTo().rigidInverse();
00072 }
00073 gripperToArm = gripperToArm.rigidInverse();
00074 armDims = gripperToArm.translation();
00075 horScale = verScale = armDims.norm();
00076 horScale /= 0.85;
00077
00078
00079 int horIndex = 0, verIndex = 0;
00080 fmat::Transform horT, verT;
00081 if (numYawJoints != 0) {
00082 while (armConfig[horIndex] != 'H')
00083 horIndex++;
00084 while (horIndex) {
00085 horT *= KJjoints[horIndex--]->getTo();
00086 }
00087 }
00088 if (numPitchJoints != 0) {
00089 while (armConfig[verIndex] != 'V')
00090 verIndex++;
00091 while (verIndex) {
00092 verT *= KJjoints[verIndex--]->getTo();
00093 }
00094 }
00095 horToBase = horT.translation();
00096 verToBase = verT.translation();
00097
00098
00099 theLastOne=theOne;
00100 theOne=this;
00101 cmdsock=wireless->socket(Socket::SOCK_STREAM, 2048, 2048);
00102 wireless->setReceiver(cmdsock->sock, mechacmd_callback);
00103 wireless->setDaemon(cmdsock,true);
00104 wireless->listen(cmdsock->sock, config->main.armControl_port);
00105
00106 Controller::loadGUI("org.tekkotsu.mon.ArmGUI","ArmGUI",config->main.armControl_port);
00107 }
00108
00109 void ArmController::doStop() {
00110 Controller::closeGUI("ArmGUI");
00111 erouter->removeListener(this);
00112 wireless->setDaemon(cmdsock,false);
00113 wireless->close(cmdsock);
00114 theOne=theLastOne;
00115 motman->removeMotion(arm_id);
00116 motman->removeMotion(pidMCID);
00117 }
00118
00119 void ArmController::doEvent() {
00120 if(event->getGeneratorID()==EventBase::timerEGID) {
00121 float normJointVal, jointAngle;
00122 for(unsigned int joint = 0; joint < NumArmJoints; joint++) {
00123 jointAngle = state->outputs[ArmOffset + joint];
00124
00125 normJointVal = (outputRanges[ArmOffset + joint][MaxRange] - jointAngle)/(outputRanges[ArmOffset + joint][MaxRange] - outputRanges[ArmOffset + joint][MinRange]);
00126 cmdsock->printf( "Value %d %d %f\n", -1, joint, normJointVal );
00127 }
00128
00129 computeCoords();
00130 sendCoords();
00131
00132
00133 if (displayMode == pitchAndYaw) {
00134 cmdsock->printf("RValue %f %f\n", -yawCoords[numYawJoints -1][0] / horScale, yawCoords[numYawJoints -1][1] / horScale);
00135 cmdsock->printf("RValue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00136 }
00137
00138
00139 if (displayMode == yawOnly) {
00140 cmdsock->printf("RValue %f %f\n", -yawCoords[numYawJoints -1][0] / horScale, yawCoords[numYawJoints -1][1] / horScale);
00141 }
00142
00143
00144 if (displayMode == pitchOnly) {
00145 cmdsock->printf("Rvalue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00146 }
00147 }
00148 }
00149
00150
00151 int ArmController::mechacmd_callback(char *buf, int bytes) {
00152 static char cb_buf[19];
00153 static int cb_buf_filled;
00154
00155
00156
00157
00158 if(cb_buf_filled) {
00159 while((cb_buf_filled < 19) && bytes) {
00160 cb_buf[cb_buf_filled++] = *buf++;
00161 --bytes;
00162 }
00163
00164 if(cb_buf_filled == 9 && ((unsigned char*)cb_buf)[0] != 'x') {
00165 if(ArmController::theOne) ArmController::theOne->runCommand((unsigned char*) cb_buf);
00166 cb_buf_filled = 0;
00167 }
00168
00169 if(cb_buf_filled == 19) {
00170 if(ArmController::theOne) ArmController::theOne->runCommand((unsigned char*) cb_buf);
00171 cb_buf_filled = 0;
00172 }
00173 }
00174
00175
00176 while(bytes >= 9) {
00177 if (((unsigned char*)buf)[0] != 'x') {
00178 if(ArmController::theOne) ArmController::theOne->runCommand((unsigned char *) buf);
00179 bytes -= 9;
00180 buf += 9;
00181 } else if (((unsigned char*)buf)[0] == 'x') {
00182 if(ArmController::theOne) ArmController::theOne->runCommand((unsigned char *) buf);
00183 bytes -= 19;
00184 buf += 19;
00185 }
00186 }
00187
00188
00189 while(bytes) {
00190 cb_buf[cb_buf_filled++] = *buf++;
00191 --bytes;
00192 }
00193
00194 return 0;
00195 }
00196
00197 void ArmController::runCommand(unsigned char *command) {
00198
00199 float param;
00200 float param2;
00201 float param3;
00202 int cmdno;
00203 unsigned char *paramp = (unsigned char *) ¶m;
00204 unsigned char *paramp2 = (unsigned char *) ¶m2;
00205 unsigned char *paramp3 = (unsigned char *) ¶m3;
00206 unsigned char *cmdnop = (unsigned char *) &cmdno;
00207
00208 #if defined(BYTE_ORDER) && BYTE_ORDER==BIG_ENDIAN
00209 paramp[0] = command[4];
00210 paramp[1] = command[3];
00211 paramp[2] = command[2];
00212 paramp[3] = command[1];
00213
00214 if (command[0] == 'x') {
00215 paramp2[0] = command[9];
00216 paramp2[1] = command[8];
00217 paramp2[2] = command[7];
00218 paramp2[3] = command[6];
00219
00220 paramp3[0] = command[14];
00221 paramp3[1] = command[13];
00222 paramp3[2] = command[12];
00223 paramp3[3] = command[11];
00224
00225 cmdnop[0] = command[18];
00226 cmdnop[1] = command[17];
00227 cmdnop[2] = command[16];
00228 cmdnop[3] = command[15];
00229 } else {
00230 cmdnop[0] = command[8];
00231 cmdnop[1] = command[7];
00232 cmdnop[2] = command[6];
00233 cmdnop[3] = command[5];
00234 }
00235 #else
00236 paramp[0] = command[1];
00237 paramp[1] = command[2];
00238 paramp[2] = command[3];
00239 paramp[3] = command[4];
00240
00241 if (command[0] == 'x') {
00242 paramp2[0] = command[6];
00243 paramp2[1] = command[7];
00244 paramp2[2] = command[8];
00245 paramp2[3] = command[9];
00246
00247 paramp3[0] = command[11];
00248 paramp3[1] = command[12];
00249 paramp3[2] = command[13];
00250 paramp3[3] = command[14];
00251
00252 cmdnop[0] = command[15];
00253 cmdnop[1] = command[16];
00254 cmdnop[2] = command[17];
00255 cmdnop[3] = command[18];
00256 } else {
00257 cmdnop[0] = command[5];
00258 cmdnop[1] = command[6];
00259 cmdnop[2] = command[7];
00260 cmdnop[3] = command[8];
00261 }
00262
00263 #endif // byte order
00264
00265
00266 switch(command[0]) {
00267 case CMD_connect:
00268 cmdConnect();
00269 break;
00270 case CMD_point:
00271 cmdPointPicker(param, param2, param3, cmdno);
00272 break;
00273 case CMD_gripper:
00274 cmdGripper(param, cmdno);
00275 break;
00276 case CMD_speed:
00277 speed = param;
00278 break;
00279 case CMD_relax:
00280 cmdRelax();
00281 break;
00282 case CMD_unrelax:
00283 cmdUnrelax();
00284 break;
00285 default: {
00286 setJoint( command[0], param );
00287 }
00288 }
00289 }
00290
00291
00292 void ArmController::cmdConnect() {
00293
00294
00295 if(numYawJoints > 0 && numPitchJoints > 0)
00296 displayMode = pitchAndYaw;
00297 else if(numYawJoints > 0 && numPitchJoints == 0)
00298 displayMode = yawOnly;
00299 else
00300 displayMode = pitchOnly;
00301
00302
00303 cmdsock->printf("NOJ %d %d\n", NumArmJoints, displayMode);
00304
00305
00306 for(unsigned int i = 0; i < NumArmJoints; i++)
00307 cmdsock->printf("Config %u %c\n", i, armConfig[i]);
00308
00309
00310 OriJoint = linksToDisplay - 1;
00311
00312
00313 cmdsock->printf("OriJoint %d %d %d\n", OriJoint, numYawJoints, numPitchJoints);
00314
00315
00316 float jointVal, normJointVal;
00317
00318 for(unsigned int joint = 0; joint < NumArmJoints; joint++) {
00319 jointVal = state->outputs[ArmOffset + joint];
00320 normJointVal = (outputRanges[ArmOffset + joint][MaxRange] - jointVal) /
00321 (outputRanges[ArmOffset + joint][MaxRange] - outputRanges[ArmOffset + joint][MinRange]);
00322 cmdsock->printf("JointParam %s %f %f %f\n", outputNames[ArmOffset + joint],
00323 outputRanges[ArmOffset + joint][MaxRange], outputRanges[ArmOffset + joint][MinRange], normJointVal);
00324 }
00325
00326
00327 if(numYawJoints > 0)
00328 cmdsock->printf("IRGValue %f %f\n", -yawCoords[numYawJoints - 1][0] / horScale, yawCoords[numYawJoints - 1][1] / horScale);
00329 if(numPitchJoints > 0)
00330 cmdsock->printf("IRGValue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00331
00332
00333 computeCoords();
00334 sendCoords();
00335
00336 }
00337
00338
00339 void ArmController::cmdPointPicker(float param, float param2, float param3, int cmdno) {
00340 #if TGT_TENTACLE
00341
00342 #else
00343 fmat::Column<3> tgtPoint;
00344 if (param3 == 1.0) {
00345 theta = std::atan2(-param,param2);
00346 tgtPoint[0] = param2 * horScale + horToBase[0];
00347 tgtPoint[1] = -param * horScale + horToBase[1];
00348 tgtPoint[2] = verZ * verScale;
00349 }
00350 else if (param3 == 2.0) {
00351 verZ = param2;
00352 tgtPoint[0] = (param * verScale + verToBase[0]) * std::cos(theta);
00353 tgtPoint[1] = tgtPoint[0] * std::tan(theta);
00354 tgtPoint[2] = param2 * verScale + verToBase[2];
00355 }
00356
00357 const KinematicJoint* tmpKJ = KJjoints[0];
00358
00359 while (tmpKJ->getParent() != NULL) {
00360 tgtPoint += tmpKJ->getTo().translation();
00361 tmpKJ = tmpKJ->getParent();
00362 }
00363
00364
00365 gripperFrameKJ->getIK().solve(fmat::Column<3>(), *gripperFrameKJ, IKSolver::Point(tgtPoint));
00366
00367 for(int joint = 0; joint < linksToDisplay; joint++) {
00368
00369 float normJointVal;
00370
00371
00372 float q = KJjoints[joint]->getQ();
00373
00374 if (q > outputRanges[ArmOffset + joint][MaxRange]) {
00375 q = outputRanges[ArmOffset + joint][MaxRange];
00376 normJointVal = 0;
00377 }
00378 else if (q < outputRanges[ArmOffset + joint][MinRange]) {
00379 q = outputRanges[ArmOffset + joint][MinRange];
00380 normJointVal = 1;
00381 }
00382 else {
00383
00384 normJointVal = (outputRanges[ArmOffset + joint][MaxRange] - q)/(outputRanges[ArmOffset + joint][MaxRange] - outputRanges[ArmOffset + joint][MinRange]);
00385 }
00386
00387 if(!std::isfinite(normJointVal))
00388 normJointVal = state->outputs[ArmOffset + joint];
00389 cmdsock->printf("CValue %d %d %f\n", cmdno, joint, normJointVal);
00390 }
00391 #endif
00392 }
00393
00394 void ArmController::cmdGripper(float param, int cmdno) {
00395 #ifdef TGT_HAS_GRIPPER
00396 float gripper = (1.0f - param) / 2.0f;
00397 # ifdef TGT_HAS_FINGERS
00398 float right = gripper;
00399 float left = 1.0f - gripper;
00400
00401 cmdsock->printf("CValue %d %d %f\n", cmdno, RightFingerOffset - ArmOffset, right);
00402 cmdsock->printf("CValue %d %d %f\n", cmdno, LeftFingerOffset - ArmOffset, left);
00403 # else
00404 cmdsock->printf("CValue %d %d %f\n", cmdno, GripperOffset - ArmOffset, gripper);
00405 # endif
00406 #endif
00407 }
00408
00409 void ArmController::cmdRelax() {
00410 MMAccessor<PIDMC> relaxer(pidMCID);
00411 for(unsigned int joint = 0; joint < NumArmJoints; joint++)
00412 relaxer->setJointPowerLevel(ArmOffset + joint, 0);
00413 processEvent(EventBase(EventBase::timerEGID,1,EventBase::statusETID,0));
00414 erouter->addTimer(this,0,500);
00415 }
00416
00417 void ArmController::cmdUnrelax() {
00418 erouter->removeTimer(this);
00419 MMAccessor<PIDMC> unrelaxer(pidMCID);
00420 for(unsigned int joint = 0; joint < NumArmJoints; joint++)
00421 unrelaxer->setJointPowerLevel(ArmOffset + joint, 1.0);
00422 }
00423
00424 void ArmController::setJoint(unsigned int joint, float param) {
00425 unsigned int jointNo = joint < NumArmJoints ? joint : joint - NumArmJoints;
00426 if (jointNo >= NumArmJoints) {
00427 std::cerr << "Illegal command to ArmController " << joint << " " << jointNo << " " << NumArmJoints << std::endl;
00428 return;
00429 }
00430
00431 MMAccessor<ArmMC> arm(arm_id);
00432 arm->setMaxSpeed(jointNo, speed);
00433
00434 float jointVal = -( param * (outputRanges[ArmOffset + jointNo][MaxRange] - outputRanges[ArmOffset + jointNo][MinRange]) ) + outputRanges[ArmOffset + jointNo][MaxRange];
00435 arm->setJointValue(jointNo, jointVal);
00436
00437 if(KJjoints[jointNo] != NULL)
00438 KJjoints[jointNo]->setQ(jointVal);
00439
00440 computeCoords();
00441 sendCoords();
00442
00443 if ( joint < NumArmJoints ) {
00444 switch (displayMode) {
00445 case pitchAndYaw:
00446
00447 cmdsock->printf("RValue %f %f\n", -yawCoords[numYawJoints -1][0] / horScale, yawCoords[numYawJoints -1][1] / horScale);
00448 cmdsock->printf("RValue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00449 break;
00450 case yawOnly:
00451
00452 cmdsock->printf("RValue %f %f\n", -yawCoords[numYawJoints -1][0] / horScale, yawCoords[numYawJoints -1][1] / horScale);
00453 break;
00454 case pitchOnly:
00455
00456 cmdsock->printf("Rvalue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00457 break;
00458 }
00459 }
00460 }
00461
00462
00463 void ArmController::computeCoords() {
00464
00465 fmat::Column<3> baseHorizontal;
00466 fmat::Column<3> baseVertical;
00467
00468
00469 for(int i = 0; i < linksToDisplay; i++){
00470 if(armConfig[i] == 'H'){
00471 baseHorizontal = KJjoints[i]->getWorldPosition();
00472 break;
00473 }
00474 }
00475
00476 for(int i = 0; i < linksToDisplay; i++){
00477 if(armConfig[i] == 'V'){
00478 baseVertical = KJjoints[i]->getWorldPosition();
00479 break;
00480 }
00481 }
00482
00483 int yawCount = 0, pitchCount = 0;
00484
00485
00486 for (int links = 0; links < linksToDisplay; links++){
00487 if (armConfig[links] == 'H'){
00488 KinematicJoint* relPosJoint;
00489 if (yawCount == numYawJoints - 1)
00490 relPosJoint = gripperFrameKJ;
00491 else
00492 relPosJoint = KJjoints[links+1];
00493 fmat::Column<3> relPos = relPosJoint->getWorldPosition() - baseHorizontal;
00494 yawCoords[yawCount][0] = relPos[1];
00495 yawCoords[yawCount][1] = relPos[0];
00496 yawCount++;
00497 }
00498 else if (armConfig[links] == 'V'){
00499 KinematicJoint* relPosJoint;
00500 if (pitchCount == numPitchJoints - 1)
00501 relPosJoint = gripperFrameKJ;
00502 else
00503 relPosJoint = KJjoints[links+1];
00504 fmat::Column<3> relPos = relPosJoint->getWorldPosition() - baseVertical;
00505 std::cout << relPos << " = " << relPosJoint->getWorldPosition() << " - " << baseVertical << std::endl;
00506 pitchCoords[pitchCount][0] = fmat::SubVector<2>(relPos).norm() * (yawCoords[yawCount-1][1] * relPos[0] > 0 ? 1 : -1);
00507 pitchCoords[pitchCount][1] = relPos[2];
00508 pitchCount++;
00509 }
00510 }
00511 }
00512
00513 void ArmController::sendCoords() {
00514
00515 switch (displayMode) {
00516 case pitchAndYaw:
00517 for(int links = 0; links < numYawJoints; links++)
00518 cmdsock->printf("Coord %d %f %f\n", links, -yawCoords[links][0]/horScale, yawCoords[links][1]/horScale);
00519 for(int links = 0; links < numPitchJoints; links++)
00520 cmdsock->printf("Coord1 %d %f %f\n", links, pitchCoords[links][0] / verScale, pitchCoords[links][1] / verScale);
00521
00522 cmdsock->printf("GValue %f %f\n", -yawCoords[numYawJoints - 1][0] / horScale, yawCoords[numYawJoints - 1][1] / horScale);
00523
00524
00525 cmdsock->printf("GValue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00526 break;
00527 case yawOnly:
00528 for(int links = 0; links < numYawJoints; links++)
00529 cmdsock->printf("Coord %d %f %f\n", links, -yawCoords[links][0]/horScale, yawCoords[links][1]/horScale);
00530
00531 cmdsock->printf("GValue %f %f\n", -yawCoords[numYawJoints - 1][0] / horScale, yawCoords[numYawJoints - 1][1] / horScale);
00532 break;
00533 case pitchOnly:
00534 for(int links = 0; links < numPitchJoints; links++)
00535 cmdsock->printf("Coord1 %d %f %f\n", links, pitchCoords[links][0] / verScale, pitchCoords[links][1] / verScale);
00536
00537 cmdsock->printf("GValue1 %f %f\n", pitchCoords[numPitchJoints - 1][0] / verScale, pitchCoords[numPitchJoints - 1][1] / verScale);
00538 }
00539 }
00540
00541 #endif // TGT_HAS_ARMS
00542
00543 REGISTER_BEHAVIOR_MENU_OPT(ArmController,"TekkotsuMon",BEH_NONEXCLUSIVE);
00544
00545
00546
00547
00548