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 #include "searchEnergy.h"
00027
00028 #include <time.h>
00029
00030 #include "robot.h"
00031 #include "barrett.h"
00032 #include "body.h"
00033 #include "grasp.h"
00034 #include "contact.h"
00035 #include "world.h"
00036 #include "quality.h"
00037 #include "searchState.h"
00038 #include "graspitGUI.h"
00039 #include "ivmgr.h"
00040 #include "matrix.h"
00041
00042
00043 #include "debug.h"
00044
00045
00046 #include "profiling.h"
00047
00048 PROF_DECLARE(QS);
00049
00050
00051 const double unbalancedForceThreshold = 1.0e10;
00052
00053 SearchEnergy::SearchEnergy()
00054 {
00055 mHand = NULL;
00056 mObject = NULL;
00057 mType = ENERGY_CONTACT;
00058 mContactType = CONTACT_LIVE;
00059 mVolQual = NULL;
00060 mEpsQual = NULL;
00061 mDisableRendering = true;
00062 mOut = NULL;
00063 }
00064
00065 void
00066 SearchEnergy::createQualityMeasures()
00067 {
00068 if (mVolQual) delete mVolQual;
00069 if (mEpsQual) delete mEpsQual;
00070 mVolQual = new QualVolume( mHand->getGrasp(), QString("SimAnn_qvol"),"L1 Norm");
00071 mEpsQual = new QualEpsilon( mHand->getGrasp(), QString("SimAnn_qeps"), "L1 Norm");
00072 DBGP("Qual measures created");
00073 }
00074
00075 void
00076 SearchEnergy::setHandAndObject(Hand *h, Body *o)
00077 {
00078 if (mHand != h) {
00079 mHand = h;
00080 createQualityMeasures();
00081 }
00082 mObject = o;
00083 }
00084
00085 SearchEnergy::~SearchEnergy()
00086 {
00087 delete mVolQual;
00088 delete mEpsQual;
00089 }
00090
00091 bool
00092 SearchEnergy::legal() const
00093 {
00094
00095
00096 if (mType == ENERGY_COMPLIANT || mType == ENERGY_DYNAMIC) return true;
00097
00098
00099
00100
00101
00102
00103
00104 return mHand->getWorld()->noCollision(mHand);
00105
00106
00107
00108
00109
00110
00111 }
00112
00113 void
00114 SearchEnergy::analyzeCurrentPosture(Hand *h, Body *o, bool &isLegal, double &stateEnergy, bool noChange)
00115 {
00116 setHandAndObject(h,o);
00117
00118 if (noChange) {
00119 h->saveState();
00120 }
00121
00122 if ( !legal() ) {
00123 isLegal = false;
00124 stateEnergy = 0;
00125 } else {
00126 isLegal = true;
00127 stateEnergy = energy();
00128 }
00129
00130 if (noChange) {
00131 h->restoreState();
00132 }
00133 }
00134
00135 void SearchEnergy::analyzeState(bool &isLegal, double &stateEnergy, const GraspPlanningState *state, bool noChange)
00136 {
00137 Hand *h = state->getHand();
00138 setHandAndObject( h, state->getObject() );
00139 h->saveState();
00140 transf objTran = state->getObject()->getTran();
00141
00142 bool render = h->getRenderGeometry();
00143 if( mDisableRendering) {
00144 h->setRenderGeometry(false);
00145 }
00146
00147 if ( !state->execute() || !legal() ) {
00148 isLegal = false;
00149 stateEnergy = 0;
00150 } else {
00151 isLegal = true;
00152 stateEnergy = energy();
00153 }
00154
00155 if (noChange || !isLegal) {
00156 h->restoreState();
00157 state->getObject()->setTran(objTran);
00158 }
00159
00160 if (render && mDisableRendering) h->setRenderGeometry(true);
00161 return;
00162 }
00163
00164
00165 double SearchEnergy::energy() const
00166 {
00167
00168
00169
00170
00171 if (mContactType == CONTACT_LIVE && mType != ENERGY_AUTOGRASP_QUALITY && mType != ENERGY_STRICT_AUTOGRASP) {
00172 mHand->getWorld()->findVirtualContacts(mHand, mObject);
00173 DBGP("Live contacts computation");
00174 }
00175
00176 double e;
00177 switch (mType) {
00178 case ENERGY_CONTACT:
00179 mHand->getGrasp()->collectVirtualContacts();
00180 e = contactEnergy();
00181 break;
00182 case ENERGY_POTENTIAL_QUALITY:
00183 mHand->getGrasp()->collectVirtualContacts();
00184 e = potentialQualityEnergy();
00185 break;
00186 case ENERGY_AUTOGRASP_QUALITY:
00187
00188 e = autograspQualityEnergy();
00189 break;
00190 case ENERGY_CONTACT_QUALITY:
00191 mHand->getGrasp()->collectVirtualContacts();
00192 e = guidedPotentialQualityEnergy();
00193 break;
00194 case ENERGY_GUIDED_AUTOGRASP:
00195
00196 e = guidedAutograspEnergy();
00197 break;
00198 case ENERGY_STRICT_AUTOGRASP:
00199
00200 e = strictAutograspEnergy();
00201 break;
00202 case ENERGY_COMPLIANT:
00203 e = compliantEnergy();
00204 break;
00205 case ENERGY_DYNAMIC:
00206 e = dynamicAutograspEnergy();
00207 break;
00208 default:
00209 fprintf(stderr,"Wrong type of energy requested!\n");
00210 e = 0;
00211 }
00212 return e;
00213 }
00214
00215 double
00216 SearchEnergy::contactEnergy() const
00217 {
00218
00219
00220 VirtualContact *contact;
00221 vec3 p,n,cn;
00222 double totalError = 0;
00223 for (int i=0; i<mHand->getGrasp()->getNumContacts(); i++) {
00224 contact = (VirtualContact*)mHand->getGrasp()->getContact(i);
00225 contact->getObjectDistanceAndNormal(mObject, &p, NULL);
00226
00227 double dist = p.len();
00228
00229
00230
00231
00232 totalError += fabs(dist);
00233
00234
00235
00236
00237
00238 cn = contact->getWorldNormal();
00239 n = normalise(p);
00240 double d = 1 - cn % n;
00241 totalError += d * 100.0 / 2.0;
00242 }
00243
00244 totalError /= mHand->getGrasp()->getNumContacts();
00245
00246
00247 return totalError;
00248 }
00249
00254 double
00255 SearchEnergy::guidedAutograspEnergy() const
00256 {
00257
00258 VirtualContact *contact;
00259 vec3 p,n,cn;
00260 double virtualError = 0; int closeContacts=0;
00261
00262
00263 mHand->getGrasp()->collectVirtualContacts();
00264 for (int i=0; i<mHand->getGrasp()->getNumContacts(); i++) {
00265
00266 contact = (VirtualContact*)mHand->getGrasp()->getContact(i);
00267 contact->getObjectDistanceAndNormal(mObject, &p, &n);
00268
00269 double dist = p.len();
00270 if ( (-1.0 * p) % n < 0) dist = -dist;
00271
00272
00273 virtualError += fabs(dist);
00274 cn = -1.0 * contact->getWorldNormal();
00275 double d = 1 - cn % n;
00276 virtualError += d * 100.0 / 2.0;
00277
00278 if ( fabs(dist)<20 && d < 0.3 ) closeContacts++;
00279 }
00280
00281 virtualError /= mHand->getGrasp()->getNumContacts();
00282
00283
00284 double volQuality = 0, epsQuality = 0;
00285 if (closeContacts >= 2) {
00286 mHand->autoGrasp(false, 1.0);
00287
00288 mHand->getGrasp()->collectContacts();
00289 if (mHand->getGrasp()->getNumContacts() >= 4) {
00290 mHand->getGrasp()->updateWrenchSpaces();
00291 volQuality = mVolQual->evaluate();
00292 epsQuality = mEpsQual->evaluate();
00293 if (epsQuality < 0) epsQuality = 0;
00294 }
00295
00296 DBGP("Virtual error " << virtualError << " and " << closeContacts << " close contacts.");
00297 DBGP("Volume quality: " << volQuality << " Epsilon quality: " << epsQuality);
00298 }
00299
00300
00301 double q;
00302 if ( volQuality == 0) q = virtualError;
00303 else q = virtualError - volQuality * 1.0e3;
00304 if (volQuality || epsQuality) {DBGP("Final quality: " << q);}
00305
00306
00307 return q;
00308 }
00309
00314 double
00315 SearchEnergy::guidedPotentialQualityEnergy() const
00316 {
00317 double cEn = contactEnergy();
00318 double pEn = potentialQualityEnergy(false);
00319
00320 if (pEn > 0.0) return cEn;
00321 return pEn;
00322 }
00323
00324 double
00325 SearchEnergy::potentialQualityEnergy(bool verbose) const
00326 {
00327 VirtualContact *contact;
00328 vec3 p,n,cn;
00329
00330 int count = 0;
00331
00332 for (int i=0; i<mHand->getGrasp()->getNumContacts(); i++) {
00333
00334 contact = (VirtualContact*)mHand->getGrasp()->getContact(i);
00335 contact->computeWrenches(true, false);
00336
00337 contact->getObjectDistanceAndNormal(mObject, &p, NULL);
00338 n= contact->getWorldNormal();
00339
00340 double dist = p.len();
00341 p = normalise(p);
00342 double cosTheta = n % p;
00343
00344 double factor = potentialQualityScalingFunction(dist, cosTheta);
00345
00346 if (verbose) {
00347 fprintf(stderr,"VC %d on finger %d link %d\n",i,contact->getFingerNum(), contact->getLinkNum());
00348 fprintf(stderr,"Distance %f cosTheta %f\n",dist,cosTheta);
00349 fprintf(stderr,"Scaling factor %f\n\n",factor);
00350 }
00351 contact->scaleWrenches( factor );
00352 if (factor > 0.25) {
00353 count++;
00354 contact->mark(true);
00355 } else contact->mark(false);
00356 }
00357
00358 double gq = -1 ,gv = -1;
00359
00360
00361 std::vector<int> forceDimensions(6,0);
00362 forceDimensions[0] = forceDimensions[1] = forceDimensions[2] = 1;
00363 if (count >= 3) {
00364 mHand->getGrasp()->updateWrenchSpaces(forceDimensions);
00365 gq = mEpsQual->evaluate();
00366 gv = mVolQual->evaluate();
00367 }
00368 if (verbose) {
00369 fprintf(stderr,"Quality: %f\n\n",gq);
00370 }
00371 if (count) {
00372 DBGP("Count: " << count << "; Gq: " << gq << "; Gv: " << gv);
00373 }
00374 return -gq;
00375 }
00376
00379 double
00380 SearchEnergy::autograspQualityEnergy() const
00381 {
00382 DBGP("Autograsp quality computation");
00383 mHand->autoGrasp(false, 1.0);
00384 mHand->getGrasp()->collectContacts();
00385 mHand->getGrasp()->updateWrenchSpaces();
00386 double volQual = mVolQual->evaluate();
00387 double epsQual = mEpsQual->evaluate();
00388 if (epsQual < 0) epsQual = 0;
00389 DBGP("Autograsp quality: " << volQual << " volume and " << epsQual << " epsilon.");
00390 return - (30 * volQual) - (100 * epsQual);
00391 }
00392
00396 double
00397 SearchEnergy::approachAutograspQualityEnergy() const
00398 {
00399 transf initialTran = mHand->getTran();
00400 bool contact = mHand->approachToContact(30);
00401 if (contact) {
00402 if ( mHand->getPalm()->getNumContacts() == 0) contact = false;
00403 }
00404 if (!contact) {
00405
00406
00407 DBGP("Approach found no contacts");
00408 mHand->setTran( initialTran );
00409 } else {
00410 DBGP("Approach results in contact");
00411 }
00412 return autograspQualityEnergy();
00413 }
00414
00415 void
00416 SearchEnergy::autoGraspStep(int numCols, bool &stopRequest) const
00417 {
00418
00419 stopRequest = false;
00420 if (!numCols) {
00421 return;
00422 }
00423
00424 mHand->getWorld()->resetDynamicWrenches();
00425
00426 Matrix tau(mHand->staticJointTorques(false));
00427 int result = mHand->getGrasp()->computeQuasistaticForces(tau);
00428 if (result) {
00429 if (result > 0) {
00430 PRINT_STAT(mOut, "Unbalanced");
00431 } else {
00432 PRINT_STAT(mOut, "ERROR");
00433 }
00434 mCompUnbalanced = true;
00435 stopRequest = true;
00436 return;
00437 }
00438 assert(mObject->isDynamic());
00439 double* extWrench = static_cast<DynamicBody*>(mObject)->getExtWrenchAcc();
00440 vec3 force(extWrench[0], extWrench[1], extWrench[2]);
00441 if (force.len() > mMaxUnbalancedForce.len()) {
00442 mMaxUnbalancedForce = force;
00443 }
00444
00445 }
00446
00447 double
00448 SearchEnergy::compliantEnergy() const
00449 {
00450 PROF_RESET(QS);
00451 PROF_TIMER_FUNC(QS);
00452
00453 mHand->findInitialContact(200);
00454
00455 if (!mHand->getNumContacts(mObject)) return 1;
00456
00457
00458 mCompUnbalanced = false;
00459 mMaxUnbalancedForce.set(0.0,0.0,0.0);
00460
00461 QObject::connect(mHand, SIGNAL(moveDOFStepTaken(int, bool&)),
00462 this, SLOT(autoGraspStep(int, bool&)));
00463 mHand->autoGrasp(!mDisableRendering, 1.0, false);
00464 QObject::disconnect(mHand, SIGNAL(moveDOFStepTaken(int, bool&)),
00465 this, SLOT(autoGraspStep(int, bool&)));
00466
00467 if (mCompUnbalanced || mMaxUnbalancedForce.len() > unbalancedForceThreshold) {
00468
00469 }
00470
00471
00472 if (mHand->getNumContacts(mObject) < 2) return 1;
00473
00474 PRINT_STAT(mOut, "unbal: " << mMaxUnbalancedForce);
00475
00476
00477
00478
00479
00480 for (int d=0; d<mHand->getNumDOF(); d++) {
00481 mHand->getDOF(d)->setForce( mHand->getDOF(d)->getMaxForce() );
00482 }
00483 mHand->getWorld()->resetDynamicWrenches();
00484
00485 Matrix tau(mHand->staticJointTorques(true));
00486 int result = mHand->getGrasp()->computeQuasistaticForces(tau);
00487 if (result) {
00488 if (result > 0) {
00489 PRINT_STAT(mOut, "Final_unbalanced");
00490 } else {
00491 PRINT_STAT(mOut, "Final_ERROR");
00492 }
00493 return 1.0;
00494 }
00495 double* extWrench = static_cast<DynamicBody*>(mObject)->getExtWrenchAcc();
00496 vec3 force(extWrench[0], extWrench[1], extWrench[2]);
00497 vec3 torque(extWrench[3], extWrench[4], extWrench[5]);
00498
00499
00500 mHand->getGrasp()->collectContacts();
00501 mHand->getGrasp()->updateWrenchSpaces();
00502 double epsQual = mEpsQual->evaluate();
00503 PRINT_STAT(mOut, "eps: " << epsQual);
00504
00505 if ( epsQual < 0.05) return 1.0;
00506
00507 PROF_PRINT(QS);
00508 PRINT_STAT(mOut, "torque: " << torque << " " << torque.len());
00509 PRINT_STAT(mOut, "force: " << force << " " << force.len());
00510
00511 return -200.0 + force.len();
00512 }
00513 void
00514 SearchEnergy::dynamicsError(const char*) const
00515 {
00516 DBGA("Dynamics error; early exit");
00517 mDynamicsError = true;
00518 }
00519
00520 bool
00521 SearchEnergy::contactSlip() const
00522 {
00523 return mHand->contactSlip();
00524 }
00525
00530 bool SearchEnergy::dynamicAutograspComplete() const
00531 {
00532 return mHand->dynamicAutograspComplete();
00533 }
00534
00535 double
00536 SearchEnergy::dynamicAutograspEnergy() const
00537 {
00538
00539 mHand->findInitialContact(200);
00540
00541 if (!mHand->getNumContacts(mObject)) return 1;
00542
00543
00544
00545
00546 mHand->getWorld()->resetDynamics();
00547
00548 mHand->getWorld()->resetDynamicWrenches();
00549 mHand->getWorld()->turnOnDynamics();
00550
00551
00552 mHand->autoGrasp(false, 0.5);
00553
00554 QObject::connect(mHand->getWorld(), SIGNAL(dynamicsError(const char*)),
00555 this, SLOT(dynamicsError(const char*)));
00556
00557 mDynamicsError = false;
00558 int steps=0; int stepFailsafe = 1500;
00559 int autoGraspDone = 0; int afterSteps = 100;
00560
00561 while (1) {
00562 if (!(steps%100)) {DBGA("Step " << steps);}
00563 mHand->getWorld()->stepDynamics();
00564 if (mDynamicsError) break;
00565
00566 if (!autoGraspDone && dynamicAutograspComplete()) {
00567 autoGraspDone = steps;
00568 }
00569
00570 if (autoGraspDone && steps - autoGraspDone > afterSteps) {
00571 break;
00572 }
00573
00574 if (++steps > stepFailsafe) break;
00575 }
00576
00577 if (mDynamicsError) {
00578 PRINT_STAT(mOut, "Dynamics error");
00579 return 2.0;
00580 } else if (steps > stepFailsafe) {
00581 PRINT_STAT(mOut, "Time failsafe");
00582 return 2.0;
00583 }
00584 PRINT_STAT(mOut, "Autograsp done");
00585
00586
00587 Body *obstacle;
00588 for (int b=0; b<mHand->getWorld()->getNumBodies(); b++) {
00589 Body *bod = mHand->getWorld()->getBody(b);
00590 if (bod->isDynamic()) continue;
00591 if (bod->getOwner() != bod) continue;
00592 obstacle = bod;
00593 break;
00594 }
00595 if (!obstacle) {
00596 PRINT_STAT(mOut, "Obstacle not found!");
00597 return 2.0;
00598 }
00599 mHand->getWorld()->toggleCollisions(false, obstacle);
00600
00601 steps = 0; afterSteps = 400;
00602 while (1) {
00603 if (!(steps%100)) {DBGA("After step " << steps);}
00604 mHand->getWorld()->stepDynamics();
00605
00606
00607
00608
00609
00610 if (mDynamicsError) break;
00611 if (++steps > afterSteps) break;
00612 }
00613 mHand->getWorld()->toggleCollisions(true, obstacle);
00614 QObject::disconnect(mHand->getWorld(), SIGNAL(dynamicsError(const char*)),
00615 this, SLOT(dynamicsError(const char*)));
00616
00617 mHand->getWorld()->turnOffDynamics();
00618
00619 if (mDynamicsError) {
00620 PRINT_STAT(mOut, "Dynamics error");
00621 return 2.0;
00622 }
00623
00624
00625 if (mHand->getNumContacts(mObject) < 2) {
00626 PRINT_STAT(mOut, "Ejected");
00627 return 0.0;
00628 }
00629
00630
00631 mHand->getGrasp()->collectContacts();
00632 mHand->getGrasp()->updateWrenchSpaces();
00633 double epsQual = mEpsQual->evaluate();
00634 PRINT_STAT(mOut, "eps: " << epsQual);
00635
00636 if ( epsQual < 0.05) return -0.5;
00637
00638
00639 PRINT_STAT(mOut, "Success 1");
00640 return -1.0;
00641 }
00642
00646 double
00647 SearchEnergy::strictAutograspEnergy() const
00648 {
00649
00650 double gq = approachAutograspQualityEnergy();
00651 if (gq==0) return 1.0e8;
00652 else return gq;
00653 }
00654
00655
00656 double
00657 SearchEnergy::distanceFunction(double d) const
00658 {
00659 double ERRORWIDTH=25;
00660 if (d > 0) {
00661 return ( 40.0 - 40.0 / pow(4.0,d/ERRORWIDTH) );
00662 } else {
00663 return -d;
00664 }
00665 }
00666
00667 double
00668 SearchEnergy::potentialQualityScalingFunction(double dist, double cosTheta) const
00669 {
00670 double sf = 0;
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 if (cosTheta < 0.7) return 0;
00696 if (dist > 50) return 0;
00697 sf = cos ( 3.14 * dist / 50.0) + 1;
00698 return sf;
00699 }
00700
00701 double SearchEnergy::getEpsQual(){
00702 mHand->getWorld()->findAllContacts();
00703 mHand->getWorld()->updateGrasps();
00704 return mEpsQual->evaluate();
00705 }
00706
00707 double SearchEnergy::getVolQual(){
00708 mHand->getWorld()->findAllContacts();
00709 mHand->getWorld()->updateGrasps();
00710 return mVolQual->evaluate();
00711 }
00712
00713
00714
00715 void
00716 ClosureSearchEnergy::analyzeState(bool &isLegal, double &stateEnergy, const GraspPlanningState *state, bool noChange)
00717 {
00718
00719 if (mAvoidList) {
00720 std::list<GraspPlanningState*>::const_iterator it; int i=0;
00721 for (it = mAvoidList->begin(); it!=mAvoidList->end(); it++){
00722 if ( (*it)->distance(state) < mThreshold ) {
00723 isLegal = false;
00724 stateEnergy = 0.0;
00725 DBGP("State rejected; close to state " << i);
00726 return;
00727 }
00728 i++;
00729 }
00730 }
00731
00732
00733 SearchEnergy::analyzeState(isLegal, stateEnergy, state, noChange);
00734 }