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
00030
00031 #include <stdio.h>
00032 #include <stdlib.h>
00033 #include <math.h>
00034 #include <iostream>
00035 #include <exception>
00036 #include <typeinfo>
00037
00038 #include <QString>
00039 #include <q3listbox.h>
00040
00041
00042 #include "grasp.h"
00043 #include "world.h"
00044 #include "robot.h"
00045 #include "joint.h"
00046 #include "body.h"
00047 #include "contact.h"
00048 #include "gws.h"
00049 #include "quality.h"
00050 #include "gwsprojection.h"
00051 #include "matrix.h"
00052 #include "matvec3D.h"
00053
00054 #ifdef MKL
00055 #include "mkl_wrappers.h"
00056 #else
00057 #include "lapack_wrappers.h"
00058 #endif
00059
00060 #include <Inventor/Qt/SoQtComponent.h>
00061
00062 #ifdef USE_DMALLOC
00063 #include "dmalloc.h"
00064 #endif
00065
00066
00067 #include "debug.h"
00068
00069 #define G_ 9.81
00070
00074 const std::vector<int> Grasp::ALL_DIMENSIONS = std::vector<int>(6, 1);
00075
00076 const int Grasp::CONTACT_FORCE_EXISTENCE = 0;
00077 const int Grasp::CONTACT_FORCE_OPTIMIZATION = 1;
00078 const int Grasp::GRASP_FORCE_EXISTENCE = 2;
00079 const int Grasp::GRASP_FORCE_OPTIMIZATION = 3;
00080
00081
00086 Grasp::Grasp(Hand *h)
00087 {
00088 int i;
00089
00090 hand = h;
00091 object = NULL;
00092 numContacts=0;
00093 valid=true;
00094 useGravity = false;
00095
00096 for (i=0;i<6;i++) minWrench[i]=0.0;
00097
00098 numQM = 0;
00099 }
00100
00106 Grasp::~Grasp()
00107 {
00108 int i;
00109 std::list<GWSprojection *>::iterator gpp;
00110 std::list<GWS *>::iterator gp;
00111
00112 std::cout << "Deleting grasp" <<std::endl;
00113
00114 for (i=0;i<numQM;i++) removeQM(0);
00115 for (gpp=projectionList.begin();gpp!=projectionList.end();gpp++)
00116 delete *gpp;
00117 for (gp=gwsList.begin();gp!=gwsList.end();gp++)
00118 delete *gp;
00119 }
00120
00125 GWS *
00126 Grasp::getGWS(const char *type)
00127 {
00128 GWS *gws = NULL;
00129 std::list<GWS *>::iterator gp;
00130 for (gp=gwsList.begin();gp!=gwsList.end();gp++) {
00131 if (!strcmp((*gp)->getType(),type)) {
00132 gws = *gp;
00133 }
00134 }
00135 if (gws) gws->ref();
00136 return gws;
00137 }
00138
00145 GWS *
00146 Grasp::addGWS(const char *type)
00147 {
00148 GWS *gws = NULL;
00149 std::list<GWS *>::iterator gp;
00150
00151
00152 for (gp=gwsList.begin();gp!=gwsList.end();gp++)
00153 if (!strcmp((*gp)->getType(),type))
00154 gws = *gp;
00155
00156 if (!gws) {
00157 gws = GWS::createInstance(type,this);
00158
00159 gwsList.push_back(gws);
00160 printf("created new %s GWS.\n",type);
00161 }
00162
00163 gws->ref();
00164
00165 return gws;
00166 }
00167
00172 void
00173 Grasp::removeGWS(GWS *gws)
00174 {
00175 DBGP("removing gws");
00176 gws->unref();
00177 if (gws->getRefCount() == 0) {
00178 DBGP("deleting gws");
00179 gwsList.remove(gws);
00180 delete gws;
00181 } else {
00182 DBGP("gws refcount: "<<gws->getRefCount());
00183 }
00184 }
00185
00189 void
00190 Grasp::addQM(QualityMeasure *qm)
00191 {
00192 qmList.push_back(qm);
00193 numQM++;
00194 }
00195
00201 void
00202 Grasp::replaceQM(int which,QualityMeasure *qm)
00203 {
00204 int i;
00205 std::list<QualityMeasure *>::iterator qp;
00206
00207 for (qp=qmList.begin(),i=0; qp!=qmList.end() && i!=which; qp++,i++);
00208 qmList.insert(qp,qm);
00209
00210 if (qp!=qmList.end()) {
00211 delete *qp;
00212 qmList.erase(qp);
00213 }
00214 }
00215
00220 QualityMeasure *
00221 Grasp::getQM(int which)
00222 {
00223 int i;
00224 std::list<QualityMeasure *>::iterator qp;
00225
00226 for (qp=qmList.begin(),i=0; qp!=qmList.end() && i!=which; qp++,i++);
00227 if (qp!=qmList.end()) return *qp;
00228 return NULL;
00229 }
00230
00235 void
00236 Grasp::removeQM(int which)
00237 {
00238 int i;
00239 std::list<QualityMeasure *>::iterator qp;
00240
00241 for (qp=qmList.begin(),i=0; qp!=qmList.end() && i!=which; qp++,i++);
00242 if (qp!=qmList.end()) {
00243 printf("Removing QM\n");
00244 delete *qp;
00245 qmList.erase(qp);
00246 numQM--;
00247 }
00248 }
00249
00253 void
00254 Grasp::addProjection(GWSprojection *gp)
00255 {
00256 projectionList.push_back(gp);
00257 update();
00258 }
00259
00263 void
00264 Grasp::removeProjection(GWSprojection *gp)
00265 {
00266 projectionList.remove(gp);
00267 delete gp;
00268 }
00269
00274 void
00275 Grasp::destroyProjection(void * user, SoQtComponent *)
00276 {
00277 GWSprojection *gp = (GWSprojection *)user;
00278 gp->getGWS()->getGrasp()->removeProjection(gp);
00279 }
00280
00306 void
00307 Grasp::update(std::vector<int> useDimensions)
00308 {
00309 if (hand) {
00310 std::vector<Robot*> robotVec;
00311 hand->getAllAttachedRobots(robotVec);
00312 for (std::vector<Robot*>::iterator it=robotVec.begin(); it!=robotVec.end(); it++) {
00313 (*it)->resetContactsChanged();
00314 }
00315 if (object) {
00316 collectContacts();
00317 } else {
00318 collectVirtualContacts();
00319 }
00320 } else if (object) {
00321
00322 collectVirtualContactsOnObject();
00323 }
00324
00325 DBGP("numContacts: " << numContacts);
00326 updateWrenchSpaces(useDimensions);
00327 }
00328
00332 void
00333 Grasp::updateWrenchSpaces(std::vector<int> useDimensions)
00334 {
00335 std::list<GWS *>::iterator gp;
00336 std::list<GWSprojection *>::iterator pp;
00337
00338
00339 vec3 gravDirection(0,0,1);
00340
00341
00342 gravDirection = 0.5 * gravDirection;
00343
00344
00345 if (useGravity && object) {
00346 gravDirection = gravDirection * object->getTran().inverse();
00347 }
00348
00349
00350 for (gp=gwsList.begin();gp!=gwsList.end();gp++) {
00351 if (useGravity && object) {
00352 (*gp)->setGravity(true, gravDirection);
00353 } else {
00354 (*gp)->setGravity(false);
00355 }
00356 (*gp)->build(useDimensions);
00357 }
00358
00359
00360 for (pp=projectionList.begin();pp!=projectionList.end();pp++) {
00361 (*pp)->update();
00362 }
00363
00364 }
00365
00376 void
00377 Grasp::collectContacts()
00378 {
00379 contactVec.clear();
00380
00381 std::vector<Robot*> robotVec;
00382 hand->getAllAttachedRobots(robotVec);
00383 for (std::vector<Robot*>::iterator it=robotVec.begin(); it!=robotVec.end(); it++) {
00384 std::list<Contact*> contacts = (*it)->getContacts(object);
00385 contactVec.insert(contactVec.end(), contacts.begin(), contacts.end());
00386 }
00387
00388 for (std::vector<Contact *>::iterator cp=contactVec.begin(); cp!=contactVec.end(); cp++) {
00389 (*cp)->getMate()->computeWrenches();
00390 }
00391 numContacts = (int)contactVec.size();
00392 DBGP("Contacts: " << numContacts);
00393 }
00394
00395 vec3 Grasp::virtualCentroid()
00396 {
00397 vec3 cog(0,0,0);
00398 position pos;
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 position topCorner(-1.0e5, -1.0e5, -1.0e5), bottomCorner(1.0e5, 1.0e5, 1.0e5);
00412 for (int i=0; i<(int)contactVec.size(); i++) {
00413 pos = ((VirtualContact*)contactVec[i])->getWorldLocation();
00414 if ( pos.x() > topCorner.x() ) topCorner.x() = pos.x();
00415 if ( pos.y() > topCorner.y() ) topCorner.y() = pos.y();
00416 if ( pos.z() > topCorner.z() ) topCorner.z() = pos.z();
00417 if ( pos.x() < bottomCorner.x() ) bottomCorner.x() = pos.x();
00418 if ( pos.y() < bottomCorner.y() ) bottomCorner.y() = pos.y();
00419 if ( pos.z() < bottomCorner.z() ) bottomCorner.z() = pos.z();
00420 }
00421 cog = 0.5 * (topCorner - bottomCorner);
00422 cog = vec3(bottomCorner.toSbVec3f()) + cog;
00423
00424 return cog;
00425 }
00426
00430 void
00431 Grasp::setVirtualCentroid()
00432 {
00433 vec3 cog = virtualCentroid();
00434 position pos;
00435
00436
00437 vec3 radius;
00438 double maxRadius = 0;
00439 for (int i=0; i<(int)contactVec.size(); i++) {
00440 pos = ((VirtualContact*)contactVec[i])->getWorldLocation();
00441 radius = vec3( pos.toSbVec3f() ) - cog;
00442 if ( radius.len() > maxRadius) maxRadius = radius.len();
00443 }
00444
00445
00446 maxRadius = 150;
00447
00448
00449
00450 for (int i=0; i<(int)contactVec.size(); i++) {
00451 ((VirtualContact*)contactVec[i])->setCenter( position(cog.toSbVec3f()) );
00452 ((VirtualContact*)contactVec[i])->setRadius(maxRadius);
00453
00454 }
00455 }
00456
00461 void
00462 Grasp::setRealCentroid(GraspableBody *body)
00463 {
00464 position cog = body->getCoG() * body->getTran();
00465 double maxRadius = body->getMaxRadius();
00466 for (int i=0; i<(int)contactVec.size(); i++) {
00467 ((VirtualContact*)contactVec[i])->setCenter(cog);
00468 ((VirtualContact*)contactVec[i])->setRadius(maxRadius);
00469 }
00470 }
00471
00480 void
00481 Grasp::collectVirtualContacts()
00482 {
00483 int f,l;
00484 std::list<Contact *>::iterator cp;
00485 std::list<Contact *> contactList;
00486
00487 contactVec.clear();
00488 numContacts = 0;
00489
00490 contactList = hand->getPalm()->getVirtualContacts();
00491 for (cp=contactList.begin();cp!=contactList.end();cp++) {
00492 contactVec.push_back(*cp);
00493 numContacts++;
00494 }
00495
00496 for(f=0;f<hand->getNumFingers();f++) {
00497 for (l=0;l<hand->getFinger(f)->getNumLinks();l++) {
00498 contactList = hand->getFinger(f)->getLink(l)->getVirtualContacts();
00499 for (cp=contactList.begin();cp!=contactList.end();cp++){
00500 contactVec.push_back(*cp);
00501 numContacts++;
00502 }
00503 }
00504 }
00505
00506 if (object == NULL) {
00507 setVirtualCentroid();
00508 for (int i=0; i<(int)contactVec.size(); i++) {
00509 ((VirtualContact*)contactVec[i])->computeWrenches(false);
00510 }
00511 } else {
00512 setRealCentroid(object);
00513
00514
00515
00516
00517
00518 }
00519 }
00520
00526 void
00527 Grasp::collectVirtualContactsOnObject()
00528 {
00529 std::list<Contact *>::iterator cp;
00530 std::list<Contact *> contactList;
00531
00532 contactVec.clear();
00533 numContacts = 0;
00534 contactList = object->getVirtualContacts();
00535 for (cp=contactList.begin();cp!=contactList.end();cp++){
00536 contactVec.push_back(*cp);
00537 numContacts++;
00538 }
00539 for (int i=0; i<(int)contactVec.size(); i++) {
00540
00541 ((Contact*)contactVec[i])->computeWrenches();
00542 }
00543 #ifdef GRASPITDBG
00544 fprintf(stderr,"ContactOnObject has been pushed, number is %d\n",numContacts);
00545 #endif
00546 setRealCentroid(object);
00547 }
00548
00549 double
00550 Grasp::getMaxRadius()
00551 {
00552 if (object) return object->getMaxRadius();
00553 if (numContacts == 0) return 0;
00554 return ((VirtualContact*)contactVec[0])->getMaxRadius();
00555 }
00556
00557 position
00558 Grasp::getCoG()
00559 {
00560 if (object) return object->getCoG();
00561 if (numContacts == 0) return position(0,0,0);
00562 return ((VirtualContact*)contactVec[0])->getCenter();
00563 }
00564
00572 double *
00573 Grasp::getLinkJacobian(int f, int l)
00574 {
00575 int j,col;
00576 Joint *jointPtr;
00577 int numDOF = hand->getNumDOF();
00578 double *jac = new double[6*numDOF];
00579 double k;
00580 mat3 m;
00581 vec3 p;
00582 transf T;
00583 double db0 = 0.0;
00584
00585 dcopy(6*numDOF,&db0,0,jac,1);
00586
00587
00588 if (f < 0) return jac;
00589
00590 for (j=hand->getFinger(f)->getLastJoint(l);j>=0;j--) {
00591 jointPtr = hand->getFinger(f)->getJoint(j);
00592 col = jointPtr->getDOFNum();
00593
00594 k = hand->getDOF(jointPtr->getDOFNum())->getStaticRatio(jointPtr);
00595 T = T * jointPtr->getDH()->getTran();
00596 m = T.affine();
00597 p = T.translation();
00598
00599 if (jointPtr->getType() == REVOLUTE) {
00600 jac[col*6] += k*(-m.element(0,0)*p.y() + m.element(0,1)*p.x());
00601 jac[col*6+1] += k*(-m.element(1,0)*p.y() + m.element(1,1)*p.x());
00602 jac[col*6+2] += k*(-m.element(2,0)*p.y() + m.element(2,1)*p.x());
00603 jac[col*6+3] += k*m.element(0,2);
00604 jac[col*6+4] += k*m.element(1,2);
00605 jac[col*6+5] += k*m.element(2,2);
00606 } else {
00607 jac[col*6] += k*m.element(0,2);
00608 jac[col*6+1] += k*m.element(1,2);
00609 jac[col*6+2] += k*m.element(2,2);
00610 jac[col*6+3] += 0.0;
00611 jac[col*6+4] += 0.0;
00612 jac[col*6+5] += 0.0;
00613 }
00614 }
00615 return jac;
00616 }
00617
00635 Matrix
00636 Grasp::contactJacobian(const std::list<Joint*> &joints,
00637 const std::list< std::pair<transf, Link*> > &contact_locations)
00638 {
00639
00640
00641 std::vector< std::vector<transf> > jointTransf(hand->getNumChains());
00642 for (int c=0; c<hand->getNumChains(); c++) {
00643 jointTransf[c].resize(hand->getChain(c)->getNumJoints(), transf::IDENTITY);
00644 hand->getChain(c)->getJointLocations(NULL, jointTransf[c]);
00645 }
00646
00647 Matrix J( Matrix::ZEROES<Matrix>(int(contact_locations.size()) * 6, (int)joints.size()) );
00648 std::list<Joint*>::const_iterator joint_it;
00649 int joint_count = 0;
00650 int numRows = 0;
00651 for (joint_it=joints.begin(); joint_it!=joints.end(); joint_it++) {
00652 std::list< std::pair<transf, Link*> >::const_iterator contact_it;
00653 numRows = 0;
00654 for(contact_it=contact_locations.begin(); contact_it!=contact_locations.end(); contact_it++, numRows+=6) {
00655 Link *link = contact_it->second;
00656
00657 if ( (*joint_it)->getChainNum() != link->getChainNum() ) {
00658 continue;
00659 }
00660 KinematicChain *chain = hand->getChain( link->getChainNum() );
00661
00662 int last_joint = chain->getLastJoint( link->getLinkNum() );
00663
00664
00665 int jointNumInChain = (*joint_it)->getNum() - chain->getFirstJointNum();
00666 assert(jointNumInChain >= 0);
00667 if ( jointNumInChain > last_joint) continue;
00668
00669 transf joint_tran = jointTransf.at(link->getChainNum()).at(jointNumInChain);
00670 transf contact_tran = contact_it->first * link->getTran();
00671
00672 Matrix indJ(Joint::jacobian(*joint_it, joint_tran, contact_tran, false));
00673
00674 J.copySubMatrix(numRows, joint_count, indJ);
00675 }
00676 joint_count++;
00677 }
00678 return J;
00679 }
00680
00683 Matrix
00684 Grasp::contactJacobian(const std::list<Joint*> &joints,
00685 const std::list<Contact*> &contacts)
00686 {
00687 std::list< std::pair<transf, Link*> > contact_locations;
00688 std::list<Contact*>::const_iterator contact_it;
00689 for(contact_it=contacts.begin(); contact_it!=contacts.end(); contact_it++) {
00690 if ((*contact_it)->getBody1()->getOwner() != hand) {
00691 DBGA("Grasp jacobian: contact not on hand");
00692 continue;
00693 }
00694 Link *link = static_cast<Link*>((*contact_it)->getBody1());
00695 contact_locations.push_back( std::pair<transf, Link*>((*contact_it)->getContactFrame(), link) );
00696 }
00697 return contactJacobian(joints, contact_locations);
00698 }
00699
00702 Matrix
00703 Grasp::contactJacobian(const std::list<Joint*> &joints,
00704 const std::list<VirtualContact*> &contacts)
00705 {
00706 std::list< std::pair<transf, Link*> > contact_locations;
00707 std::list<VirtualContact*>::const_iterator contact_it;
00708 for(contact_it=contacts.begin(); contact_it!=contacts.end(); contact_it++) {
00709 if ((*contact_it)->getBody1()->getOwner() != hand) {
00710 DBGA("Grasp jacobian: contact not on hand");
00711 continue;
00712 }
00713 Link *link = static_cast<Link*>((*contact_it)->getBody1());
00714 contact_locations.push_back( std::pair<transf, Link*>((*contact_it)->getContactFrame(), link) );
00715 }
00716 return contactJacobian(joints, contact_locations);
00717 }
00718
00729 Matrix
00730 Grasp::graspMapMatrix(const Matrix &R, const Matrix &D)
00731 {
00732 int numContacts = R.rows() / 6;
00733 assert(6 * numContacts == R.rows());
00734
00735 Matrix S(6, 6*numContacts);
00736 for(int i=0; i<numContacts; i++) {
00737 S.copySubMatrix(0, 6*i, Matrix::EYE(6,6));
00738 }
00739
00740 Matrix SR(S.rows(), R.cols());
00741 matrixMultiply(S, R, SR);
00742 Matrix G(S.rows(), D.cols());
00743 matrixMultiply(SR, D, G);
00744 return G;
00745 }
00746
00747
00762 int
00763 Grasp::computeQuasistaticForces(const Matrix &robotTau)
00764 {
00765
00766
00767
00768 for (int c=0; c<hand->getNumChains(); c++) {
00769 if ( hand->getChain(c)->getNumContacts(NULL) !=
00770 hand->getChain(c)->getNumContacts(object) ) {
00771 DBGA("Hand contacts not on object");
00772 return 1;
00773 }
00774 }
00775
00776 std::list<Contact*> contacts;
00777 std::list<Joint*> joints;
00778
00779 bool freeChainForces = false;
00780 for(int c=0; c<hand->getNumChains(); c++) {
00781
00782 std::list<Contact*> chainContacts = hand->getChain(c)->getContacts(object);
00783 contacts.insert(contacts.end(), chainContacts.begin(), chainContacts.end());
00784 if (!chainContacts.empty()) {
00785 std::list<Joint*> chainJoints = hand->getChain(c)->getJoints();
00786 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
00787 } else {
00788
00789
00790 Matrix chainTau = hand->getChain(c)->jointTorquesVector(robotTau);
00791
00792 if (chainTau.absMax() > 1.0e3) {
00793 DBGA("Joint torque " << chainTau.absMax() << " on chain " << c
00794 << " with no contacts");
00795 freeChainForces = true;
00796 }
00797 }
00798 }
00799
00800 if (contacts.empty()) return 0;
00801
00802
00803 Matrix tau((int)joints.size(), 1);
00804 int jc; std::list<Joint*>::iterator jit;
00805 for (jc=0, jit = joints.begin(); jit!=joints.end(); jc++,jit++) {
00806 tau.elem(jc,0) = robotTau.elem( (*jit)->getNum(), 0 );
00807 }
00808
00809
00810
00811
00812 if (tau.absMax() < 1.0e-3) {
00813 return 0;
00814 }
00815
00816
00817 if (freeChainForces) {
00818 return 1;
00819 }
00820
00821 Matrix J(contactJacobian(joints, contacts));
00822 Matrix D(Contact::frictionForceBlockMatrix(contacts));
00823 Matrix F(Contact::frictionConstraintsBlockMatrix(contacts));
00824 Matrix R(Contact::localToWorldWrenchBlockMatrix(contacts));
00825
00826
00827 Matrix G(graspMapMatrix(R, D));
00828
00829
00830 Matrix JTran(J.transposed());
00831 Matrix JTD(JTran.rows(), D.cols());
00832 matrixMultiply(JTran, D, JTD);
00833
00834
00835 Matrix zeroes(Matrix::ZEROES<Matrix>(F.rows(), 1));
00836
00837
00838 Matrix c_beta(D.cols(), 1);
00839
00840
00841 Matrix lowerBounds(Matrix::ZEROES<Matrix>(D.cols(),1));
00842 Matrix upperBounds(Matrix::MAX_VECTOR(D.cols()));
00843
00844
00845 double objVal;
00846 int result = factorizedQPSolver(G, JTD, tau, F, zeroes, lowerBounds, upperBounds,
00847 c_beta, &objVal);
00848 if (result) {
00849 if( result > 0) {
00850 DBGP("Grasp: problem unfeasible");
00851 } else {
00852 DBGA("Grasp: QP solver error");
00853 }
00854 return result;
00855 }
00856
00857
00858 Matrix cWrenches(D.rows(), 1);
00859 matrixMultiply(D, c_beta, cWrenches);
00860 DBGP("Contact wrenches:\n" << cWrenches);
00861
00862
00863 Matrix objectWrenches(R.rows(), cWrenches.cols());
00864 matrixMultiply(R, cWrenches, objectWrenches);
00865 DBGP("Object wrenches:\n" << objectWrenches);
00866
00867
00868 displayContactWrenches(&contacts, cWrenches);
00869 accumulateAndDisplayObjectWrenches(&contacts, objectWrenches);
00870
00871
00872 Matrix fCheck(tau.rows(), 1);
00873 matrixMultiply(JTran, cWrenches, fCheck);
00874 for (int j=0; j<tau.rows(); j++) {
00875
00876 double err = fabs(tau.elem(j, 0) - fCheck.elem(j,0));
00877
00878 if ( fabs(tau.elem(j,0)) > 1.0e-2) {
00879 err = err / fabs(tau.elem(j, 0));
00880 } else {
00881
00882
00883 if (err < 1.0e2) err = 0;
00884 }
00885
00886 if ( err > 1.0e-1) {
00887 DBGA("Desired torque not obtained on joint " << j << ", error " << err <<
00888 " out of " << fabs(tau.elem(j, 0)) );
00889 return -1;
00890 }
00891 }
00892
00893
00894
00895 double* extWrench = object->getExtWrenchAcc();
00896 vec3 force(extWrench[0], extWrench[1], extWrench[2]);
00897 vec3 torque(extWrench[3], extWrench[4], extWrench[5]);
00898
00899 double wrenchError = objVal*1.0e-6 - (force.len_sq() + torque.len_sq()) * 1.0e6;
00900
00901 if (wrenchError > 1.0e3) {
00902 DBGA("Wrench sanity check error: " << wrenchError);
00903 return -1;
00904 }
00905 return 0;
00906 }
00907
00914 int
00915 graspForceExistence(Matrix &JTD, Matrix &D, Matrix &F, Matrix &G,
00916 Matrix &beta, Matrix &tau, double *objVal)
00917 {
00918
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930 int numJoints = tau.rows();
00931 Matrix beta_tau(beta.rows() + tau.rows(), 1);
00932
00933
00934 Matrix right_hand( JTD.rows() + 1, 1);
00935 right_hand.setAllElements(0.0);
00936
00937
00938 right_hand.elem( right_hand.rows()-1, 0) = 1.0e10;
00939
00940
00941 Matrix LeftHand( JTD.rows() + 1, D.cols() + numJoints);
00942 LeftHand.setAllElements(0.0);
00943 LeftHand.copySubMatrix(0, 0, JTD);
00944 LeftHand.copySubMatrix(0, D.cols(), Matrix::NEGEYE(numJoints, numJoints) );
00945 for (int i=0; i<numJoints; i++) {
00946 LeftHand.elem( JTD.rows(), D.cols() + i) = 1.0;
00947 }
00948
00949
00950
00951 Matrix FO(F.rows(), F.cols() + numJoints);
00952 FO.setAllElements(0.0);
00953 FO.copySubMatrix(0, 0, F);
00954
00955
00956 Matrix inEqZeroes(FO.rows(), 1);
00957 inEqZeroes.setAllElements(0.0);
00958
00959
00960 Matrix GO(Matrix::ZEROES<Matrix>(G.rows(), G.cols() + numJoints));
00961 GO.copySubMatrix(0, 0, G);
00962
00963
00964
00965 Matrix lowerBounds(Matrix::MIN_VECTOR(beta_tau.rows()));
00966 lowerBounds.copySubMatrix( 0, 0, Matrix::ZEROES<Matrix>(beta.rows(), 1) );
00967 Matrix upperBounds(Matrix::MAX_VECTOR(beta_tau.rows()));
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988 int result = factorizedQPSolver(GO, LeftHand, right_hand, FO, inEqZeroes,
00989 lowerBounds, upperBounds,
00990 beta_tau, objVal);
00991 beta.copySubBlock(0, 0, beta.rows(), 1, beta_tau, 0, 0);
00992 tau.copySubBlock(0, 0, tau.rows(), 1, beta_tau, beta.rows(), 0);
00993 return result;
00994 }
00995
01002 int
01003 contactForceExistence(Matrix &F, Matrix &N, Matrix &Q, Matrix &beta, double *objVal)
01004 {
01005
01006
01007
01008
01009
01010
01011
01012
01013 Matrix right_hand(1,1);
01014
01015 right_hand.elem(0,0) = 1.0e7;
01016
01017
01018 Matrix inEqZeroes(F.rows(), 1);
01019 inEqZeroes.setAllElements(0.0);
01020
01021
01022 Matrix lowerBounds(Matrix::ZEROES<Matrix>(beta.rows(),1));
01023 Matrix upperBounds(Matrix::MAX_VECTOR(beta.rows()));
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037 int result = factorizedQPSolver(Q, N, right_hand, F, inEqZeroes,
01038 lowerBounds, upperBounds,
01039 beta, objVal);
01040 return result;
01041 }
01042
01051 int
01052 contactForceOptimization(Matrix &F, Matrix &N, Matrix &Q, Matrix &beta, double *objVal)
01053 {
01054
01055
01056
01057
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 Matrix right_hand(Matrix::ZEROES<Matrix>(Q.rows()+1, 1));
01068
01069 right_hand.elem(Q.rows(),0) = 1.0e7;
01070
01071
01072 Matrix LeftHand(Q.rows() + 1, Q.cols());
01073 LeftHand.copySubMatrix(0, 0, Q);
01074 LeftHand.copySubMatrix(Q.rows(), 0, N);
01075
01076
01077 Matrix lowerBounds(Matrix::ZEROES<Matrix>(beta.rows(),1));
01078 Matrix upperBounds(Matrix::MAX_VECTOR(beta.rows()));
01079
01080
01081 Matrix FSum(1,F.rows());
01082 FSum.setAllElements(1.0);
01083 Matrix FObj(1,F.cols());
01084 matrixMultiply(FSum, F, FObj);
01085
01086
01087
01088
01089
01090
01091
01092
01093
01094
01095
01096
01097 int result = LPSolver(FObj, LeftHand, right_hand, F, Matrix::ZEROES<Matrix>(F.rows(), 1),
01098 lowerBounds, upperBounds,
01099 beta, objVal);
01100 return result;
01101 }
01102
01111 int
01112 graspForceOptimization(Matrix &JTD, Matrix &D, Matrix &F, Matrix &G,
01113 Matrix &beta, Matrix &tau, double *objVal)
01114 {
01115
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125
01126
01127
01128
01129 Matrix beta_tau(beta.rows() + tau.rows(), 1);
01130 int numJoints = tau.rows();
01131
01132
01133 Matrix right_hand( JTD.rows() + G.rows() + 1, 1);
01134 right_hand.setAllElements(0.0);
01135
01136
01137 right_hand.elem( right_hand.rows()-1, 0) = 1.0e10;
01138
01139
01140 Matrix LeftHand( JTD.rows() + G.rows() + 1, D.cols() + numJoints);
01141 LeftHand.setAllElements(0.0);
01142 LeftHand.copySubMatrix(0, 0, JTD);
01143 LeftHand.copySubMatrix(0, D.cols(), Matrix::NEGEYE(numJoints, numJoints) );
01144 LeftHand.copySubMatrix(JTD.rows(), 0, G);
01145 for (int i=0; i<numJoints; i++) {
01146 LeftHand.elem( JTD.rows() + G.rows(), D.cols() + i) = 1.0;
01147 }
01148
01149
01150
01151
01152 Matrix FO(F.rows(), F.cols() + numJoints);
01153 FO.setAllElements(0.0);
01154 FO.copySubMatrix(0, 0, F);
01155
01156 Matrix FSum(1, F.rows());
01157 FSum.setAllElements(1.0);
01158 Matrix FObj(1, FO.cols());
01159 matrixMultiply(FSum, FO, FObj);
01160
01161
01162 Matrix lowerBounds(Matrix::ZEROES<Matrix>(beta_tau.rows(),1));
01163 Matrix upperBounds(Matrix::MAX_VECTOR(beta_tau.rows()));
01164
01165
01166 Matrix inEqZeroes(FO.rows(), 1);
01167 inEqZeroes.setAllElements(0.0);
01168
01169
01170 FILE *fp = fopen("gfo.txt","w");
01171 fprintf(fp,"left hand:\n");
01172 LeftHand.print(fp);
01173 fprintf(fp,"right hand:\n");
01174 right_hand.print(fp);
01175 fprintf(fp,"friction inequality:\n");
01176 FO.print(fp);
01177 fprintf(fp,"Objective:\n");
01178 FObj.print(fp);
01179 fclose(fp);
01180
01181
01182
01183
01184
01185
01186
01187 int result = LPSolver(FObj, LeftHand, right_hand, FO, inEqZeroes,
01188 lowerBounds, upperBounds,
01189 beta_tau, objVal);
01190 beta.copySubBlock(0, 0, beta.rows(), 1, beta_tau, 0, 0);
01191 tau.copySubBlock(0, 0, tau.rows(), 1, beta_tau, beta.rows(), 0);
01192 return result;
01193 }
01194
01201 std::list<Joint*> Grasp::getJointsOnContactChains()
01202 {
01203 std::list<Joint*> joints;
01204 for (int c=0; c<hand->getNumChains(); c++) {
01205 if (hand->getChain(c)->getNumContacts(object) != 0) {
01206 std::list<Joint*> chainJoints = hand->getChain(c)->getJoints();
01207 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
01208 }
01209 }
01210 return joints;
01211 }
01212
01239 int
01240 Grasp::computeQuasistaticForcesAndTorques(Matrix *robotTau, int computation)
01241 {
01242
01243
01244 std::list<Contact*> contacts;
01245 contacts.insert(contacts.begin(),contactVec.begin(), contactVec.end());
01246
01247 if (contacts.empty()) return 0;
01248
01249
01250 std::list<Joint*> joints = getJointsOnContactChains();
01251
01252
01253
01254 Matrix J(contactJacobian(joints, contacts));
01255 Matrix D(Contact::frictionForceBlockMatrix(contacts));
01256 Matrix F(Contact::frictionConstraintsBlockMatrix(contacts));
01257 Matrix R(Contact::localToWorldWrenchBlockMatrix(contacts));
01258
01259 Matrix N(Contact::normalForceSumMatrix(contacts));
01260
01261
01262 Matrix G(graspMapMatrix(R,D));
01263
01264
01265 Matrix JTran(J.transposed());
01266 Matrix JTD(JTran.rows(), D.cols());
01267 matrixMultiply(JTran, D, JTD);
01268
01269
01270 Matrix beta( D.cols(), 1);
01271 Matrix tau( (int)joints.size(), 1);
01272
01273 double objVal;
01274
01275
01276
01277
01278
01279 int result;
01280 switch(computation)
01281 {
01282 case GRASP_FORCE_EXISTENCE:
01283 result = graspForceExistence(JTD, D, F, G, beta, tau, &objVal);
01284 break;
01285 case GRASP_FORCE_OPTIMIZATION:
01286 result = graspForceOptimization(JTD, D, F, G, beta, tau, &objVal);
01287 break;
01288 case CONTACT_FORCE_EXISTENCE:
01289 result = contactForceExistence(F, N, G, beta, &objVal);
01290 matrixMultiply(JTD, beta, tau);
01291 break;
01292 case CONTACT_FORCE_OPTIMIZATION:
01293 result = contactForceOptimization(F, N, G, beta, &objVal);
01294 matrixMultiply(JTD, beta, tau);
01295 break;
01296 default:
01297 DBGA("Unknown computation type requested");
01298 return -1;
01299 }
01300
01301 if (result) {
01302 if( result > 0) {
01303 DBGA("Grasp: problem unfeasible");
01304 } else {
01305 DBGA("Grasp: solver error");
01306 }
01307 return result;
01308 }
01309 DBGA("Optimization solved; objective: " << objVal);
01310
01311 DBGP("beta:\n" << beta);
01312 DBGP("tau:\n" << tau);
01313 DBGP("Joint forces sum: " << tau.elementSum());
01314
01315 Matrix Gbeta(G.rows(), beta.cols());
01316 matrixMultiply(G, beta, Gbeta);
01317 DBGP("Total object wrench:\n" << Gbeta);
01318
01319
01320 Matrix cWrenches(D.rows(), 1);
01321 matrixMultiply(D, beta, cWrenches);
01322 DBGP("Contact forces:\n " << cWrenches);
01323
01324
01325 Matrix objectWrenches(R.rows(), cWrenches.cols());
01326 matrixMultiply(R, cWrenches, objectWrenches);
01327 DBGP("Object wrenches:\n" << objectWrenches);
01328
01329
01330 displayContactWrenches(&contacts, cWrenches);
01331 accumulateAndDisplayObjectWrenches(&contacts, objectWrenches);
01332
01333
01334 std::list<Joint*>::iterator it;
01335 int jc;
01336 for(it=joints.begin(), jc=0; it!=joints.end(); it++,jc++) {
01337 robotTau->elem( (*it)->getNum(), 0 ) = 1.0 * tau.elem(jc,0);
01338 }
01339
01340
01341
01342
01343
01344 return 0;
01345 }
01346
01352 void
01353 Grasp::displayContactWrenches(std::list<Contact*> *contacts,
01354 const Matrix &contactWrenches)
01355 {
01356 int count = 0;
01357 std::list<Contact*>::iterator it;
01358 for (it=contacts->begin(); it!=contacts->end(); it++, count++) {
01359 Contact *contact = *it;
01360 if (contact->getBody2()->isDynamic()) {
01361
01362
01363
01364 double dynWrench[6];
01365 for (int i=0; i<6; i++) {
01366 dynWrench[i] = -1.0 * 1.0e-6 * contactWrenches.elem(6*count+i,0);
01367 }
01368
01369 dynWrench[1] = -1.0 * dynWrench[1];
01370 dynWrench[4] = -1.0 * dynWrench[4];
01371 contact->getMate()->setDynamicContactWrench(dynWrench);
01372 }
01373 }
01374 }
01375
01376
01385 void
01386 Grasp::accumulateAndDisplayObjectWrenches(std::list<Contact*> *contacts,
01387 const Matrix &objectWrenches)
01388 {
01389 int count = 0;
01390 std::list<Contact*>::iterator it;
01391 for (it=contacts->begin(); it!=contacts->end(); it++, count++) {
01392 Contact *contact = *it;
01393 vec3 force(objectWrenches.elem(6*count+0,0),
01394 objectWrenches.elem(6*count+1,0),
01395 objectWrenches.elem(6*count+2,0));
01396 vec3 torque(objectWrenches.elem(6*count+3,0),
01397 objectWrenches.elem(6*count+4,0),
01398 objectWrenches.elem(6*count+5,0));
01399 if (contact->getBody2()->isDynamic()) {
01400 DynamicBody *object = (DynamicBody*)(contact->getBody2());
01401
01402
01403 force = 1.0e-6 * force * object->getTran().inverse();
01404
01405 torque = 1.0e-6 * torque * object->getTran().inverse();
01406
01407 object->addForce(force);
01408 object->addTorque(torque);
01409 }
01410 }
01411 }