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
00029 #include <iomanip>
00030 #include <QFile>
00031 #include <QTextStream>
00032
00033
00034 #include "SoArrow.h"
00035 #include <Inventor/nodes/SoCube.h>
00036
00037 #include "bBox.h"
00038 #include "mytools.h"
00039 #include "matvecIO.h"
00040 #include "robot.h"
00041 #include "joint.h"
00042 #include "dynJoint.h"
00043 #include "world.h"
00044 #include "grasp.h"
00045 #include "graspitGUI.h"
00046 #include "ivmgr.h"
00047 #include "dynamics.h"
00048 #include "gloveInterface.h"
00049 #include "eigenGrasp.h"
00050 #include "matrix.h"
00051 #include "tinyxml.h"
00052
00053 #ifdef USE_DMALLOC
00054 #include "dmalloc.h"
00055 #endif
00056
00057
00058 #include "debug.h"
00059
00060 #define PROF_ENABLED
00061 #include "profiling.h"
00062
00063 PROF_DECLARE(MOVE_DOF);
00064
00065 #define AUTO_GRASP_TIME_STEP 0.01
00066
00071 Robot::~Robot()
00072 {
00073 for (int i=0;i<numChains;i++) {
00074 if (chainVec[i]) delete chainVec[i];
00075 }
00076 for (int i=0;i<numDOF;i++) {
00077 if (dofVec[i]) delete dofVec[i];
00078 }
00079 if (base) myWorld->destroyElement(base);
00080 if (mountPiece) myWorld->destroyElement(mountPiece);
00081 if (parent) parent->detachRobot(this);
00082 if (mGloveInterface) delete mGloveInterface;
00083 if (mEigenGrasps) delete mEigenGrasps;
00084
00085 std::cout << "Deleted robot: " << name() <<std::endl;
00086 }
00087
00095 int
00096 Robot::loadFromXml(const TiXmlElement* root,QString rootPath)
00097 {
00098 QString robotName = root->Attribute("type");
00099 if(robotName.isNull()){
00100 QTWARNING("Robot Name undefined");
00101 return FAILURE;
00102 }
00103 const TiXmlElement* element = findXmlElement(root,"palm");
00104 QString valueStr;
00105 QString ivdir = rootPath + "iv/";
00106
00107 DBGA("Creating base...\n");
00108 if(element){
00109 valueStr = element->GetText();
00110 valueStr = valueStr.stripWhiteSpace();
00111 base = new Link(this,-1,-1,myWorld,(QString(name())+"Base").latin1());
00112 if (!base || base->load(ivdir+valueStr)==FAILURE) {
00113 if (base) delete base;
00114 base = NULL;
00115 DBGA("Failed to load base");
00116 return FAILURE;
00117 }
00118 base->addToIvc();
00119
00120
00121 IVRoot = new SoSeparator;
00122 IVRoot->addChild(base->getIVRoot());
00123 }
00124 else{
00125 QTWARNING("Base not found");
00126 return FAILURE;
00127 }
00128 std::list<const TiXmlElement*> elementList = findAllXmlElements(root, "dof");
00129 numDOF = countXmlElements(root, "dof");
00130 if (numDOF < 1) {
00131 DBGA("Wrong number of DOFs specified: " << numDOF);
00132 return FAILURE;
00133 }
00134 DBGA("Setting up " << numDOF << " degrees of freedom...");
00135 dofVec.resize(numDOF, NULL);
00136
00137
00138 std::list<const TiXmlElement*>::iterator p = elementList.begin();
00139 int f=0;
00140 while(p!=elementList.end()){
00141 valueStr = (*p)->Attribute("type");
00142 if(valueStr.isNull()){
00143 QTWARNING("DOF Type not found");
00144 return FAILURE;
00145 }
00146 QString dofType = valueStr.stripWhiteSpace();
00147 if(dofType == "r")
00148 dofVec[f] = new RigidDOF();
00149 else if(dofType == "b")
00150 dofVec[f] = new BreakAwayDOF();
00151 else if(dofType == "c")
00152 dofVec[f] = new CompliantDOF();
00153 else {
00154 DBGA("Unknown DOF Type requested: " << dofType.toStdString() << " for DOF " << f);
00155 return FAILURE;
00156 }
00157 dofVec[f]->dofNum = f;
00158 if (!dofVec[f]->readParametersFromXml(*p)) {
00159 DBGA("Failed to read DOF " << f );
00160 return FAILURE;
00161 }
00162 p++;
00163 f++;
00164 }
00165
00166
00167 numChains = countXmlElements(root,"chain");
00168 if (numChains < 1) {
00169 DBGA("Wrong number of chains");
00170 return FAILURE;
00171 }
00172 DBGA("Creating " << numChains << " kinematic chains (fingers)...");
00173 chainVec.resize(numChains, NULL);
00174
00175
00176 numJoints = 0;
00177 f = 0;
00178 elementList = findAllXmlElements(root, "chain");
00179 p = elementList.begin();
00180 while(p!=elementList.end()){
00181 fprintf(stderr, "Chain %d: ",f);
00182 chainVec[f] = new KinematicChain(this,f, numJoints);
00183 if (chainVec[f]->initChainFromXml((*p),ivdir)==FAILURE) {
00184 DBGA("Failed to read chain " << f);
00185 return FAILURE;
00186 }
00187 numJoints += chainVec[f]->getNumJoints();
00188 p++;
00189 f++;
00190 }
00191
00192
00193 std::list<Joint *>jointList;
00194 for (int d=0; d<numDOF; d++) {
00195 jointList.clear();
00196 for (int f=0; f<numChains; f++) {
00197 for (int j=0; j<chainVec[f]->getNumJoints(); j++) {
00198 if (chainVec[f]->getJoint(j)->getDOFNum() == d) {
00199 jointList.push_back(chainVec[f]->getJoint(j));
00200 }
00201 }
00202 }
00203 dofVec[d]->initDOF(this,jointList);
00204 }
00205
00206
00207 getBase()->fix();
00208 for (int i=0; i<getNumDOF(); i++) {
00209 getDOF(i)->setDesiredPos( getDOF(i)->getVal() );
00210 }
00211
00212
00213
00214
00215 approachTran = transf::IDENTITY;
00216 element = findXmlElement(root,"approachDirection");
00217 if(element){
00218 const TiXmlElement* tmp = findXmlElement(element,"referenceLocation");
00219 if(!tmp){
00220 DBGA("Failed to read approach direction");
00221 return FAILURE;
00222 }
00223 valueStr = tmp->GetText();
00224 valueStr = valueStr.simplifyWhiteSpace().stripWhiteSpace();
00225 QStringList l = QStringList::split(' ', valueStr);
00226 if(l.count()!=3){
00227 DBGA("Invalid approach direction input");
00228 return FAILURE;
00229 }
00230 bool ok1, ok2, ok3;
00231 float locX, locY, locZ;
00232 locX = l[0].toFloat(&ok1);
00233 locY = l[1].toFloat(&ok2);
00234 locZ = l[2].toFloat(&ok3);
00235 if(!ok1 || !ok2 || !ok3){
00236 DBGA("Invalid approach direction input");
00237 return FAILURE;
00238 }
00239 vec3 aPt = vec3(locX, locY, locZ);
00240
00241 tmp = findXmlElement(element,"direction");
00242 if(!tmp){
00243 DBGA("Failed to read approach direction");
00244 return FAILURE;
00245 }
00246 valueStr = tmp->GetText();
00247 valueStr = valueStr.simplifyWhiteSpace().stripWhiteSpace();
00248 l = QStringList::split(' ', valueStr);
00249 if(l.count()!=3){
00250 DBGA("Invalid approach direction input");
00251 return FAILURE;
00252 }
00253 locX = l[0].toFloat(&ok1);
00254 locY = l[1].toFloat(&ok2);
00255 locZ = l[2].toFloat(&ok3);
00256 if(!ok1 || !ok2 || !ok3){
00257 DBGA("Invalid approach direction input");
00258 return FAILURE;
00259 }
00260 vec3 zdir = vec3(locX, locY, locZ);
00261 zdir = normalise(zdir);
00262
00263 vec3 xdir;
00264 if ( fabs(zdir % vec3(1,0,0)) > 0.9 ) xdir = vec3(0,1,0);
00265 else xdir = vec3(1,0,0);
00266 vec3 ydir = zdir * xdir;
00267 xdir = ydir * zdir;
00268
00269 mat3 r(xdir, ydir, zdir);
00270 approachTran.set(r, aPt);
00271 }
00272 addApproachGeometry();
00273
00274
00275 mEigenGrasps = new EigenGraspInterface(this);
00276 bool eigenLoaded = false;
00277 element = findXmlElement(root,"eigenGrasps");
00278 if(element) {
00279 valueStr = element->GetText();
00280 valueStr = valueStr.stripWhiteSpace();
00281 QString eigenFile = rootPath + valueStr;
00282 if (loadEigenData(eigenFile)==SUCCESS) {
00283 DBGA("Using eigengrasps from file: " << valueStr.latin1());
00284 eigenLoaded = true;
00285 }
00286 }
00287 if (!eigenLoaded) {
00288 mEigenGrasps->setTrivial();
00289 DBGA("Using identity eigengrasps");
00290 }
00291
00292
00293 element = findXmlElement(root,"virtualContacts");
00294 if(element){
00295 valueStr = element->GetText();
00296 valueStr = valueStr.stripWhiteSpace();
00297 QString contactFile = rootPath + valueStr;
00298 if (loadContactData(contactFile)==SUCCESS) {
00299 DBGA("Loaded virtual contacts from file " << valueStr.latin1());
00300 showVirtualContacts(true);
00301 } else {
00302 DBGA("Failed to load virtual contacts from file " << valueStr.latin1());
00303 }
00304 }
00305
00306
00307 mUseCyberGlove = false;
00308 element = findXmlElement(root,"cyberGlove");
00309 if(element){
00310 valueStr = element->GetText();
00311 valueStr = valueStr.stripWhiteSpace();
00312 mGloveInterface = new GloveInterface(this);
00313 QString calibFile = rootPath + valueStr;
00314 if (!mGloveInterface->loadCalibration(calibFile.latin1())) {
00315 DBGA("Failed to load glove calibration file " << calibFile.latin1());
00316 delete mGloveInterface; mGloveInterface = NULL;
00317 mUseCyberGlove = false;
00318 } else {
00319 DBGA("Cyberglove calibration loaded from " << calibFile.latin1());
00320 mUseCyberGlove = true;
00321 }
00322 }
00323
00324
00325 element = findXmlElement(root,"flockOfBirds");
00326 if(element){
00327 QString birdNumber = element->Attribute("number");
00328 if(birdNumber.isNull()){
00329 DBGA("There was a problem reading the Flock of Birds data in the configuration file");
00330 return FAILURE;
00331 }
00332 birdNumber = birdNumber.stripWhiteSpace();
00333 mBirdNumber = birdNumber.toInt();
00334 transf sensorTrans;
00335 const TiXmlElement* tmp = findXmlElement(element,"transform");
00336 if(!getTransform(tmp, sensorTrans)){
00337 DBGA("There was a problem reading the Flock of Birds data in the configuration file");
00338 return FAILURE;
00339 }
00340 mFlockTran.identity();
00341 mFlockTran.setMount(sensorTrans);
00342 mUsesFlock = true;
00343 DBGA("Robot using Flock of Birds sensor " << mBirdNumber);
00344 }
00345 if (mUsesFlock) {
00346 addFlockSensorGeometry();
00347 }
00348 return SUCCESS;
00349 }
00350
00352 int
00353 Robot::loadEigenData(QString filename)
00354 {
00355 if ( !mEigenGrasps->readFromFile(filename.latin1()) ) {
00356 DBGA("Unable to load eigenGrasp file " << filename.latin1());
00357 return FAILURE;
00358 }
00359 QString name = filename.section('/',-1,-1);
00360 name = name.section('.',0,0);
00361 mEigenGrasps->setName(name);
00362 return SUCCESS;
00363 }
00364
00367 int
00368 Robot::loadContactData(QString filename)
00369 {
00370 FILE *fp = fopen(filename.latin1(), "r");
00371 if (!fp) {
00372 DBGA("Could not open contact file " << filename.latin1());
00373 return FAILURE;
00374 }
00375
00376 char robotName[500];
00377 fscanf(fp,"%s",robotName);
00378
00379 int numContacts;
00380 fscanf(fp,"%d",&numContacts);
00381 for (int i=0; i<numContacts; i++) {
00382 VirtualContact* newContact = new VirtualContact();
00383 newContact->readFromFile(fp);
00384 int f = newContact->getFingerNum();
00385 int l = newContact->getLinkNum();
00386 if ( f >= 0) {
00387 if ( f>=getNumChains() || l>=getChain(f)->getNumLinks()) {
00388 DBGA("Virtual contact error, chain " << f << " link " << l << " does not exist");
00389 delete newContact;
00390 continue;
00391 }
00392 newContact->setBody( getChain(f)->getLink(l) );
00393 getChain(f)->getLink(l)->addVirtualContact( newContact );
00394 }
00395 else {
00396 newContact->setBody( getBase() );
00397 getBase()->addVirtualContact(newContact);
00398 }
00399 newContact->computeWrenches(false,false);
00400 }
00401 fclose(fp);
00402 return SUCCESS;
00403 }
00404
00415 void
00416 Robot::cloneFrom(Robot *original)
00417 {
00418 myName = original->getName() + QString(" clone");
00419
00420
00421 if (base) delete base;
00422 base = new Link(this,-1,-1,myWorld,(QString(name())+"Base").latin1());
00423 base->cloneFrom( original->getBase() );
00424
00425 IVRoot = new SoSeparator;
00426 IVRoot->addChild(base->getIVRoot());
00427
00428 numDOF = original->getNumDOF();
00429 dofVec.resize(numDOF, NULL);
00430 for (int f=0; f<numDOF; f++) {
00431 switch(original->getDOF(f)->getType()) {
00432 case DOF::RIGID:
00433 dofVec[f] = new RigidDOF( (RigidDOF*)(original->getDOF(f)) );
00434 break;
00435 case DOF::BREAKAWAY:
00436 dofVec[f] = new BreakAwayDOF( (BreakAwayDOF*)(original->getDOF(f)) );
00437 break;
00438 case DOF::COMPLIANT:
00439 dofVec[f] = new CompliantDOF( (CompliantDOF*)(original->getDOF(f)) );
00440 break;
00441 default:
00442 DBGA("ERROR: Unknown DOF type in original!");
00443 assert(0);
00444 }
00445 }
00446
00447 numChains = original->getNumChains();
00448 chainVec.resize(numChains, NULL);
00449 numJoints = 0;
00450 for (int f=0; f<numChains; f++) {
00451 chainVec[f] = new KinematicChain(this,f,numJoints);
00452 chainVec[f]->cloneFrom( original->getChain(f) );
00453 numJoints += chainVec[f]->getNumJoints();
00454 }
00455 assert (numJoints == original->getNumJoints() );
00456
00457 std::list<Joint *>jointList;
00458 for (int d=0; d<numDOF; d++) {
00459 jointList.clear();
00460 for (int f=0; f<numChains; f++) {
00461 for (int j=0; j<chainVec[f]->getNumJoints(); j++) {
00462 if (chainVec[f]->getJoint(j)->getDOFNum() == d) {
00463 jointList.push_back(chainVec[f]->getJoint(j));
00464 }
00465 }
00466 }
00467 dofVec[d]->initDOF(this,jointList);
00468 }
00469
00470 base->setTran(transf::IDENTITY);
00471
00472 getBase()->fix();
00473 for (int i=0; i<getNumDOF(); i++) {
00474 getDOF(i)->setDesiredPos( getDOF(i)->getVal() );
00475 }
00476
00477 setRenderGeometry( original->getRenderGeometry() );
00478
00479
00480 approachTran = original->getApproachTran();
00481 addApproachGeometry();
00482
00483
00484 mEigenGrasps = new EigenGraspInterface(original->getEigenGrasps());
00485
00486
00487 mGloveInterface = NULL;
00488 this->mUseCyberGlove = false;
00489 }
00490
00494 void
00495 Robot::setTransparency(float t)
00496 {
00497 base->setTransparency(t);
00498 for (int i=0; i<getNumChains(); i++) {
00499 for (int l=0; l<getChain(i)->getNumLinks(); l++) {
00500 getChain(i)->getLink(l)->setTransparency(t);
00501 }
00502 }
00503 }
00504
00508 void
00509 Robot::setName(QString newName)
00510 {
00511 WorldElement::setName(newName);
00512 for (int c=0; c<getNumChains(); c++) {
00513 for (int l=0; l<getChain(c)->getNumLinks(); l++){
00514 getChain(c)->getLink(l)->setName( newName + QString("_chain%1_link%2").arg(c).arg(l) );
00515 }
00516 }
00517 if (base) base->setName(newName + QString("_base"));
00518 }
00519
00524 void
00525 Robot::addApproachGeometry()
00526 {
00527 IVApproachRoot = new SoSeparator();
00528
00529 SoTransform *t1 = new SoTransform();
00530 approachTran.toSoTransform(t1);
00531 IVApproachRoot->addChild(t1);
00532
00533 SoArrow *arrow = new SoArrow;
00534 arrow->height = 14;
00535 arrow->cylRadius = (float)1.25;
00536 arrow->coneRadius = (float)2.6;
00537 arrow->coneHeight = (float)5.5;
00538 SoTransform *arrowTran = new SoTransform();
00539 arrowTran->rotation.setValue(SbVec3f(1,0,0),(float)(M_PI/2.0));
00540 IVApproachRoot->addChild(arrowTran);
00541 IVApproachRoot->addChild(arrow);
00542
00543 getBase()->getIVRoot()->addChild(IVApproachRoot);
00544 }
00545
00550 void
00551 Robot::addFlockSensorGeometry()
00552 {
00553 IVFlockRoot = new SoSeparator();
00554 SoTransform *t = new SoTransform();
00555 mFlockTran.getMount().toSoTransform( t );
00556 IVFlockRoot->addChild(t);
00557 SoCube *cube = new SoCube();
00558 cube->width = 30;
00559 cube->height = 20;
00560 cube->depth = 4;
00561 IVFlockRoot->addChild(cube);
00562 SoCube *smallCube = new SoCube();
00563 smallCube->width = 10;
00564 smallCube->height = 20;
00565 smallCube->depth = 6;
00566 SoTransform *t2 = new SoTransform();
00567 t2->translation.setValue(10,0,-5);
00568 IVFlockRoot->addChild(t2);
00569 IVFlockRoot->addChild(smallCube);
00570 getBase()->getIVRoot()->addChild(IVFlockRoot);
00571 }
00572
00577 int
00578 Robot::useIdentityEigenData()
00579 {
00580 if (!mEigenGrasps->setTrivial()) {
00581 QTWARNING("Error setting Identity EigenGrasps");
00582 return FAILURE;
00583 }
00584 return SUCCESS;
00585 }
00586
00591 void Robot::setGlove(CyberGlove *glove)
00592 {
00593 if (!mGloveInterface) {
00594 mUseCyberGlove = false;
00595 return;
00596 }
00597 mGloveInterface->setGlove(glove);
00598 }
00599
00604 void
00605 Robot::processCyberGlove()
00606 {
00607 int i;
00608 double *desiredVals = new double[getNumDOF()];
00609 for (i=0; i<getNumDOF(); i++) {
00610 if ( mGloveInterface->isDOFControlled(i) ) {
00611 desiredVals[i] = mGloveInterface->getDOFValue(i);
00612 if ( desiredVals[i] < getDOF(i)->getMin() ) desiredVals[i] = getDOF(i)->getMin();
00613 if ( desiredVals[i] > getDOF(i)->getMax() ) desiredVals[i] = getDOF(i)->getMax();
00614 }
00615 else {
00616 desiredVals[i] = getDOF(i)->getVal();
00617 }
00618 }
00619 moveDOFToContacts(desiredVals, NULL, false);
00620 emitConfigChange();
00621 delete [] desiredVals;
00622 }
00623
00628 Link *
00629 Robot::importMountPiece(QString filename)
00630 {
00631 QString mountName = QString(name())+"_mount";
00632 mountPiece = new Link(this,-1,-1,myWorld,mountName.latin1());
00633 if (mountPiece->load(filename)==FAILURE){
00634 delete mountPiece; mountPiece = NULL; return NULL;
00635 }
00636 mountPiece->addToIvc();
00637 IVRoot->addChild(mountPiece->getIVRoot());
00638 mountPiece->setTran(base->getTran());
00639 base->setDynJoint(new FixedDynJoint(mountPiece,base));
00640 return mountPiece;
00641 }
00642
00646 void
00647 Robot::getBodyList(std::vector<Body*> *bodies)
00648 {
00649 if (base) bodies->push_back(base);
00650 if (mountPiece) bodies->push_back(mountPiece);
00651 for (int c=0; c<numChains; c++) {
00652 for (int l=0; l<chainVec[c]->getNumLinks(); l++) {
00653 bodies->push_back(chainVec[c]->getLink(l));
00654 }
00655 }
00656 for (int c=0; c<numChains; c++) {
00657 for (int i=0; i<chainVec[c]->getNumAttachedRobots(); i++) {
00658 chainVec[c]->getAttachedRobot(i)->getBodyList(bodies);
00659 }
00660 }
00661 }
00662
00667 void
00668 Robot::getAllLinks(std::vector<DynamicBody *> &allLinkVec)
00669 {
00670 int c,l,i;
00671 if (base) allLinkVec.push_back(base);
00672 if (mountPiece) allLinkVec.push_back(mountPiece);
00673
00674 for (c=0;c<numChains;c++)
00675 for (l=0;l<chainVec[c]->getNumLinks();l++)
00676 allLinkVec.push_back(chainVec[c]->getLink(l));
00677 for (c=0;c<numChains;c++)
00678 for (i=0;i<chainVec[c]->getNumAttachedRobots();i++)
00679 chainVec[c]->getAttachedRobot(i)->getAllLinks(allLinkVec);
00680 }
00681
00686 void
00687 Robot::getAllAttachedRobots(std::vector<Robot *> &robotVec)
00688 {
00689 robotVec.push_back(this);
00690 for (int c=0;c<numChains;c++) {
00691 for (int i=0;i<chainVec[c]->getNumAttachedRobots();i++) {
00692 chainVec[c]->getAttachedRobot(i)->getAllAttachedRobots(robotVec);
00693 }
00694 }
00695 }
00696
00697
00708 void
00709 Robot::attachRobot(Robot *r,int chainNum,const transf &offsetTr)
00710 {
00711 r->parent = this;
00712 r->parentChainNum = chainNum;
00713 r->tranToParentEnd = offsetTr.inverse();
00714 chainVec[chainNum]->attachRobot(r,offsetTr);
00715
00716 Link *lastLink = chainVec[chainNum]->getLink(chainVec[chainNum]->getNumLinks()-1);
00717 myWorld->toggleCollisions(false, lastLink, r->getBase());
00718 if (r->getMountPiece()) {
00719 myWorld->toggleCollisions(false, lastLink, r->getMountPiece());
00720 }
00721 }
00722
00723
00728 void
00729 Robot::detachRobot(Robot *r)
00730 {
00731 DBGA("Detaching Robot " << r->getName().latin1() << " from " << getName().latin1());
00732 r->parent = NULL;
00733 chainVec[r->parentChainNum]->detachRobot(r);
00734 }
00735
00736
00743 void
00744 Robot::fwdKinematics(double* dofVals,std::vector<transf>& trVec,int chainNum)
00745 {
00746 double *jointVals = new double[numJoints];
00747 getJointValues(jointVals);
00748 for (int d=0; d<numDOF; d++) {
00749 dofVec[d]->accumulateMove(dofVals[d], jointVals, NULL);
00750 }
00751 chainVec[chainNum]->fwdKinematics(jointVals,trVec);
00752 delete [] jointVals;
00753 }
00754
00760 int
00761 Robot::invKinematics(const transf& targetPos, double* dofVals, int chainNum)
00762 {
00763
00764
00765 double factor = 0, epsilon = 0.0001, upperBound = 0.2;
00766 const int safeGuardUpperBound = 200;
00767 Matrix deltaPR(6,1);
00768 deltaPR.setAllElements(1.0);
00769 Matrix deltaDOF(numDOF, 1);
00770 std::vector<double> currentDOFVals(numDOF);
00771
00772 for(int i = 0; i < numDOF; ++i){
00773
00774 currentDOFVals[i] = dofVec[i]->getVal();
00775
00776 dofVals[i] = dofVec[i]->getVal();
00777 }
00778
00779 std::vector<transf> fwdK;
00780 fwdK.resize(chainVec[chainNum]->getNumLinks(), transf::IDENTITY);
00781 transf currentPos;
00782
00783
00784
00785
00786 fwdKinematics(¤tDOFVals[0], fwdK, chainNum);
00787 currentPos = fwdK[chainVec[chainNum]->getNumLinks() - 1];
00788
00789 DBGP("from: " << currentPos.translation().x() << " " <<
00790 currentPos.translation().y() << " " <<
00791 currentPos.translation().z() << " " <<
00792 currentPos.rotation().w << " " <<
00793 currentPos.rotation().x << " " <<
00794 currentPos.rotation().y << " " <<
00795 currentPos.rotation().z);
00796
00797 DBGP("to: " << targetPos.translation().x() << " " <<
00798 targetPos.translation().y() << " " <<
00799 targetPos.translation().z() << " " <<
00800 targetPos.rotation().w << " " <<
00801 targetPos.rotation().x << " " <<
00802 targetPos.rotation().y << " " <<
00803 targetPos.rotation().z);
00804
00805 int safeguard = 0;
00806 while(++safeguard < safeGuardUpperBound){
00807
00808
00809 fwdKinematics(¤tDOFVals[0], fwdK, chainNum);
00810 currentPos = fwdK[chainVec[chainNum]->getNumLinks() - 1];
00811
00812 vec3 dtLocation, dtOrientation;
00813 dtLocation = targetPos.translation() - currentPos.translation();
00814
00815 vec3 v1, v2;
00816 mat3 m1, m2;
00817 currentPos.rotation().ToRotationMatrix(m1);
00818 targetPos.rotation().ToRotationMatrix(m2);
00819
00820 v1 = vec3(m1.element(0,0), m1.element(0,1), m1.element(0,2));
00821 v2 = vec3(m2.element(0,0), m2.element(0,1), m2.element(0,2));
00822 dtOrientation = v1 * v2;
00823 v1 = vec3(m1.element(1,0), m1.element(1,1), m1.element(1,2));
00824 v2 = vec3(m2.element(1,0), m2.element(1,1), m2.element(1,2));
00825 dtOrientation += v1 * v2;
00826 v1 = vec3(m1.element(2,0), m1.element(2,1), m1.element(2,2));
00827 v2 = vec3(m2.element(2,0), m2.element(2,1), m2.element(2,2));
00828 dtOrientation += v1 * v2;
00829 dtOrientation *= 0.5;
00830
00831 deltaPR.elem(0,0) = dtLocation[0];
00832 deltaPR.elem(1,0) = dtLocation[1];
00833 deltaPR.elem(2,0) = dtLocation[2];
00834 deltaPR.elem(3,0) = dtOrientation[0];
00835 deltaPR.elem(4,0) = dtOrientation[1];
00836 deltaPR.elem(5,0) = dtOrientation[2];
00837
00838 Matrix m = chainVec[chainNum]->actuatedJacobian(chainVec[chainNum]->linkJacobian(true));
00839 Matrix jointJacobian = m.getSubMatrix(m.rows() - 6, 0, 6, chainVec[chainNum]->getNumJoints());
00840 Matrix jointToDOFJacobian = getJacobianJointToDOF(chainNum);
00841 Matrix DOFJacobian = Matrix(jointJacobian.rows(), jointToDOFJacobian.cols());
00842 matrixMultiply(jointJacobian, jointToDOFJacobian, DOFJacobian);
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855
00856
00857
00858
00859 underDeterminedSolveQR(DOFJacobian, deltaPR, deltaDOF);
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 for(int i = 0; i < numDOF; ++i){
00870
00871 currentDOFVals[i] += deltaDOF.elem(i,0);
00872
00873 currentDOFVals[i] -= (int)(currentDOFVals[i]/(2*M_PI)) * 2 * M_PI;
00874 }
00875
00876
00877 factor = -1.0;
00878 for(int i = 0; i < deltaDOF.cols(); ++i){
00879 factor = factor > fabs(deltaDOF.elem(i,0)) ? factor : fabs(deltaDOF.elem(i,0));
00880 }
00881
00882
00883 if(factor < epsilon){
00884 for(int k = 0; k < numDOF; ++k){
00885
00886
00887 if(fabs(dofVals[k] - currentDOFVals[k]) > upperBound){
00888 std::cout << "exceeds the upper bound at DOF: " << k << " , jumping to another pose\n";
00889 return FAILURE;
00890 }
00891 dofVals[k] = currentDOFVals[k];
00892 }
00893 break;
00894 }
00895 }
00896
00897 for(int i = 0; i < numChains; ++i){
00898 for(int j = 0; j < chainVec[i]->getNumJoints(); ++j){
00899 double jnt = dofVals[chainVec[i]->getJoint(j)->getDOFNum()] *
00900 chainVec[i]->getJoint(j)->getCouplingRatio();
00901 if(jnt > chainVec[i]->getJoint(j)->getMax() ||
00902 jnt < chainVec[i]->getJoint(j)->getMin()){
00903 std::cout << "inverse kinematics in invalid joint value: " << i << "th chain, " << j << "th joint\n";
00904 return FAILURE;
00905 }
00906 }
00907 }
00908
00909 if(safeguard >= safeGuardUpperBound){
00910 std::cout << "safeguard hit\n";
00911 return FAILURE;
00912 }
00913
00914
00915
00916
00917
00918
00919
00920
00921
00922
00923
00924 return SUCCESS;
00925 }
00926
00934 bool
00935 Robot::simpleContactsPreventMotion(const transf& motion) const
00936 {
00937 transf linkMotion;
00938 transf baseToLink;
00939
00940 for (int i=0;i<numChains;i++) {
00941 for (int j=0; j<chainVec[i]->getNumLinks();j++) {
00942 if (chainVec[i]->getLink(j)->getNumContacts()) {
00943 baseToLink = chainVec[i]->getLink(j)->getTran() * base->getTran().inverse();
00944 linkMotion = baseToLink * motion * baseToLink.inverse();
00945 if (chainVec[i]->getLink(j)->externalContactsPreventMotion(linkMotion))
00946 return true;
00947 }
00948 }
00949
00950 for (int j=0;j<chainVec[i]->getNumAttachedRobots();j++) {
00951 baseToLink = chainVec[i]->getAttachedRobot(j)->getBase()->getTran() * base->getTran().inverse();
00952 linkMotion = baseToLink * motion * baseToLink.inverse();
00953 if (chainVec[i]->getAttachedRobot(j)->simpleContactsPreventMotion(linkMotion))
00954 return true;
00955 }
00956 }
00957 return false;
00958 }
00959
00960
00969 bool
00970 Robot::contactsPreventMotion(const transf& motion) const
00971 {
00972 int l;
00973 transf linkMotion;
00974
00975
00976 if (base->externalContactsPreventMotion(motion)) return true;
00977 if (mountPiece && mountPiece->contactsPreventMotion(motion)) return true;
00978
00979
00980 if (simpleContactsPreventMotion(motion)) return true;
00981
00982
00983
00984 if (parent) {
00985 transf newTran = tranToParentEnd*motion*base->getTran();
00986 KinematicChain *chain = parent->getChain(parentChainNum);
00987 std::vector<transf> parentTrVec(chain->getNumLinks());
00988 double *dofVals = new double[parent->getNumDOF()];
00989
00990 if (parent->invKinematics(newTran,dofVals,parentChainNum)==FAILURE){
00991 delete [] dofVals;
00992 return true;
00993 }
00994
00995 parent->fwdKinematics(dofVals,parentTrVec,parentChainNum);
00996 delete [] dofVals;
00997
00998 for (l=0;l<chain->getNumLinks();l++) {
00999 if (chain->getLink(l)->getNumContacts()) {
01000 linkMotion = parentTrVec[l] * chain->getLink(l)->getTran().inverse();
01001 if (chain->getLink(l)->contactsPreventMotion(linkMotion)) {
01002 return true;
01003 }
01004 }
01005 }
01006 }
01007 return false;
01008 }
01009
01011 void
01012 Robot::breakContacts()
01013 {
01014 for (int f=0; f<getNumChains(); f++) {
01015 for (int l=0; l<getChain(f)->getNumLinks(); l++) {
01016 getChain(f)->getLink(l)->breakContacts();
01017 }
01018 }
01019 base->breakContacts();
01020 if (mountPiece) mountPiece->breakContacts();
01021 }
01022
01023
01031 void
01032 Robot::setRenderGeometry(bool s)
01033 {
01034 mRenderGeometry = s;
01035 if (parent) parent->setRenderGeometry(s);
01036 for (int c=0; c<numChains; c++) {
01037 for (int j=0; j<chainVec[c]->getNumAttachedRobots(); j++) {
01038 chainVec[c]->getAttachedRobot(j)->setRenderGeometry(s);
01039 }
01040 }
01041 for (int f=0; f<getNumChains(); f++) {
01042 for (int l=0; l<getChain(f)->getNumLinks(); l++) {
01043 getChain(f)->getLink(l)->setRenderGeometry(s);
01044 }
01045 }
01046 base->setRenderGeometry(s);
01047 if (mountPiece) mountPiece->setRenderGeometry(s);
01048 }
01049
01056 int
01057 Robot::setTran(const transf& tr)
01058 {
01059 if (parent) {
01060 double *dofVals = new double[parent->getNumDOF()];
01061 transf parentBaseToEnd = tranToParentEnd*tr;
01062 if (parent->invKinematics(parentBaseToEnd,dofVals,parentChainNum)==FAILURE) {
01063 delete [] dofVals;
01064 return FAILURE;
01065 }
01066 parent->forceDOFVals(dofVals);
01067 delete [] dofVals;
01068 } else {
01069 simpleSetTran(tr);
01070 }
01071 return SUCCESS;
01072 }
01073
01077 int
01078 Robot::getNumLinks() const
01079 {
01080 int links=0;
01081 for (int k=0; k<getNumChains(); k++) {
01082 links += chainVec[k]->getNumLinks();
01083 }
01084 links++;
01085 if (mountPiece) links++;
01086 return links;
01087 }
01088
01093 int
01094 Robot::getNumContacts(Body *body)
01095 {
01096 int c = getBase()->getNumContacts(body);
01097 for (int f=0; f<getNumChains(); f++) {
01098 c += getChain(f)->getNumContacts(body);
01099 }
01100 return c;
01101 }
01102
01107 std::list<Contact*>
01108 Robot::getContacts(Body* body)
01109 {
01110 std::list<Contact*> contacts;
01111 std::list<Contact*> chainContacts = getBase()->getContacts(body);
01112 contacts.insert(contacts.end(),chainContacts.begin(), chainContacts.end());
01113 for (int f=0; f<getNumChains(); f++) {
01114 chainContacts = getChain(f)->getContacts(body);
01115 contacts.insert(contacts.end(),chainContacts.begin(), chainContacts.end());
01116 }
01117 return contacts;
01118 }
01119
01123 int
01124 Robot::getNumVirtualContacts()
01125 {
01126 int c = getBase()->getNumVirtualContacts();
01127 for (int f=0; f<getNumChains(); f++) {
01128 for (int l=0; l<getChain(f)->getNumLinks(); l++) {
01129 c += getChain(f)->getLink(l)->getNumVirtualContacts();
01130 }
01131 }
01132 return c;
01133 }
01134
01140 void
01141 Robot::showVirtualContacts(bool on)
01142 {
01143 int s; bool b;
01144 if (on) s = 1;
01145 else s = 2;
01146 b = getBase()->frictionConesShown();
01147 getBase()->showFrictionCones(b, s);
01148 for (int f=0; f<getNumChains(); f++) {
01149 for (int l=0; l<getChain(f)->getNumLinks(); l++) {
01150 b = getChain(f)->getLink(l)->frictionConesShown();
01151 getChain(f)->getLink(l)->showFrictionCones( b, s );
01152 }
01153 }
01154 }
01155
01156
01157
01163 void
01164 Robot::saveState()
01165 {
01166 savedTran = getTran();
01167 savedDOF.clear();
01168 QTextStream stream(&savedDOF,QIODevice::ReadWrite);
01169 writeDOFVals(stream);
01170 savedState = true;
01171 }
01172
01177 void
01178 Robot::restoreState()
01179 {
01180 if (!savedState) {
01181 DBGA("Warning: hand state not saved!");
01182 if (savedDOF.size()==0) {
01183 DBGA("Saved DOF data absent; can not restore");
01184 return;
01185 }
01186 }
01187 savedState = false;
01188 setTran( savedTran );
01189 QTextStream stream(&savedDOF,QIODevice::ReadOnly);
01190 readDOFVals(stream);
01191 }
01192
01196 QTextStream&
01197 Robot::readDOFVals(QTextStream &is)
01198 {
01199 for (int d=0; d<numDOF; d++) {
01200 if (!dofVec[d]->readFromStream(is)) {
01201 DBGA("Failed to read DOF " << d << " from stream");
01202 return is;
01203 }
01204 }
01205
01206
01207
01208 double *jointVals = new double[numJoints];
01209 for (int d=0; d<numDOF; d++) {
01210 dofVec[d]->getJointValues(jointVals);
01211 }
01212 setJointValuesAndUpdate(jointVals);
01213 delete [] jointVals;
01214 return is;
01215 }
01216
01220 QTextStream&
01221 Robot::writeDOFVals(QTextStream &os)
01222 {
01223 for (int d=0; d<numDOF; d++) {
01224 dofVec[d]->writeToStream(os);
01225 os << " ";
01226 }
01227 return os;
01228 }
01229
01230
01231
01236 void Robot::setJointValues(const double* jointVals)
01237 {
01238 for (int c=0; c<numChains; c++) {
01239 chainVec[c]->setJointValues(jointVals);
01240 }
01241 }
01242
01248 void Robot::setJointValuesAndUpdate(const double* jointVals)
01249 {
01250 for (int c=0; c<numChains; c++) {
01251 chainVec[c]->setJointValues(jointVals);
01252 chainVec[c]->updateLinkPoses();
01253 }
01254 }
01255
01256
01273 int
01274 Robot::interpolateJoints(double *initialVals, double *finalVals,
01275 CollisionReport *colReport, double *interpolationTime)
01276 {
01277 double *currentVals = new double[ getNumJoints() ];
01278 double minDist,t = 0.0,deltat = 1.0;
01279 while (deltat > 1.0e-20 && t >= 0) {
01280
01281 DBGP("DOF joint interpolation cycle")
01282 deltat *= 0.5;
01283 for (int j=0; j<getNumJoints(); j++) {
01284 currentVals[j] = t*finalVals[j] + (1.0-t)*initialVals[j];
01285 }
01286 setJointValuesAndUpdate(currentVals);
01287
01288 minDist = 1.0e10;
01289 for (int i=0; i<(int)colReport->size(); i++) {
01290 minDist = MIN(minDist,myWorld->getDist( (*colReport)[i].first, (*colReport)[i].second));
01291 if ( minDist <= 0 ) {
01292 t -= deltat;
01293 break;
01294 }
01295 }
01296 if (minDist > 0) {
01297 if (minDist < 0.5 * Contact::THRESHOLD) break;
01298 t += deltat;
01299 }
01300 }
01301
01302 int retVal;
01303 if (deltat < 1.0e-20 || t < 0) {
01304 #ifdef GRASPITDBG
01305 std::cerr << "t: " << t << " d: " << deltat << std::endl;
01306 std::cerr << "I am " << getName().latin1() << std::endl;
01307 for (int i=0; i<(int)colReport->size(); i++) {
01308 std::cerr << (*colReport)[i].first->getName().latin1()<<" -- "
01309 << (*colReport)[i].second->getName().latin1() << std::endl;
01310 }
01311 std::cerr << "min dist: " << minDist << std::endl << std::endl;
01312 #endif
01313 DBGA("Robot joint interpolation error");
01314 retVal = 0;
01315 } else {
01316 DBGP("Interpolation to t=" << t << " (deltat=" << deltat << ")");
01317 retVal = 1;
01318 }
01319 delete [] currentVals;
01320 *interpolationTime = t;
01321 return retVal;
01322 }
01323
01330 void Robot::stopJointsFromLink(Link *link, double *desiredJointVals, int *stoppedJoints)
01331 {
01332 if (link->getChainNum()<0) return;
01333 KinematicChain *chain = chainVec[link->getChainNum()];
01334 for (int j=chain->getLastJoint( link->getLinkNum() ); j>=0; j--) {
01335 int jnum = chain->getJoint(j)->getNum();
01336 if (desiredJointVals[jnum] > chain->getJoint(j)->getVal()) {
01337
01338 stoppedJoints[jnum] |= 1;
01339 } else if (desiredJointVals[jnum] < chain->getJoint(j)->getVal()){
01340
01341 stoppedJoints[jnum] |= 2;
01342 }
01343 }
01344 }
01345
01362 bool
01363 Robot::getJointValuesFromDOF(const double *desiredDofVals, double *actualDofVals,
01364 double *jointVals, int *stoppedJoints)
01365 {
01366 bool done,moving;
01367 std::vector<transf> newLinkTran;
01368 DBGP("Getting joint movement from DOFs");
01369 do {
01370 moving = false; done = true;
01371 getJointValues(jointVals);
01372
01373 for (int d=0;d<numDOF;d++){
01374
01375
01376 if (dofVec[d]->accumulateMove(desiredDofVals[d], jointVals,stoppedJoints)) {
01377 moving = true;
01378 actualDofVals[d] = desiredDofVals[d];
01379 DBGP("DOF " << d << " is moving");
01380 } else {
01381 actualDofVals[d] = dofVec[d]->getVal();
01382 }
01383 }
01384 if (!moving) {
01385 DBGP("No DOF movement; done.");
01386 break;
01387 }
01388
01389 for (int c = 0; c < getNumChains(); c++) {
01390 KinematicChain *chain = getChain(c);
01391 newLinkTran.resize(chain->getNumLinks(), transf::IDENTITY);
01392 chain->infinitesimalMotion(jointVals, newLinkTran);
01393 for (int l=0; l<chain->getNumLinks(); l++){
01394 Link *link = chain->getLink(l);
01395 transf motion = newLinkTran[l];
01396 if ( link->contactsPreventMotion(motion) ) {
01397 DBGP("Chain " << link->getChainNum() << " link " << link->getLinkNum() << " is blocked.");
01398
01399 stopJointsFromLink(link, jointVals, stoppedJoints);
01400 done = false;
01401
01402
01403 break;
01404 }
01405 }
01406 }
01407 if (done) {
01408 DBGP("All movement OK; done.");
01409 }
01410 } while (!done);
01411 return moving;
01412 }
01413
01441 bool
01442 Robot::jumpDOFToContact(double *desiredVals, int *stoppedJoints, int *numCols)
01443 {
01444 CollisionReport colReport, lateContacts;
01445
01446
01447 double *newDofVals = new double[ getNumDOF() ];
01448 double *initialDofVals = new double [ getNumDOF() ];
01449 getDOFVals(initialDofVals);
01450
01451 double *newJointVals = new double[ getNumJoints() ];
01452 double *initialJointVals = new double[ getNumJoints() ];
01453 getJointValues(initialJointVals);
01454
01455 if (!getJointValuesFromDOF(desiredVals, newDofVals, newJointVals, stoppedJoints)) {
01456 DBGP("No movement of DOFs; forceDOFTo returning false");
01457 if (numCols) *numCols = 0;
01458 delete [] initialJointVals; delete [] newJointVals;
01459 delete [] initialDofVals; delete [] newDofVals;
01460 return false;
01461 }
01462
01463
01464
01465 std::vector<Body*> interestList;
01466 for (int c=0; c<numChains; c++) {
01467 for (int l=0; l<chainVec[c]->getNumLinks(); l++) {
01468 int j = chainVec[c]->getLastJoint(l);
01469 if ( !stoppedJoints[ chainVec[c]->getJoint(j)->getNum() ] ) {
01470 interestList.push_back( chainVec[c]->getLink(l) );
01471 }
01472 }
01473 }
01474
01475 setJointValuesAndUpdate(newJointVals);
01476 bool interpolationError = false;
01477 double interpolationTime;
01478 while (1) {
01479 myWorld->getCollisionReport(&colReport, &interestList);
01480
01481 if (colReport.empty()) break;
01482
01483
01484 getJointValues(newJointVals);
01485 if (!interpolateJoints(initialJointVals, newJointVals, &colReport, &interpolationTime)) {
01486 DBGA("Interpolation failed!");
01487 interpolationError = true;
01488 break;
01489 }
01490
01491 lateContacts.clear();
01492 for (int i=0;i<(int)colReport.size();i++) {
01493 lateContacts.push_back( colReport[i] );
01494 DBGP("Contact: " << colReport[i].first->getName().latin1() << "--" <<
01495 colReport[i].second->getName().latin1());
01496 }
01497 for (int d=0; d<numDOF; d++) {
01498 DBGP("Dof " << d << "initial " << initialDofVals[d] << " new " << newDofVals[d]);
01499 newDofVals[d] = newDofVals[d] * interpolationTime +
01500 initialDofVals[d] * ( 1.0 - interpolationTime);
01501 DBGP("Interpolated: " << newDofVals[d]);
01502 }
01503 }
01504
01505 if (!interpolationError) {
01506 DBGP("ForceDOFTo done");
01507 myWorld->findContacts(lateContacts);
01508 for (int i=0; i<(int)lateContacts.size(); i++) {
01509 if (lateContacts[i].first->getOwner()==this) {
01510 stopJointsFromLink( (Link*)lateContacts[i].first, newJointVals, stoppedJoints);
01511 }
01512 if (lateContacts[i].second->getOwner()==this) {
01513 stopJointsFromLink( (Link*)lateContacts[i].second, newJointVals, stoppedJoints);
01514 }
01515 }
01516 updateDofVals(newDofVals);
01517 if (numCols) *numCols = (int)lateContacts.size();
01518 }
01519
01520 delete [] initialDofVals; delete [] newDofVals;
01521 delete [] initialJointVals; delete [] newJointVals;
01522
01523 if (!interpolationError) return true;
01524 else return false;
01525 }
01526
01527
01556 bool
01557 Robot::moveDOFToContacts(double *desiredVals, double *desiredSteps, bool stopAtContact, bool renderIt)
01558 {
01559
01560
01561 PROF_TIMER_FUNC(MOVE_DOF);
01562
01563 int i,d;
01564 CollisionReport result;
01565
01566 double *stepSize= new double[numDOF];
01567 double *currVals = new double[numDOF];
01568 double *newVals = new double[numDOF];
01569
01570 for (i=0;i<numDOF;i++) {
01571 if (!desiredSteps || desiredSteps[i] == WorldElement::ONE_STEP ) {
01572 stepSize[i] = desiredVals[i] - dofVec[i]->getVal();
01573 } else if (desiredSteps[i]!=0.0) {
01574
01575 double factor = 1.0;
01576 if (desiredVals[i] < dofVec[i]->getVal()) factor = -1.0;
01577 stepSize[i] = factor * fabs(desiredSteps[i]);
01578 } else {
01579 stepSize[i] = 0.0;
01580 desiredVals[i] = dofVec[i]->getVal();
01581 }
01582 DBGP("from " << dofVec[i]->getVal() << " to " << desiredVals[i] << " in " << stepSize[i] << " steps");
01583 }
01584
01585
01586
01587 int *stoppedJoints = new int[numJoints];
01588 for (int j=0; j<numJoints; j++) {
01589 stoppedJoints[j] = 0;
01590 }
01591
01592
01593 int numCols,itercount = 0;
01594 bool moved = false;
01595 do {
01596 itercount++;
01597 DBGP("Move to contact cycle");
01598 getDOFVals(currVals);
01599 for (d=0;d<numDOF;d++) {
01600 newVals[d] = currVals[d] + stepSize[d];
01601 DBGP(" Current value (a): " << currVals[d] << "; new value: " << newVals[d] <<
01602 "; step size: " << stepSize[d]);
01603 if (stepSize[d] > 0 && newVals[d] > desiredVals[d])
01604 newVals[d] = desiredVals[d];
01605 else if (stepSize[d] < 0 && newVals[d] < desiredVals[d])
01606 newVals[d] = desiredVals[d];
01607 DBGP(" Current value (b): " << currVals[d] << "; new value: " << newVals[d]);
01608 }
01609
01610
01611 if (!jumpDOFToContact(newVals, stoppedJoints, &numCols)){
01612 DBGP("ForceDOFTo reports no movement is possible");
01613 break;
01614 }
01615 moved = true;
01616 bool stopRequest = false;
01617
01618 emit moveDOFStepTaken(numCols, stopRequest);
01619 if (stopRequest) {
01620 DBGP("Receiver of movement signal requests early exit");
01621 break;
01622 }
01623
01624 if (stopAtContact && numCols != 0) {
01625 DBGP("Stopping at first contact");
01626 break;
01627 }
01628 if (itercount > 500) {
01629 DBGA("MoveDOF failsafe hit");
01630 break;
01631 }
01632 if (renderIt && (itercount%25==0) && graspItGUI && graspItGUI->getIVmgr()->getWorld()==myWorld) {
01633 graspItGUI->getIVmgr()->getViewer()->render();
01634 }
01635 } while (1);
01636
01637
01638
01639
01640 delete [] currVals;
01641 delete [] newVals;
01642 delete [] stepSize;
01643 delete [] stoppedJoints;
01644 return moved;
01645 }
01646
01653 bool
01654 Robot::checkDOFPath(double *desiredVals, double desiredStep)
01655 {
01656 int d;
01657 bool done, success = true;
01658
01659 double *stepSize= new double[numDOF];
01660 double *currVals = new double[numDOF];
01661 double *newVals = new double[numDOF];
01662
01663 for (d=0;d<numDOF;d++) {
01664 if (desiredStep == WorldElement::ONE_STEP )
01665 stepSize[d] = desiredVals[d] - dofVec[d]->getVal();
01666 else if ( desiredVals[d] >= dofVec[d]->getVal() )
01667 stepSize[d] = desiredStep;
01668 else stepSize[d] = - desiredStep;
01669 }
01670
01671 do {
01672 DBGP("Move to contact cycle")
01673 getDOFVals(currVals);
01674 for (d=0;d<numDOF;d++) {
01675 newVals[d] = currVals[d] + stepSize[d];
01676 if (stepSize[d] > 0 && newVals[d] > desiredVals[d])
01677 newVals[d] = desiredVals[d];
01678 else if (stepSize[d] < 0 && newVals[d] < desiredVals[d])
01679 newVals[d] = desiredVals[d];
01680 }
01681
01682 forceDOFVals(newVals);
01683
01684 if ( !myWorld->noCollision() ) {
01685 success = false;
01686 break;
01687 }
01688
01689 done = true;
01690 for (d=0;d<numDOF;d++) {
01691 if (newVals[d] != desiredVals[d]) done = false;
01692 }
01693
01694 } while (!done);
01695
01696 delete [] currVals;
01697 delete [] newVals;
01698 delete [] stepSize;
01699 return success;
01700 }
01701
01702
01703
01714 Matrix
01715 Robot::staticJointTorques(bool useDynamicDofForce)
01716 {
01717 std::vector<double> jointTorques(getNumJoints(), 0.0);
01718 for (int d=0; d<numDOF; d++) {
01719 double dofForce = -1;
01720 if (useDynamicDofForce) {
01721 dofForce = dofVec[d]->getForce();
01722 }
01723 dofVec[d]->computeStaticJointTorques(&jointTorques[0], dofForce);
01724 }
01725 return Matrix(&jointTorques[0], getNumJoints(), 1, true);
01726 }
01727
01728
01729
01736 double
01737 Robot::getApproachDistance(Body *object, double maxDist)
01738 {
01739 position p0 = position(0,0,0) * getApproachTran() * getTran();
01740 position p = p0;
01741 vec3 app = vec3(0,0,1) * getApproachTran() * getTran();
01742 bool done = false;
01743 double totalDist = 0;
01744 vec3 direction;
01745 int loops = 0;
01746 while (!done) {
01747 loops++;
01748
01749 direction = myWorld->pointDistanceToBody(p, object);
01750
01751
01752 position pc = p; pc+=direction;
01753
01754 if ( normalise(pc-p0) % app > 0.86 ) {
01755 done = true;
01756 }
01757
01758 double d = direction.len();
01759 totalDist += d;
01760 p += d * app;
01761 if (totalDist > maxDist) done = true;
01762 if (loops > 10) {
01763 done = true;
01764 totalDist = maxDist+1;
01765 DBGA("Force exit from gettAppDist");
01766 }
01767 }
01768
01769
01770 return totalDist;
01771 }
01772
01778 bool
01779 Robot::snapChainToContacts(int chainNum, CollisionReport colReport)
01780 {
01781 bool persistent = true;
01782
01783 KinematicChain *chain = getChain(chainNum);
01784 chain->filterCollisionReport(colReport);
01785 if (colReport.empty()) {
01786 DBGP("Snap to chain "<<chainNum<<" done from the start - no collisions");
01787 return true;
01788 }
01789
01790 std::vector<double> openVals(numDOF);
01791 std::vector<double> closedVals(numDOF);
01792 std::vector<double> openJointVals(numJoints);
01793 std::vector<double> closedJointVals(numJoints);
01794 CollisionReport openColReport;
01795
01796 getDOFVals(&closedVals[0]);
01797 getDOFVals(&openVals[0]);
01798 getJointValues(&closedJointVals[0]);
01799
01800 double SNAP = 0.1;
01801 while (1) {
01802 bool limitHit = true;
01803 int l = chain->getNumLinks() - 1;
01804 for (int j=chain->getLastJoint(l); j>=0; j--) {
01805 int d = chain->getJoint(j)->getDOFNum();
01806 double current = dofVec[d]->getVal();
01807 double target;
01808 if (dofVec[d]->getDefaultVelocity() < 0) {
01809 target = current + SNAP;
01810 if ( target > dofVec[d]->getMax() ) target = dofVec[d]->getMax();
01811 else limitHit = false;
01812 } else if (dofVec[d]->getDefaultVelocity() > 0) {
01813 target = current - SNAP;
01814 if ( target < dofVec[d]->getMin()) target = dofVec[d]->getMin();
01815 else limitHit = false;
01816 } else target = current;
01817 openVals[d] = target;
01818 }
01819
01820 forceDOFVals(&openVals[0]);
01821 myWorld->getCollisionReport(&openColReport);
01822 chainVec[chainNum]->filterCollisionReport(openColReport);
01823 if ( !openColReport.empty() ) {
01824 if (persistent && !limitHit) {
01825
01826 forceDOFVals(&closedVals[0]);
01827 SNAP += 0.1;
01828 }
01829 else break;
01830 } else {
01831 break;
01832 }
01833 }
01834 if (!openColReport.empty()) {
01835 DBGP("Snap to chain "<<chainNum<<" done - open position in collision");
01836 forceDOFVals(&closedVals[0]);
01837 return false;
01838 }
01839
01840 DBGP("Open values valid");
01841 getJointValues(&openJointVals[0]);
01842 double time;
01843 if (!interpolateJoints(&openJointVals[0], &closedJointVals[0], &colReport, &time)) {
01844 DBGP("Snap to chain "<<chainNum<<" interpolation failed");
01845 forceDOFVals(&closedVals[0]);
01846 return false;
01847 } else {
01848
01849 for (int d=0; d<numDOF; d++) {
01850 closedVals[d] = closedVals[d] * time + openVals[d] * ( 1.0 - time);
01851 }
01852 updateDofVals(&closedVals[0]);
01853 }
01854 DBGP("Snap to chain "<<chainNum<<" success");
01855 myWorld->findContacts(colReport);
01856 return true;
01857 }
01858
01859
01860
01861
01876 void
01877 Robot::setDesiredDOFVals(double *dofVals)
01878 {
01879 int i,j,d,numSteps;
01880 double timeNeeded;
01881 double t;
01882 double coeffs[5];
01883 double tpow,q1,q0,qd0,qd1;
01884 double *traj;
01885
01886 for (d=0;d<numDOF;d++) {
01887 if (dofVec[d]->getDefaultVelocity() == 0.0) continue;
01888
01889 DBGP("DOF "<<d<<" trajectory");
01890 dofVec[d]->setDesiredPos(dofVals[d]);
01891 if (dofVec[d]->getVal() != dofVals[d]) {
01892
01893 q0 = dofVec[d]->getVal();
01894 q1 = dofVals[d];
01895 qd0 = 0.0;
01896 qd1 = 0.0;
01897
01898 timeNeeded = fabs(dofVals[d]-dofVec[d]->getVal()) / fabs( dofVec[d]->getDesiredVelocity() );
01899
01900
01901 numSteps = (int)ceil(timeNeeded/myWorld->getTimeStep());
01902 timeNeeded = numSteps*myWorld->getTimeStep();
01903
01904 DBGP("numSteps: "<< numSteps << " time needed: " << timeNeeded);
01905 traj = new double[numSteps];
01906
01907 for (i=0;i<numSteps;i++) {
01908 t = (double)i/(double)(numSteps-1);
01909 coeffs[4] = 6.0*(q1 - q0) - 3.0*(qd1+qd0)*timeNeeded;
01910 coeffs[3] = -15.0*(q1 - q0) + (8.0*qd0 + 7.0*qd1)*timeNeeded;
01911 coeffs[2] = 10.0*(q1 - q0) - (6.0*qd0 + 4.0*qd1)*timeNeeded;
01912 coeffs[1] = 0.0;
01913 coeffs[0] = qd0*timeNeeded;
01914 traj[i] = q0;
01915
01916 tpow = 1.0;
01917 for (j=0;j<5;j++) {
01918 tpow *= t;
01919 traj[i] += tpow*coeffs[j];
01920 }
01921 DBGP(i << " " << t << " " << traj[i]);
01922 }
01923 dofVec[d]->setTrajectory(traj,numSteps);
01924 delete [] traj;
01925 }
01926 }
01927 }
01928
01934 void
01935 Robot::setChainEndTrajectory(std::vector<transf>& traj,int chainNum)
01936 {
01937 int i,j,numPts = traj.size();
01938 double *dofVals = new double[numDOF];
01939 bool *dofInChain = new bool[numDOF];
01940
01941 if (numPts < 1 || chainNum < 0 || chainNum > numChains-1) return;
01942 for (j=0;j<numDOF;j++)
01943 dofInChain[j] = false;
01944
01945 for (j=0;j<chainVec[chainNum]->getNumJoints();j++)
01946 dofInChain[chainVec[chainNum]->getJoint(j)->getDOFNum()] = true;
01947
01948 invKinematics(traj[0],dofVals,chainNum);
01949 for (j=0;j<numDOF;j++)
01950 if (dofInChain[j]) dofVec[j]->setTrajectory(&dofVals[j],1);
01951
01952 for (i=1;i<numPts;i++) {
01953 invKinematics(traj[i],dofVals,chainNum);
01954 for (j=0;j<numDOF;j++)
01955 if (dofInChain[j]) dofVec[j]->addToTrajectory(&dofVals[j],1);
01956 }
01957 delete [] dofVals;
01958 delete [] dofInChain;
01959 }
01960
01961
01972 void
01973 Robot::generateCartesianTrajectory(const transf &startTr, const transf &endTr,
01974 std::vector<transf> &traj,
01975 double startVel, double endVel,
01976 double timeNeeded)
01977 {
01978 int i,j,numSteps;
01979 double t,tpow,dist,angle,coeffs[5];
01980 vec3 newPos,axis;
01981 Quaternion newRot;
01982
01983 (endTr.rotation() * startTr.rotation().inverse()).ToAngleAxis(angle,axis);
01984
01985 if (timeNeeded <= 0.0) {
01986 if (defaultTranslVel == 0.0 || defaultRotVel == 0.0) return;
01987 timeNeeded =
01988 MAX((endTr.translation() - startTr.translation()).len()/defaultTranslVel,
01989 fabs(angle)/defaultRotVel);
01990 }
01991
01992
01993 numSteps = (int)ceil(timeNeeded/myWorld->getTimeStep());
01994 timeNeeded = numSteps*myWorld->getTimeStep();
01995 DBGP("Desired Tran Traj numSteps " << numSteps);
01996
01997 if (numSteps) {
01998 traj.clear();
01999 traj.reserve(numSteps);
02000 }
02001
02002 for (i=0;i<numSteps;i++) {
02003 t = (double)i/(double)(numSteps-1);
02004
02005 coeffs[4] = 6.0 - 3.0*(startVel+endVel)*timeNeeded;
02006 coeffs[3] = -15.0 + (8.0*startVel + 7.0*endVel)*timeNeeded;
02007 coeffs[2] = 10.0 - (6.0*startVel + 4.0*endVel)*timeNeeded;
02008 coeffs[1] = 0.0;
02009 coeffs[0] = startVel*timeNeeded;
02010
02011 dist = 0.0;
02012 tpow = 1.0;
02013 for (j=0;j<5;j++) {
02014 tpow *= t;
02015 dist += tpow*coeffs[j];
02016 }
02017 newRot = Quaternion::Slerp(dist,startTr.rotation(),endTr.rotation());
02018 newPos = (1.0-dist)*startTr.translation() + dist*endTr.translation();
02019 traj.push_back(transf(newRot,newPos));
02020 }
02021 }
02022
02029 void
02030 Robot::updateJointValuesFromDynamics()
02031 {
02032 double *jointVals = new double[ getNumJoints() ];
02033
02034 for (int f=0;f<numChains;f++) {
02035 for (int l=0;l<chainVec[f]->getNumLinks();l++) {
02036 if (chainVec[f]->getLink(l)->getDynJoint())
02037 chainVec[f]->getLink(l)->getDynJoint()->updateValues();
02038 }
02039 for (int j=0; j<chainVec[f]->getNumJoints(); j++) {
02040 jointVals[ chainVec[f]->getJoint(j)->getNum() ] = chainVec[f]->getJoint(j)->getDynamicsVal();
02041 }
02042 }
02043
02044 setJointValues(jointVals);
02045
02046
02047
02048
02049
02050 delete [] jointVals;
02051 }
02052
02062 void
02063 Robot::applyJointPassiveInternalWrenches()
02064 {
02065 for (int c=0; c<numChains; c++) {
02066 for (int j=0; j<getChain(c)->getNumJoints(); j++) {
02067 getChain(c)->getJoint(j)->applyPassiveInternalWrenches();
02068 }
02069 }
02070 }
02071
02076 void
02077 Robot::buildDOFLimitConstraints(std::map<Body*,int> &islandIndices, int numBodies,
02078 double* H, double *g, int &hcn)
02079 {
02080 for (int d=0; d<numDOF; d++) {
02081 dofVec[d]->buildDynamicLimitConstraints(islandIndices, numBodies, H, g, hcn);
02082 }
02083 }
02084
02089 void
02090 Robot::buildDOFCouplingConstraints(std::map<Body*,int> &islandIndices, int numBodies,
02091 double* Nu, double *eps, int &ncn)
02092 {
02093 for(int d=0; d<numDOF; d++) {
02094 dofVec[d]->buildDynamicCouplingConstraints(islandIndices, numBodies, Nu, eps, ncn);
02095 }
02096 return;
02097 }
02098
02105 void
02106 Robot::DOFController(double timeStep)
02107 {
02108 DBGP(" in Robot controller");
02109 if (myWorld->getWorldTime() > dofUpdateTime) {
02110 DBGP("Updating setpoints");
02111 for (int d=0;d<numDOF;d++) {
02112 dofVec[d]->updateSetPoint();
02113 }
02114 dofUpdateTime += myWorld->getTimeStep();
02115 }
02116 for (int d=0;d<numDOF;d++) {
02117 dofVec[d]->callController(timeStep);
02118 }
02119 }
02120
02121
02126 bool
02127 Robot::dynamicAutograspComplete()
02128 {
02129 for (int c=0; c<numChains; c++) {
02130 Link *l = chainVec[c]->getLink( chainVec[c]->getNumLinks()-1 );
02131
02132 if (l->getNumContacts()) continue;
02133 int jNum = chainVec[c]->getLastJoint(chainVec[c]->getNumLinks()-1);
02134 Joint *j = chainVec[c]->getJoint(jNum);
02135 double limit;
02136
02137 if (dofVec[j->getDOFNum()]->getDefaultVelocity() > 0) {
02138 if (j->getCouplingRatio() > 0) {
02139 limit = j->getMax();
02140 } else {
02141 limit = j->getMin();
02142 }
02143 } else if (dofVec[j->getDOFNum()]->getDefaultVelocity() < 0) {
02144 if (j->getCouplingRatio() < 0) {
02145 limit = j->getMax();
02146 } else {
02147 limit = j->getMin();
02148 }
02149 } else {
02150 assert(0);
02151 }
02152
02153 if (fabs(j->getDynamicsVal() - limit) < 3.0e-2) continue;
02154
02155 DBGP("Autograsp going on chain " << c << " joint " << jNum << ": val "
02156 << j->getDynamicsVal() << "; limit " << limit);
02157 return false;
02158 }
02159 return true;
02160 }
02161
02166 bool
02167 Robot::contactSlip()
02168 {
02169 double linearThreshold = 100.0;
02170 double angularThreshold = 2.0;
02171 for (int c=0; c<numChains; c++) {
02172 for (int l=0; l<getChain(c)->getNumLinks(); l++) {
02173 Link *link = getChain(c)->getLink(l);
02174 if (!link->getNumContacts()) continue;
02175 const double *v = link->getVelocity();
02176 double magn = 0.0;
02177 for (int i=0; i<3; i++) {
02178 magn += v[i] * v[i];
02179 }
02180 if (magn > linearThreshold * linearThreshold) {
02181 DBGA("Chain " << c << " link " << l << " moving with linear vel. magnitude " << magn);
02182 return true;
02183 }
02184 magn = 0.0;
02185 for (int i=3; i<6; i++) {
02186 magn += v[i] * v[i];
02187 }
02188 if (magn > angularThreshold * angularThreshold) {
02189 DBGA("Chain " << c << " link " << l << " moving with angular vel. magnitude " << magn);
02190 return true;
02191 }
02192 }
02193 }
02194 return false;
02195 }
02196
02198
02200
02202 Hand::Hand(World *w,const char *name) : Robot(w,name)
02203 {
02204 grasp = new Grasp(this);
02205 }
02206
02208 Hand::~Hand()
02209 {
02210 std::cout << "Deleting Hand: " << std::endl;
02211 delete grasp;
02212 }
02213
02217 void
02218 Hand::cloneFrom(Hand *original)
02219 {
02220 Robot::cloneFrom(original);
02221 grasp->setObjectNoUpdate( original->getGrasp()->getObject() );
02222 grasp->setGravity( original->getGrasp()->isGravitySet() );
02223 }
02224
02239 bool
02240 Hand::autoGrasp(bool renderIt, double speedFactor, bool stopAtContact)
02241 {
02242 int i;
02243 double *desiredVals = new double[numDOF];
02244
02245 if (myWorld->dynamicsAreOn()) {
02246 for (i=0;i<numDOF;i++) {
02247 if (speedFactor * dofVec[i]->getDefaultVelocity() > 0)
02248 desiredVals[i] = dofVec[i]->getMax();
02249 else if (speedFactor * dofVec[i]->getDefaultVelocity() < 0)
02250 desiredVals[i] = dofVec[i]->getMin();
02251 else desiredVals[i] = dofVec[i]->getVal();
02252 DBGP("Desired val "<<i<<" "<<desiredVals[i]);
02253
02254 dofVec[i]->setDesiredVelocity(speedFactor * dofVec[i]->getDefaultVelocity());
02255 }
02256 setDesiredDOFVals(desiredVals);
02257 delete [] desiredVals;
02258 return true;
02259 }
02260
02261 double *stepSize= new double[numDOF];
02262 for (i=0;i<numDOF;i++) {
02263 if (speedFactor * dofVec[i]->getDefaultVelocity() >= 0) desiredVals[i] = dofVec[i]->getMax();
02264 else desiredVals[i] = dofVec[i]->getMin();
02265 stepSize[i] = dofVec[i]->getDefaultVelocity()*speedFactor*AUTO_GRASP_TIME_STEP;
02266 }
02267
02268 bool moved = moveDOFToContacts(desiredVals, stepSize, stopAtContact, renderIt);
02269 delete [] desiredVals;
02270 delete [] stepSize;
02271 return moved;
02272 }
02273
02274
02275
02276
02277
02278
02279
02280 bool
02281 Hand::quickOpen(double speedFactor)
02282 {
02283 double *desiredVals = new double[numDOF];
02284 getDOFVals(desiredVals);
02285 double *desiredSteps = new double[numDOF];
02286 for (int i=0; i<numDOF; i++) {
02287 double d = -1 * dofVec[i]->getDefaultVelocity();
02288 if ( d > 0 ) {
02289 desiredSteps[i] = d * speedFactor * (dofVec[i]->getMax() - desiredVals[i]);
02290 } else if ( d < 0 ) {
02291 desiredSteps[i] = d * speedFactor * (desiredVals[i] - dofVec[i]->getMin() );
02292 } else {
02293 desiredSteps[i] = 0;
02294 }
02295 }
02296 bool done = false, success = false;
02297 int loops = 0;
02298 while (!done) {
02299 loops++;
02300
02301 done = true;
02302 for (int i=0; i<numDOF; i++) {
02303 desiredVals[i] += desiredSteps[i];
02304
02305 if ( desiredVals[i] > dofVec[i]->getMax() ) {desiredVals[i] = dofVec[i]->getMax();}
02306 else if ( desiredVals[i] < dofVec[i]->getMin() ){ desiredVals[i] = dofVec[i]->getMin();}
02307 else if (desiredSteps[i] != 0) {done = false;}
02308
02309 }
02310 forceDOFVals(desiredVals);
02311 if ( myWorld->noCollision() ) {
02312 done = true;
02313 success = true;
02314 }
02315 }
02316 if (loops > 20) DBGA("Open finger loops: " << loops << " Hand: " << myName.latin1());
02317 delete [] desiredVals;
02318 delete [] desiredSteps;
02319 return success;
02320 }
02321
02327 bool
02328 Hand::approachToContact(double moveDist, bool oneStep)
02329 {
02330 transf newTran = translate_transf(vec3(0,0,moveDist) * getApproachTran()) * getTran();
02331 bool result;
02332 if (oneStep) {
02333 result = moveTo(newTran, WorldElement::ONE_STEP, WorldElement::ONE_STEP);
02334 } else {
02335 result = moveTo(newTran, 50*Contact::THRESHOLD, M_PI/36.0);
02336 }
02337 if (result) {
02338 DBGP("Approach no contact");
02339 return false;
02340 } else {
02341 DBGP("Approach results in contact");
02342 return true;
02343 }
02344 }
02345
02351 bool
02352 Hand::findInitialContact(double moveDist)
02353 {
02354 CollisionReport colReport;
02355 while (myWorld->getCollisionReport(&colReport)) {
02356 transf newTran = translate_transf(vec3(0,0,-moveDist / 2.0) *
02357 getApproachTran()) * getTran();
02358 setTran(newTran);
02359 }
02360 return approachToContact(moveDist, false);
02361 }
02362
02363 Matrix
02364 Robot::getJacobianJointToDOF(int chainNum){
02365 Matrix m = Matrix(chainVec[chainNum]->getNumJoints(), numDOF);
02366
02367 m.setAllElements(0.0);
02368 for(int i = 0; i < m.rows(); ++i){
02369
02370 m.elem(i,chainVec[chainNum]->getJoint(i)->getDOFNum()) = chainVec[chainNum]->getJoint(i)->getCouplingRatio();
02371 }
02372 return m;
02373 }