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 "mcGrip.h"
00027
00028 #include <limits>
00029
00030 #include "matrix.h"
00031 #include "debug.h"
00032
00039 McGrip::McGrip(World *w,const char *name) : HumanHand(w,name)
00040 {
00041 mLinkLength = 20;
00042 mJointRadius = 5;
00043
00044 delete grasp;
00045 grasp = new McGripGrasp(this);
00046 }
00047
00051 int
00052 McGrip::loadFromXml(const TiXmlElement* root,QString rootPath)
00053 {
00054 int result = HumanHand::loadFromXml(root, rootPath);
00055 for (size_t i=0; i<(int)mTendonVec.size(); i++) {
00056 mTendonVec[i]->setApplyPassiveForce(false);
00057 }
00058 return result;
00059 }
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073 void
00074 McGrip::assembleTorqueMatrices(int refJointNum, int thisJointNum, int nextJointNum,
00075 double tx, double ty,
00076 double theta, double theta_n,
00077 Matrix &B, Matrix &a)
00078 {
00079 DBGP("\nRef: " << refJointNum << " Proximal: "
00080 << thisJointNum << " Distal: " << nextJointNum);
00081
00082 if (thisJointNum == refJointNum) {
00083 DBGP(">>> - cos(theta/2) = " << - cos(theta/2.0));
00084 }
00085
00086
00087 Matrix t(2,1);
00088 t.elem(0,0) = tx; t.elem(1,0) = ty;
00089
00090
00091
00092 Matrix Rtheta(Matrix::ROTATION2D(-theta));
00093
00094
00095
00096
00097 Matrix m1(1,2);
00098
00099
00100 if (nextJointNum >= 0) {
00101 m1.elem(0,0) = cos(theta) - cos(theta/2.0);
00102 m1.elem(0,1) = -sin(theta) + sin(theta/2.0);
00103 } else {
00104 m1.elem(0,0) = -cos(theta/2.0);
00105 m1.elem(0,1) = sin(theta/2.0);
00106 }
00107
00108 Matrix free_term(1,1);
00109 matrixMultiply(m1, t, free_term);
00110
00111 Matrix b_terms(1,2);
00112 matrixMultiply(m1, Rtheta, b_terms);
00113
00114 B.elem(refJointNum, thisJointNum) += b_terms.elem(0,0);
00115 DBGP("Proximal effect: " << b_terms.elem(0,0));
00116 B.elem(refJointNum, 6) += b_terms.elem(0,1);
00117 a.elem(refJointNum, 0) += free_term.elem(0,0);
00118
00119
00120 if (nextJointNum >= 0) {
00121 m1.elem(0,0) = cos(theta + theta_n/2.0) - cos(theta);
00122 m1.elem(0,1) = -sin(theta + theta_n/2.0) + sin(theta);
00123
00124 Matrix S(Matrix::ZEROES<Matrix>(2,3));
00125 S.elem(0,0) = S.elem(1,1) = S.elem(1,2) = 1.0;
00126
00127 matrixMultiply(m1, t, free_term);
00128
00129 matrixMultiply(m1, Rtheta, b_terms);
00130 Matrix b_terms_ext(1,3);
00131 matrixMultiply(b_terms, S, b_terms_ext);
00132
00133 B.elem(refJointNum, nextJointNum) += b_terms_ext.elem(0,0);
00134 DBGP("Distal effect: " << b_terms_ext.elem(0,0));
00135 B.elem(refJointNum, 6) += b_terms_ext.elem(0,1);
00136 B.elem(refJointNum, 7) += b_terms_ext.elem(0,2);
00137 a.elem(refJointNum, 0) += free_term.elem(0,0);
00138 }
00139
00140
00141 if (nextJointNum >= 0) {
00142 DBGP("Proximal -1.0 and distal +1.0");
00143 B.elem(refJointNum, thisJointNum) += -1.0;
00144 B.elem(refJointNum, nextJointNum) += 1.0;
00145 }
00146 }
00147
00169 void
00170 McGrip::getRoutingMatrices(Matrix **B, Matrix **a)
00171 {
00172 *B = new Matrix(Matrix::ZEROES<Matrix>(6,8));
00173 *a = new Matrix(Matrix::ZEROES<Matrix>(6,1));
00174
00175
00176
00177 std::vector< std::vector<transf> > jointTransf(getNumChains());
00178 for (int c=0; c<getNumChains(); c++) {
00179 jointTransf[c].resize(getChain(c)->getNumJoints(), transf::IDENTITY);
00180 getChain(c)->getJointLocations(NULL, jointTransf[c]);
00181 }
00182
00183 assert(numChains==2);
00184 for(int c=0; c<2; c++) {
00185 assert (getChain(c)->getNumJoints()==3);
00186 for (int j=0; j<3; j++) {
00187 int refJointNum = c*3 + j;
00188 transf refTran = jointTransf.at(c).at(j);
00189 for (int k=j; k<3; k++) {
00190 int thisJointNum = c*3 + k;
00191 int nextJointNum = -1;
00192 if (k!=2) {
00193 nextJointNum = c*3 + k + 1;
00194 }
00195
00196 transf thisTran = jointTransf.at(c).at(k);
00197
00198 transf relTran = refTran * thisTran.inverse();
00199 vec3 translation = relTran.translation();
00200
00201 if (translation.z() > 1.0e-3) {
00202 DBGA("Z translation in McGrip routing matrix");
00203 }
00204 double tx, ty;
00205
00206
00207 tx = translation.y();
00208 ty = translation.x();
00209
00210
00211 DBGP("Joint translation: " << tx << " " << ty);
00212
00213
00214 double theta = getChain(c)->getJoint(k)->getVal() +
00215 getChain(c)->getJoint(k)->getOffset();
00216 double theta_n = 0.0;
00217 if (k!=2) {
00218 theta_n = getChain(c)->getJoint(k+1)->getVal() +
00219 getChain(c)->getJoint(k+1)->getOffset();
00220 }
00221
00222
00223
00224 assembleTorqueMatrices(refJointNum, thisJointNum, nextJointNum,
00225 -tx, -ty,
00226 theta, theta_n,
00227 **B, **a);
00228 }
00229 }
00230 }
00231
00232
00233 (*B)->multiply(-1.0);
00234 (*a)->multiply(-1.0);
00235 DBGP("B matrix:\n" << **B);
00236 DBGP("a vector:\n" << **a);
00237 }
00238
00239 int
00240 McGrip::jointTorqueEquilibrium()
00241 {
00242 Matrix *a, *B;
00243 getRoutingMatrices(&B, &a);
00244 Matrix p(8, 1);
00245
00246 p.elem(0,0) = 5;
00247 p.elem(1,0) = 5;
00248 p.elem(2,0) = 1.65;
00249
00250 p.elem(3,0) = 5;
00251 p.elem(4,0) = 5;
00252 p.elem(5,0) = 1.65;
00253
00254
00255 p.elem(6,0) = getJointRadius();
00256 p.elem(7,0) = getLinkLength();
00257
00258
00259 Matrix tau(6, 1);
00260 matrixMultiply(*B, p, tau);
00261 matrixAdd(tau, *a, tau);
00262
00263
00264 assert(mTendonVec.size()==2);
00265 assert(mTendonVec[0]->getName()=="Finger 0");
00266 assert(mTendonVec[1]->getName()=="Finger 1");
00267 double f = mTendonVec[0]->getActiveForce();
00268 for (int j=0; j<3; j++) {
00269 tau.elem(j,0) *= f;
00270 }
00271 f = mTendonVec[1]->getActiveForce();
00272 for (int j=0; j<3; j++) {
00273 tau.elem(3+j,0) *= f;
00274 }
00275
00276 DBGA("Recovered joint forces:\n" << tau);
00277
00278
00279 assert(numChains==2);
00280 Matrix k(6, 1);
00281 for(int c=0; c<2; c++) {
00282 assert (getChain(c)->getNumJoints()==3);
00283 for(int j=0; j<3; j++) {
00284 k.elem(3*c+j,0) = getChain(c)->getJoint(j)->getSpringForce();
00285 }
00286 }
00287 DBGA("Recovered spring forces:\n" << k);
00288
00289
00290 Matrix delta(6,1);
00291 k.multiply(-1.0);
00292 matrixAdd(tau, k, delta);
00293 f = delta.fnorm();
00294 int result;
00295 if ( f >= 1.0e3) {
00296 DBGA("McGrip joint equilibrium failed; error norm: " << f);
00297 result = 1;
00298 } else {
00299 DBGA("McGrip joint equilibrium success");
00300 result = 0;
00301 }
00302
00303 return result;
00304 }
00305
00306 void
00307 McGrip::getJointDisplacementMatrix(Matrix **J)
00308 {
00309 *J = new Matrix(Matrix::ZEROES<Matrix>(6,6));
00310 assert(numChains==2);
00311 for(int c=0; c<2; c++) {
00312 assert (getChain(c)->getNumJoints()==3);
00313 for(int j=0; j<3; j++) {
00314 (*J)->elem(3*c+j, 3*c+j) = getChain(c)->getJoint(j)->getDisplacement();
00315 }
00316 }
00317 }
00318
00319 int
00320 McGripGrasp::computeQuasistaticForces(double tendonForce)
00321 {
00322
00323 Matrix *B, *a;
00324 static_cast<McGrip*>(hand)->getRoutingMatrices(&B, &a);
00325
00326
00327 Matrix p(8, 1);
00328
00329 p.elem(0,0) = 5;
00330 p.elem(1,0) = 5;
00331 p.elem(2,0) = 1.65;
00332
00333 p.elem(3,0) = 5;
00334 p.elem(4,0) = 5;
00335 p.elem(5,0) = 1.65;
00336
00337
00338 p.elem(6,0) = static_cast<McGrip*>(hand)->getJointRadius();
00339 p.elem(7,0) = static_cast<McGrip*>(hand)->getLinkLength();
00340
00341
00342 Matrix tau(6, 1);
00343 matrixMultiply(*B, p, tau);
00344 matrixAdd(tau, *a, tau);
00345 delete a;
00346 delete B;
00347
00348
00349 tau.multiply(tendonForce);
00350
00351
00352 return Grasp::computeQuasistaticForces(tau);
00353 }
00354
00408 int
00409 McGripGrasp::tendonAndHandOptimization(Matrix *parameters, double &objValRet)
00410 {
00411
00412
00413 std::list<Contact*> contacts;
00414 contacts.insert(contacts.begin(),contactVec.begin(), contactVec.end());
00415
00416 if (contacts.empty()) return 0;
00417
00418
00419
00420
00421
00422
00423 std::list<Joint*> joints;
00424 for (int c=0; c<hand->getNumChains(); c++) {
00425 std::list<Joint*> chainJoints = hand->getChain(c)->getJoints();
00426 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
00427 }
00428
00429
00430
00431 Matrix J(contactJacobian(joints, contacts));
00432 Matrix D(Contact::frictionForceBlockMatrix(contacts));
00433 Matrix F(Contact::frictionConstraintsBlockMatrix(contacts));
00434 Matrix R(Contact::localToWorldWrenchBlockMatrix(contacts));
00435
00436 Matrix G(graspMapMatrix(R,D));
00437
00438 Matrix JTran(J.transposed());
00439 Matrix JTD(JTran.rows(), D.cols());
00440 matrixMultiply(JTran, D, JTD);
00441
00442
00443 Matrix *a, *negB;
00444 static_cast<McGrip*>(hand)->getRoutingMatrices(&negB, &a);
00445 negB->multiply(-1.0);
00446 assert(JTD.rows() == negB->rows());
00447 assert(JTD.rows() == a->rows());
00448
00449 double tendonForce = 1.0e6;
00450 negB->multiply(tendonForce);
00451 a->multiply(tendonForce);
00452
00453
00454 int numParameters = negB->cols();
00455
00456
00457
00458 Matrix p(JTD.cols() + negB->cols() + a->rows(), 1);
00459
00460
00461 Matrix Q( JTD.rows(), p.rows() );
00462 Q.copySubMatrix( 0, 0, JTD );
00463 Q.copySubMatrix( 0, JTD.cols(), *negB );
00464 Q.copySubMatrix( 0, JTD.cols() + negB->cols(), Matrix::NEGEYE(a->rows(), a->rows()) );
00465
00466
00467 Matrix FO( Matrix::ZEROES<Matrix>(F.rows(), p.rows()) );
00468 FO.copySubMatrix(0, 0, F);
00469
00470
00471 Matrix EqLeft( Matrix::ZEROES<Matrix>(G.rows(), p.rows()) );
00472 EqLeft.copySubMatrix(0, 0, G);
00473
00474 Matrix eqRight( Matrix::ZEROES<Matrix>(G.rows(), 1) );
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490 Matrix lowerBounds( Matrix::MIN_VECTOR(p.rows()) );
00491 Matrix upperBounds( Matrix::MAX_VECTOR(p.rows()) );
00492
00493 for (int i=0; i<JTD.cols(); i++) {
00494 lowerBounds.elem(i,0) = 0.0;
00495 }
00496
00497 for (int i=0; i<6; i++) {
00498 lowerBounds.elem( JTD.cols() + i, 0) = -5.0;
00499 upperBounds.elem( JTD.cols() + i, 0) = 5.0;
00500 }
00501
00502
00503
00504
00505 lowerBounds.elem(JTD.cols() + 0,0) = 5;
00506 lowerBounds.elem(JTD.cols() + 1,0) = 5;
00507 lowerBounds.elem(JTD.cols() + 2,0) = 1.65;
00508 upperBounds.elem(JTD.cols() + 0,0) = 5;
00509 upperBounds.elem(JTD.cols() + 1,0) = 5;
00510 upperBounds.elem(JTD.cols() + 2,0) = 1.65;
00511
00512 lowerBounds.elem(JTD.cols() + 3,0) = 5;
00513 lowerBounds.elem(JTD.cols() + 4,0) = 5;
00514 lowerBounds.elem(JTD.cols() + 5,0) = 1.65;
00515 upperBounds.elem(JTD.cols() + 3,0) = 5;
00516 upperBounds.elem(JTD.cols() + 4,0) = 5;
00517 upperBounds.elem(JTD.cols() + 5,0) = 1.65;
00518
00519
00520 lowerBounds.elem(JTD.cols() + 6, 0) = static_cast<McGrip*>(hand)->getJointRadius();
00521 upperBounds.elem(JTD.cols() + 6, 0) = static_cast<McGrip*>(hand)->getJointRadius();
00522 lowerBounds.elem(JTD.cols() + 7, 0) = static_cast<McGrip*>(hand)->getLinkLength();
00523 upperBounds.elem(JTD.cols() + 7, 0) = static_cast<McGrip*>(hand)->getLinkLength();
00524
00525 for (int i=0; i<a->rows(); i++) {
00526 lowerBounds.elem(JTD.cols() + 8 + i, 0) = a->elem(i,0);
00527 upperBounds.elem(JTD.cols() + 8 + i, 0) = a->elem(i,0);
00528 }
00529
00530
00531 delete negB;
00532 delete a;
00533
00534
00535 double objVal;
00536 int result = factorizedQPSolver(Q,
00537 EqLeft, eqRight,
00538 FO, Matrix::ZEROES<Matrix>(FO.rows(), 1),
00539 lowerBounds, upperBounds,
00540 p, &objVal);
00541 objValRet = objVal;
00542
00543 if (result) {
00544 if( result > 0) {
00545 DBGA("McGrip constr optimization: problem unfeasible");
00546 } else {
00547 DBGA("McGrip constr optimization: QP solver error");
00548 }
00549 return result;
00550 }
00551 DBGA("Construction optimization objective: " << objVal);
00552 DBGP("Result:\n" << p);
00553
00554
00555 Matrix beta(JTD.cols(), 1);
00556 beta.copySubBlock(0, 0, JTD.cols(), 1, p, 0, 0);
00557
00558 beta.multiply(1.0e7);
00559 parameters->copySubBlock(0, 0, numParameters, 1, p, JTD.cols(), 0);
00560
00561
00562 Matrix cWrenches(D.rows(), 1);
00563 matrixMultiply(D, beta, cWrenches);
00564 DBGP("Contact forces:\n " << cWrenches);
00565
00566
00567 Matrix objectWrenches(R.rows(), cWrenches.cols());
00568 matrixMultiply(R, cWrenches, objectWrenches);
00569 DBGP("Object wrenches:\n" << objectWrenches);
00570
00571
00572 displayContactWrenches(&contacts, cWrenches);
00573 accumulateAndDisplayObjectWrenches(&contacts, objectWrenches);
00574
00575
00576
00577
00578 if (objVal > 1.0e6) {
00579 return 1;
00580 }
00581 return 0;
00582 }