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 #include <stdio.h>
00031 #include <list>
00032 #include <vector>
00033 #include <map>
00034 #include <algorithm>
00035 #ifdef Q_WS_X11
00036 #include <unistd.h>
00037 #endif
00038 #include "mytools.h"
00039 #include "dynamics.h"
00040 #include "dynJoint.h"
00041 #include "body.h"
00042 #include "robot.h"
00043 #include "contact.h"
00044 #include "world.h"
00045 #include "ivmgr.h"
00046
00047 #ifdef MKL
00048 #include "mkl_wrappers.h"
00049 #else
00050 #include "lapack_wrappers.h"
00051 #endif
00052
00053 #include "maxdet.h"
00054
00055 #ifdef USE_DMALLOC
00056 #include "dmalloc.h"
00057 #endif
00058
00059
00060 #include "debug.h"
00061
00062 extern FILE *debugfile;
00063 extern IVmgr *ivmgr;
00064
00065 int myLemke(double *M,int n,double *q,double *z,bool usePrediction,bool ldbg, int &iterations);
00066
00067
00068
00069 void
00070 buildJointConstraints(std::vector<Robot *> &robotVec,
00071 std::vector<int> &islandIndices,int numBodies,
00072 double* Nu,double *eps,double *H,double *g,double h);
00073
00074 void
00075 assembleLCPPrediction(double *lambda, int Arows, int numDOFLimits, std::list<Contact *> *contactList);
00076
00077 void
00078 printLCPBasis(double *lambda, int Arows, int numDOFLimits, int numContacts);
00079
00086 void
00087 fillMatrixBlock(double *B,int ldb,int r1,int c1,int r2,int c2,double *M,
00088 int ldm)
00089 {
00090 for (int i=c1;i<=c2;i++)
00091 for (int j=r1;j<=r2;j++)
00092 M[i*ldm + j] = B[(i-c1)*ldb + j-r1];
00093 }
00094
00101 void buildForceTransform(transf &T,vec3 &p,double *transformMat)
00102 {
00103 static int j,k;
00104 static double R[9];
00105 static double crossMat[9];
00106 static double Rcross[9];
00107 static vec3 radius;
00108
00109 R[0] = T.affine().element(0,0);
00110 R[1] = T.affine().element(0,1);
00111 R[2] = T.affine().element(0,2);
00112
00113 R[3] = T.affine().element(1,0);
00114 R[4] = T.affine().element(1,1);
00115 R[5] = T.affine().element(1,2);
00116
00117 R[6] = T.affine().element(2,0);
00118 R[7] = T.affine().element(2,1);
00119 R[8] = T.affine().element(2,2);
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 for (j=0;j<9;j++)
00135 if (fabs(R[j]) < MACHINE_ZERO) R[j] = 0.0;
00136 else if (R[j] > 1.0 - MACHINE_ZERO) R[j] = 1.0;
00137 else if (R[j] < -1.0 + MACHINE_ZERO) R[j] = -1.0;
00138
00139 radius = T.translation() - p;
00140
00141 crossMat[0]=0.0; crossMat[3]=-radius.z();crossMat[6]=radius.y();
00142 crossMat[1]=radius.z();crossMat[4]=0.0; crossMat[7]=-radius.x();
00143 crossMat[2]=-radius.y();crossMat[5]= radius.x();crossMat[8]=0.0;
00144
00145
00146
00147
00148
00149 dgemm("N","N",3,3,3,1.0,crossMat,3,R,3,0.0,Rcross,3);
00150
00151 fillMatrixBlock(R,3,0,0,2,2,transformMat,6);
00152 for (j=3;j<6;j++)
00153 for (k=0;k<3;k++)
00154 transformMat[6*j+k] = 0.0;
00155 fillMatrixBlock(Rcross,3,3,0,5,2,transformMat,6);
00156 fillMatrixBlock(R,3,3,3,5,5,transformMat,6);
00157 }
00158
00162 int
00163 invertMatrix(int n,double *A,double *INVA)
00164 {
00165 double *work;
00166 int *ipiv;
00167 int lwork = n;
00168 int info;
00169
00170 if (A && INVA) {
00171 work = new double[n];
00172 ipiv = new int[n];
00173 dcopy(n*n,A,1,INVA,1);
00174 dgetrf(n,n,INVA,n,ipiv,&info);
00175 dgetri(n,INVA,n,ipiv,work,lwork,&info);
00176 delete [] work;
00177 delete [] ipiv;
00178 }
00179 else {
00180 printf("One or both matricies in InvertMatrix are NULL\n");
00181 info = -1;
00182 }
00183 return info;
00184 }
00185
00192 int
00193 moveBodies(int numBodies,std::vector<DynamicBody *> bodyVec,double h)
00194 {
00195 static double V[42];
00196 static double tmp12[12];
00197 static double B[12];
00198 static double R_N_B[9];
00199 static double newPos[7];
00200 static mat3 Rot;
00201 int bn;
00202 double currq[7];
00203 double currv[6];
00204 int errCode=SUCCESS;
00205
00206 for (bn=0;bn<numBodies;bn++) {
00207 memcpy(currq,bodyVec[bn]->getPos(),7*sizeof(double));
00208 memcpy(currv,bodyVec[bn]->getVelocity(),6*sizeof(double));;
00209
00210 Quaternion tmpQuat(currq[3],currq[4],currq[5],currq[6]);
00211 tmpQuat.ToRotationMatrix(Rot);
00212
00213
00214
00215
00216
00217 R_N_B[0] = Rot[0]; R_N_B[3] = Rot[1]; R_N_B[6] = Rot[2];
00218 R_N_B[1] = Rot[3]; R_N_B[4] = Rot[4]; R_N_B[7] = Rot[5];
00219 R_N_B[2] = Rot[6]; R_N_B[5] = Rot[7]; R_N_B[8] = Rot[8];
00220
00221
00222
00223 B[0] = -currq[4]; B[4] = -currq[5]; B[8] = -currq[6];
00224 B[1] = currq[3]; B[5] = -currq[6]; B[9] = currq[5];
00225 B[2] = currq[6]; B[6] = currq[3]; B[10]= -currq[4];
00226 B[3] = -currq[5]; B[7] = currq[4]; B[11]= currq[3];
00227 dscal(12,0.5,B,1);
00228
00229
00230
00231
00232
00233
00234
00235
00236 dgemm("N","T",4,3,3,1.0,B,4,R_N_B,3,0.0,tmp12,4);
00237 V[0] = 1.0;
00238 V[8] = 1.0;
00239 V[16]= 1.0;
00240 fillMatrixBlock(tmp12,4,3,3,6,5,V,7);
00241
00242 dcopy(7,currq,1,newPos,1);
00243
00244 dgemv("N",7,6,h,V,7,currv,1,1.0,newPos,1);
00245
00246 #ifdef GRASPITDBG
00247 fprintf(stdout,"object %s new velocity: \n", bodyVec[bn]->getName().latin1());
00248 for (int i=0;i<6;i++) fprintf(stdout,"%le ",currv[i]);
00249 printf("\n");
00250 fprintf(stdout,"object %s new position: \n", bodyVec[bn]->getName().latin1());
00251 disp_mat(stdout,newPos,1,7,0);
00252 #endif
00253
00254
00255 if (!bodyVec[bn]->setPos(newPos)) {
00256 DBGP("requested position is out of bounds for this object!");
00257 errCode = FAILURE;
00258 }
00259 }
00260 return errCode;
00261 }
00262
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296
00297
00298
00299
00300
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319
00320
00321 int
00322 iterateDynamics(std::vector<Robot *> robotVec,
00323 std::vector<DynamicBody *> bodyVec,
00324 DynamicParameters *dp)
00325 {
00326 double h = dp->timeStep;
00327 bool useContactEps = dp->useContactEps;
00328 static double Jcg_tmp[9],Jcg_B[9],Jcg_N[9],Jcg_N_inv[9],R_N_B[9];
00329 static double db0=0.0,tmp3[3];
00330 static mat3 Rot;
00331 static int info;
00332 World *myWorld;
00333 KinematicChain *chain;
00334 int numBodies = bodyVec.size(),errCode = 0;
00335 int numRobots = robotVec.size();
00336 int numJoints=0;
00337 int numDOF=0;
00338 int bn,cn,i,j;
00339 int Mrows,Dcols,Arows,Hrows,Hcols,Nurows,Nucols;
00340 int numDOFLimits=0;
00341
00342 std::list<Contact *> contactList;
00343 std::list<Contact *> objContactList;
00344 std::list<Contact *>::iterator cp;
00345
00346
00347
00348 double *ql = new double[7*numBodies];
00349 double *qnew = new double[7*numBodies];
00350 double *vl = new double[6*numBodies];
00351 double *vlnew = new double[6*numBodies];
00352 double *M = new double[(6*numBodies)*(6*numBodies)];
00353 double *M_i = new double[(6*numBodies)*(6*numBodies)];
00354 double *fext = new double[6*numBodies];
00355
00356
00357 double *A;
00358
00359
00360 double *g,*lambda;
00361 double *predLambda = NULL;
00362
00363
00364 double *H;
00365
00366
00367 double *Nu;
00368
00369
00370 double *k;
00371
00372
00373 double *eps;
00374
00375
00376 double *HtM_i,*v1;
00377
00378
00379 double *v2;
00380
00381
00382 double *NutM_i,*NutM_iNu,*INVNutM_iNu,*INVNutM_iNuNut;
00383 double *INVNutM_iNuNutM_i,*INVNutM_iNuNutM_iH;
00384
00385
00386 double *NutM_ikminuseps,*INVNutM_iNuNutM_ikminuseps;
00387
00388 double *currq,*currM;
00389
00390 Mrows = 6*numBodies;
00391
00392 myWorld = bodyVec[0]->getWorld();
00393
00394 std::map<Body*, int> islandIndices;
00395 for (i=0;i<myWorld->getNumBodies();i++) {
00396 islandIndices.insert( std::pair<Body*, int>(myWorld->getBody(i), -1) );
00397 }
00398 for (i=0;i<numBodies;i++) {
00399 islandIndices[ bodyVec[i] ] = i;
00400 }
00401
00402
00403 int numCouplingConstraints = 0;
00404 for (i=0;i<numRobots;i++) {
00405 numDOF += robotVec[i]->getNumDOF();
00406 for (j=0;j<robotVec[i]->getNumChains();j++) {
00407 chain = robotVec[i]->getChain(j);
00408 numJoints += chain->getNumJoints();
00409 }
00410 for (j=0;j<robotVec[i]->getNumDOF();j++) {
00411 numCouplingConstraints += robotVec[i]->getDOF(j)->getNumCouplingConstraints();
00412 numDOFLimits += robotVec[i]->getDOF(j)->getNumLimitConstraints();
00413 }
00414 }
00415
00416 DBGP("Dynamics time step: " << h);
00417 DBGP("numJoints: " << numJoints);
00418
00419
00420 int numContacts = 0;
00421 int numTotalFrictionEdges = 0;
00422 int numDynJointConstraints=0;
00423 for (bn=0;bn<numBodies;bn++) {
00424
00425 if (bodyVec[bn]->getDynJoint()) {
00426 int numCon = bodyVec[bn]->getDynJoint()->getNumConstraints();
00427 numDynJointConstraints += numCon;
00428 DBGP(bodyVec[bn]->getName().latin1() << ": " << numCon << " constraints");
00429 }
00430
00431 objContactList = bodyVec[bn]->getContacts();
00432 for (cp=objContactList.begin();cp!=objContactList.end();cp++) {
00433
00434 if (std::find(contactList.begin(),contactList.end(),(*cp)->getMate()) == contactList.end()) {
00435 numContacts++;
00436 numTotalFrictionEdges += (*cp)->numFrictionEdges;
00437 contactList.push_back(*cp);
00438 }
00439 }
00440 }
00441
00442 DBGP("Num contacts: " << numContacts);
00443 DBGP("Num friction edges: " << numTotalFrictionEdges);
00444 DBGP("Num dynjoint: " << numDynJointConstraints);
00445
00446
00447 dcopy(Mrows*Mrows,&db0,0,M,1);
00448 dcopy(Mrows*Mrows,&db0,0,M_i,1);
00449 dcopy(Mrows,&db0,0,fext,1);
00450
00451
00452 if (numJoints) {
00453 Nurows = Mrows;
00454 Nucols = numDynJointConstraints + numCouplingConstraints;
00455 DBGP("Nucols: " << Nucols);
00456
00457 Nu = new double[Nurows * Nucols];
00458 dcopy(Nurows*Nucols,&db0,0,Nu,1);
00459
00460 eps = new double[Nucols];
00461 dcopy(Nucols,&db0,0,eps,1);
00462 Arows = Mrows+Nucols;
00463 }
00464
00465
00466 if (numContacts || numDOFLimits) {
00467 Dcols = numTotalFrictionEdges;
00468
00469 DBGP("numContacts " << numContacts);
00470 DBGP("Dcols " << Dcols);
00471 DBGP("numDOFLimits " << numDOFLimits);
00472
00473 Hrows = Mrows;
00474 Hcols = Dcols + 2*numContacts + numDOFLimits;
00475 H = new double[Hrows * Hcols];
00476
00477 dcopy(Hrows*Hcols,&db0,0,H,1);
00478
00479 v1 = new double[Hrows * Hcols];
00480 v2 = new double[Hrows];
00481 dcopy(Hrows*Hcols,&db0,0,v1,1);
00482 dcopy(Hrows,&db0,0,v2,1);
00483
00484 k = new double[Mrows];
00485 Arows = Hcols;
00486 lambda = new double[Arows];
00487 } else {
00488 Dcols = 0;
00489 }
00490
00491
00492 if (numJoints || numContacts) {
00493 A = new double[Arows*Arows];
00494 g = new double[Arows];
00495
00496 dcopy(Arows*Arows,&db0,0,A,1);
00497 dcopy(Arows,&db0,0,g,1);
00498 }
00499
00500
00501 for (bn=0;bn<numBodies;bn++) {
00502 memcpy(vl+6*bn,bodyVec[bn]->getVelocity(),6*sizeof(double));
00503 memcpy(vlnew+6*bn,bodyVec[bn]->getVelocity(),6*sizeof(double));
00504
00505 memcpy(ql+7*bn,bodyVec[bn]->getPos(),7*sizeof(double));
00506 memcpy(qnew+7*bn,bodyVec[bn]->getPos(),7*sizeof(double));
00507
00508 currq = qnew + 7*bn;
00509 Quaternion tmpQuat(currq[3],currq[4],currq[5],currq[6]);
00510 tmpQuat.ToRotationMatrix(Rot);
00511
00512
00513
00514
00515
00516 R_N_B[0] = Rot[0]; R_N_B[3] = Rot[1]; R_N_B[6] = Rot[2];
00517 R_N_B[1] = Rot[3]; R_N_B[4] = Rot[4]; R_N_B[7] = Rot[5];
00518 R_N_B[2] = Rot[6]; R_N_B[5] = Rot[7]; R_N_B[8] = Rot[8];
00519
00520
00521
00522
00523 memcpy(Jcg_B,bodyVec[bn]->getInertia(),9*sizeof(double));
00524
00525 dscal(9, bodyVec[bn]->getMass(), Jcg_B, 1);
00526 dgemm("N","N",3,3,3,1.0,R_N_B,3,Jcg_B,3,0.0,Jcg_tmp,3);
00527 dgemm("N","T",3,3,3,1.0,Jcg_tmp,3,R_N_B,3,0.0,Jcg_N,3);
00528
00529 if ((info = invertMatrix(3,Jcg_N,Jcg_N_inv))) {
00530 printf("In iterateDynamics, inertia matrix inversion failed (info is %d)\n",info);
00531 fprintf(stderr,"%f %f %f\n",Jcg_B[0], Jcg_B[1], Jcg_B[2]);
00532 fprintf(stderr,"%f %f %f\n",Jcg_B[3], Jcg_B[4], Jcg_B[5]);
00533 fprintf(stderr,"%f %f %f\n",Jcg_B[6], Jcg_B[7], Jcg_B[8]);
00534 fprintf(stderr,"Body is %s\n",bodyVec[bn]->getName().latin1());
00535 }
00536
00537 currM = M+((6*bn)*Mrows + bn*6);
00538
00539 currM[0] = bodyVec[bn]->getMass();
00540 currM[6*numBodies+1] = bodyVec[bn]->getMass();
00541 currM[12*numBodies+2] = bodyVec[bn]->getMass();
00542 fillMatrixBlock(Jcg_N,3,3,3,5,5,currM,Mrows);
00543
00544 currM = M_i+((6*bn)*Mrows + bn*6);
00545
00546 currM[0] = 1.0/bodyVec[bn]->getMass();
00547 currM[Mrows+1] = 1.0/bodyVec[bn]->getMass();
00548 currM[2*Mrows+2] = 1.0/bodyVec[bn]->getMass();
00549 fillMatrixBlock(Jcg_N_inv,3,3,3,5,5,currM,Mrows);
00550
00551
00552
00553
00554
00555 fext[6*bn+2] = 0;
00556
00557 dgemv("N",3,3,1.0,Jcg_N,3,&vl[6*bn+3],1,0.0,tmp3,1);
00558 fext[6*bn+3] = - (vl[6*bn+4]*tmp3[2] - vl[6*bn+5]*tmp3[1]);
00559 fext[6*bn+4] = - (vl[6*bn+5]*tmp3[0] - vl[6*bn+3]*tmp3[2]);
00560 fext[6*bn+5] = - (vl[6*bn+3]*tmp3[1] - vl[6*bn+4]*tmp3[0]);
00561
00562 double ForcesToBodyFrame[36];
00563 transf invBody = bodyVec[bn]->getTran().inverse();
00564 vec3 invBodyTransl = invBody.translation();
00565 buildForceTransform(invBody,invBodyTransl,ForcesToBodyFrame);
00566 DBGP("fext initial: ");
00567 DBGST( disp_mat(stdout,&fext[6*bn],1,6,0) );
00568
00569
00570 daxpy(6,1.0,bodyVec[bn]->getExtWrenchAcc(),1,&fext[6*bn],1);
00571 DBGP("fext with accumulated wrench: ");
00572 DBGST( disp_mat(stdout,&fext[6*bn],1,6,0) );
00573
00574 if (numContacts||numDOFLimits) {
00575
00576 currM = M+((6*bn)*Mrows + bn*6);
00577 dgemv("N",6,6,1.0,currM,Mrows,vl+6*bn,1,0.0,k+6*bn,1);
00578 }
00579 }
00580
00581 if (numJoints) {
00582 int ncn = 0;
00583 int hcn = 0;
00584 for (i=0;i<numBodies;i++) {
00585 if (bodyVec[i]->getDynJoint())
00586 bodyVec[i]->getDynJoint()-> buildConstraints(Nu,eps,numBodies,islandIndices,ncn);
00587 }
00588 for (i=0;i<numRobots;i++) {
00589 robotVec[i]->buildDOFLimitConstraints(islandIndices,numBodies,H,g,hcn);
00590 robotVec[i]->buildDOFCouplingConstraints(islandIndices,numBodies,Nu,eps,ncn);
00591 }
00592 for (i=0;i<Nucols;i++) {
00593 eps[i] *= ERP/h;
00594 }
00595 for (i=0; i<hcn; i++) {
00596 g[i] *= ERP/h;
00597 }
00598 }
00599
00600
00601 if (!contactList.empty()) {
00602 DBGP("processing contacts");
00603 double Ftform_N_C[36];
00604
00605
00606 double *Wn = &H[numDOFLimits*Hrows];
00607 double *D = &H[(numDOFLimits+numContacts)*Hrows];
00608
00609 double *E = &A[(numDOFLimits+numContacts+Dcols)*Arows + numDOFLimits+numContacts];
00610 double *negET = &A[(numDOFLimits+numContacts)*Arows + numDOFLimits+numContacts+Dcols];
00611 double *MU = &A[numDOFLimits*Arows + numDOFLimits+numContacts+Dcols];
00612 double *contactEps = &g[numDOFLimits];
00613
00614 int frictionEdgesCount = 0;
00615 for (cp=contactList.begin(),cn=0; cp!=contactList.end(); cp++,cn++){
00616
00617
00618 transf cf = (*cp)->getContactFrame() * (*cp)->getBody1Tran();
00619 transf cf2 = (*cp)->getMate()->getContactFrame() * (*cp)->getBody2Tran();
00620
00621 DBGP("CONTACT DISTANCE: " << (cf.translation() - cf2.translation()).len());
00622 if (useContactEps) {
00623 contactEps[cn] = MIN(0.0,-ERP/h *
00624 (Contact::THRESHOLD/2.0 - (cf.translation() - cf2.translation()).len()));
00625 }
00626 DBGP(" EPS: " << contactEps[cn]);
00627 vec3 normal(cf.affine().element(2,0), cf.affine().element(2,1), cf.affine().element(2,2));
00628
00629
00630 for (bn=0;bn<numBodies;bn++)
00631 if ((*cp)->getBody1() == bodyVec[bn]) break;
00632 if (bn<numBodies) {
00633
00634 vec3 radius = cf.translation() - ( bodyVec[bn]->getCoG() * (*cp)->getBody1Tran() - position::ORIGIN );
00635
00636
00637
00638 vec3 RcrossN = radius * normal;
00639 DBGP("body1 normal: " << normal);
00640 DBGP("body1 radius: " << radius);
00641
00642 Wn[cn*Hrows+6*bn] = normal.x();
00643 Wn[cn*Hrows+6*bn+1] = normal.y();
00644 Wn[cn*Hrows+6*bn+2] = normal.z();
00645 Wn[cn*Hrows+6*bn+3] = RcrossN.x();
00646 Wn[cn*Hrows+6*bn+4] = RcrossN.y();
00647 Wn[cn*Hrows+6*bn+5] = RcrossN.z();
00648
00649 vec3 bodyOrigin = bodyVec[bn]->getCoG() * (*cp)->getBody1Tran() - position::ORIGIN;
00650 buildForceTransform(cf,bodyOrigin,Ftform_N_C);
00651
00652
00653
00654
00655 dgemm("N","N",
00656 6,(*cp)->numFrictionEdges,6,
00657 1.0,Ftform_N_C,6,
00658 (*cp)->frictionEdges,6,
00659 0.0,&D[ frictionEdgesCount*Hrows+6*bn],Hrows);
00660 }
00661
00662
00663 for(bn=0;bn<numBodies;bn++)
00664 if ((*cp)->getBody2() == bodyVec[bn]) break;
00665 if (bn<numBodies) {
00666
00667
00668 normal = -normal;
00669
00670
00671 vec3 radius = cf.translation() - (bodyVec[bn]->getCoG() * (*cp)->getBody2Tran() - position::ORIGIN);
00672 vec3 RcrossN = radius * normal;
00673 DBGP("body2 normal: " << normal);
00674 DBGP("body2 radius: " << radius);
00675
00676 Wn[cn*Hrows+6*bn] = normal.x();
00677 Wn[cn*Hrows+6*bn+1] = normal.y();
00678 Wn[cn*Hrows+6*bn+2] = normal.z();
00679 Wn[cn*Hrows+6*bn+3] = RcrossN.x();
00680 Wn[cn*Hrows+6*bn+4] = RcrossN.y();
00681 Wn[cn*Hrows+6*bn+5] = RcrossN.z();
00682
00683 vec3 bodyOrigin = bodyVec[bn]->getCoG()*(*cp)->getBody2Tran() - position::ORIGIN;
00684 buildForceTransform(cf,bodyOrigin,Ftform_N_C);
00685
00686
00687
00688
00689
00690 dgemm("N","N",
00691 6,(*cp)->numFrictionEdges,6,
00692 -1.0,Ftform_N_C,6,
00693 (*cp)->frictionEdges,6,
00694 0.0,&D[ frictionEdgesCount*Hrows+6*bn ],Hrows);
00695 }
00696
00697
00698 for (i=frictionEdgesCount; i<frictionEdgesCount+(*cp)->numFrictionEdges; i++) {
00699 E[cn*Arows+i] = 1.0;
00700 negET[i*Arows+cn] = -1.0;
00701 }
00702 MU[cn*Arows + cn] = (*cp)->getCof();
00703 frictionEdgesCount += (*cp)->numFrictionEdges;
00704 }
00705 }
00706
00707 if (numContacts || numDOFLimits)
00708 daxpy(Mrows,h,fext,1,k,1);
00709
00710 if (numJoints && (numContacts || numDOFLimits)) {
00711
00712
00713
00714
00715
00716 NutM_i = new double[Nucols*Mrows];
00717 NutM_iNu = new double[Nucols*Nucols];
00718 INVNutM_iNu = new double[Nucols*Nucols];
00719 INVNutM_iNuNut = new double[Nucols*Nurows];
00720 INVNutM_iNuNutM_i = new double[Nucols*Mrows];
00721 INVNutM_iNuNutM_iH = new double[Nucols*Hcols];
00722
00723
00724 NutM_ikminuseps = new double[Nucols];
00725 INVNutM_iNuNutM_ikminuseps = new double[Nucols];
00726
00727 dgemm("T","N",Nucols,Mrows,Mrows,1.0,Nu,Nurows,M_i,Mrows, 0.0,NutM_i,Nucols);
00728 dgemm("N","N",Nucols,Nucols,Mrows,1.0,NutM_i,Nucols,Nu,Nurows, 0.0,NutM_iNu,Nucols);
00729 if ((info = invertMatrix(Nucols,NutM_iNu,INVNutM_iNu)))
00730 printf("In iterateDynamics, NutM_iNu matrix inversion failed (info is %d)\n",info);
00731
00732 dgemm("N","T",Nucols,Nurows,Nucols,1.0,INVNutM_iNu,Nucols,Nu,Nurows,
00733 0.0,INVNutM_iNuNut,Nucols);
00734 dgemm("N","N",Nucols,Mrows,Mrows,1.0,INVNutM_iNuNut,Nucols,M_i,Mrows,
00735 0.0,INVNutM_iNuNutM_i,Nucols);
00736 dgemm("N","N",Nucols,Hcols,Mrows,1.0,INVNutM_iNuNutM_i,Nucols,H,Hrows,
00737 0.0,INVNutM_iNuNutM_iH,Nucols);
00738 dgemm("N","N",Nurows,Hcols,Nucols,-1.0,Nu,Nurows,INVNutM_iNuNutM_iH,Nucols,
00739 0.0,v1,Nurows);
00740
00741 dgemv("N",Nucols,Mrows,1.0,NutM_i,Nucols,k,1,0.0,NutM_ikminuseps,1);
00742 daxpy(Nucols,-1.0,eps,1,NutM_ikminuseps,1);
00743
00744 dgemv("N",Nucols,Nucols,1.0,INVNutM_iNu,Nucols,NutM_ikminuseps,1,
00745 0.0,INVNutM_iNuNutM_ikminuseps,1);
00746
00747 dgemv("N",Nurows,Nucols,-1.0,Nu,Nurows,INVNutM_iNuNutM_ikminuseps,1,
00748 0.0,v2,1);
00749 }
00750
00751 if (numContacts || numDOFLimits) {
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761
00762 DBGP("k:");
00763 DBGST( disp_mat(stdout,k,1,Mrows,0) );
00764 DBGP("first g:");
00765 DBGST( disp_mat(stdout,g,1,Arows,0) );
00766
00767 daxpy(Mrows*Hcols,1.0,H,1,v1,1);
00768 daxpy(Mrows,1.0,k,1,v2,1);
00769
00770
00771 HtM_i = new double[Hcols*Mrows];
00772 dgemm("T","N",Hcols,Mrows,Hrows,1.0,H,Hrows,M_i,Mrows,0.0,HtM_i,Hcols);
00773
00774 dgemm("N","N",Hcols,Hcols,Mrows,1.0,HtM_i,Hcols,v1,Mrows,1.0,A,Arows);
00775
00776 dgemv("N",Hcols,Mrows,1.0,HtM_i,Hcols,v2,1,1.0,g,1);
00777 }
00778
00779 int frictionEdgesCount;
00780
00781
00782 if (numContacts || numDOFLimits) {
00783 bool lemkePredict = false;
00784 if (lemkePredict) {
00785
00786 assembleLCPPrediction(lambda, Arows, numDOFLimits, &contactList);
00787 predLambda = new double[Arows];
00788 dcopy(Arows, lambda, 1, predLambda, 1);
00789
00790
00791 }
00792
00793
00794
00795
00796 DBGP("g:");
00797 DBGST( for (i=0;i<Arows;i++) printf("%le ",g[i]); );
00798 DBGP("\n");
00799
00800 double CFM = 0.0;
00801 int lcperr = 1, lcpIter;
00802 while ( CFM < 1.0e-7) {
00803 lcperr = myLemke(A, Arows, g, lambda, lemkePredict, false, lcpIter);
00804 if (!lcperr) break;
00805 if (CFM == 0) CFM = 1.0e-11;
00806 else CFM *= 10.0;
00807 for (i=0;i<Arows;i++) A[i*Arows+i]+= CFM;
00808 DBGP("Lemke failed, re-run with CFM " << CFM);
00809 }
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825
00826
00827
00828
00829
00830
00831 if (!lcperr) {
00832
00833
00834
00835 double contactForce[6];
00836 double invh = 1.0/h;
00837 dgemv("N",Hrows,Hcols,1.0,v1,Hrows,lambda,1,1.0,v2,1);
00838 dgemv("N",Hrows,Hrows,1.0,M_i,Hrows,v2,1,0.0,vlnew,1);
00839
00840
00841
00842 frictionEdgesCount = 0;
00843 for (cp=contactList.begin(),cn=0;cp!=contactList.end();cp++,cn++){
00844
00845
00846 (*cp)->setLCPInfo(lambda[numDOFLimits+cn],
00847 lambda[Arows - numContacts + cn],
00848 &lambda[numDOFLimits + numContacts + frictionEdgesCount] );
00849
00850
00851
00852 dgemv("N",
00853 6,(*cp)->numFrictionEdges,
00854 invh,(*cp)->frictionEdges,6,
00855 &lambda[ numDOFLimits + numContacts + frictionEdgesCount ], 1,
00856 0.0,contactForce,1);
00857
00858 contactForce[2] += lambda[numDOFLimits+cn]/h;
00859
00860 dscal(3,1.0e-6,contactForce,1);
00861 dscal(3,1.0e-9,contactForce+3,1);
00862
00863 (*cp)->setDynamicContactWrench(contactForce);
00864
00865
00866
00867
00868 (*cp)->setUpFrictionEdges(true);
00869
00870 dscal(6,-1.0,contactForce,1);
00871 transf cf = (*cp)->getContactFrame() * (*cp)->getBody1Tran();
00872 transf cf2 = (*cp)->getMate()->getContactFrame() * (*cp)->getBody2Tran();
00873 vec3 cvec(contactForce);
00874 cvec = cvec * cf * cf2.inverse();
00875 contactForce[0] = cvec[0];
00876 contactForce[1] = cvec[1];
00877 contactForce[2] = cvec[2];
00878 (*cp)->getMate()->setDynamicContactWrench(contactForce);
00879
00880 (*cp)->getMate()->setUpFrictionEdges(true);
00881
00882 frictionEdgesCount += (*cp)->numFrictionEdges;
00883 }
00884
00885 #ifdef GRASPITDBG
00886 printf("Lambda is:\n");
00887 for (i=0;i<Arows;i++) {
00888 printf("%le ",lambda[i]);
00889 if (lambda[i] < -MACHINE_ZERO) {
00890 printf ("NEGATIVE LAMBDA!!!\n");
00891 }
00892 }
00893 printf("\n");
00894 printf("Alambda+g = \n");
00895 dgemv("N",Arows,Arows,1.0,A,Arows,lambda,1,1.0,g,1);
00896 for (i=0;i<Arows;i++)
00897 printf("%le ",g[i]);
00898 printf("\n");
00899 if (numJoints){
00900 double *cnu= new double[Nucols];
00901 printf("Cnu:\n");
00902 dgemv("N",Nucols,Hcols,-1.0,INVNutM_iNuNutM_iH,Nucols,lambda,1,0.0,cnu,1);
00903 daxpy(Nucols,-1.0,INVNutM_iNuNutM_ikminuseps,1,cnu,1);
00904 disp_mat(stdout,cnu,1,Nucols,0);
00905 delete [] cnu;
00906 }
00907 #endif
00908
00909 }
00910 else errCode = 1;
00911 }
00912 else if (numJoints) {
00913 DBGP("solving with inversion");
00914
00915
00916
00917
00918 fillMatrixBlock(M,Mrows,0,0,Mrows-1,Mrows-1,A,Arows);
00919 for (i=0;i<Mrows;i++)
00920 for (j=Mrows;j<Arows;j++) {
00921 A[i*Arows + j] = Nu[(j-Mrows)*Nurows + i];
00922 A[j*Arows + i] = -Nu[(j-Mrows)*Nurows + i];
00923 }
00924
00925 for (i=0;i<Arows;i++)
00926 for(j=0;j<Arows;j++)
00927 if (fabs(A[i*Arows+j]) < MACHINE_ZERO) A[i*Arows+j] = 0.0;
00928
00929 dgemv("N",Mrows,Mrows,1.0,M,Mrows,vl,1,0.0,g,1);
00930 daxpy(Mrows,h,fext,1,g,1);
00931 dcopy(Nucols,eps,1,g+Mrows,1);
00932
00933 #ifdef GRASPITDBG
00934 printf("g:\n");
00935 disp_mat(stdout,g,1,Arows,0);
00936 printf("h: %le\n",h);
00937 #endif
00938
00939 int *ipiv = new int[Arows];
00940 dgesv(Arows,1,A,Arows,ipiv,g,Arows,&info);
00941 if (info != 0){
00942 printf("In iterateDynamics, A matrix inversion failed (info is %d)\n",info);
00943 std::cerr << "matrix solve failed"<< std::endl;
00944 }
00945
00946 delete [] ipiv;
00947 #ifdef GRASPITDBG
00948 printf("lambda:\n");
00949 disp_mat(stdout,g,1,Arows,0);
00950 #endif
00951 dcopy(Mrows,g,1,vlnew,1);
00952
00953 }
00954
00955 else{
00956
00957 dgemv("N",Mrows,Mrows,h,M_i,Mrows,fext,1,1.0,vlnew,1);
00958 }
00959
00960
00961 daxpy(6*numBodies,-1,vlnew,1,vl,1);
00962 dscal(6*numBodies,-1.0/h,vl,1);
00963
00964 for (i=0;i<numBodies;i++) {
00965 bodyVec[i]->setAccel(&vl[6*i]);
00966 bodyVec[i]->setVelocity(&vlnew[6*i]);
00967 }
00968
00969
00970 if (numJoints || numContacts) {
00971 delete [] A;
00972 delete [] g;
00973 }
00974
00975 if (numJoints) {
00976 delete [] Nu;
00977 delete [] eps;
00978
00979 if (numContacts || numDOFLimits) {
00980 delete [] NutM_i;
00981 delete [] NutM_iNu;
00982 delete [] INVNutM_iNu;
00983 delete [] INVNutM_iNuNut;
00984 delete [] INVNutM_iNuNutM_i;
00985 delete [] INVNutM_iNuNutM_iH;
00986
00987 delete [] NutM_ikminuseps;
00988 delete [] INVNutM_iNuNutM_ikminuseps;
00989
00990 }
00991 }
00992
00993 if (numContacts || numDOFLimits) {
00994
00995 delete [] H;
00996 delete [] HtM_i;
00997 delete [] v1;
00998 delete [] v2;
00999 delete [] lambda;
01000 if (predLambda) delete [] predLambda;
01001 delete [] k;
01002 }
01003
01004 delete [] ql;
01005 delete [] qnew;
01006 delete [] vl;
01007 delete [] vlnew;
01008 delete [] M;
01009 delete [] M_i;
01010 delete [] fext;
01011
01012 return errCode;
01013 }
01014
01020 void
01021 assembleLCPPrediction(double *lambda, int Arows, int numDOFLimits, std::list<Contact *> *contactList)
01022 {
01023 double db0 = 0.0;
01024 dcopy(Arows, &db0, 0, lambda, 1);
01025
01026 std::list<Contact *>::iterator cp;
01027 int numContacts = contactList->size();
01028 int frictionEdgesCount = 0,cn;
01029
01030 for (cp=contactList->begin(),cn=0;cp!=contactList->end();cp++,cn++){
01031 if ( (*cp)->inherits() ) {
01032 lambda[numDOFLimits+cn] = (*cp)->getPrevCn();
01033 lambda[Arows - numContacts + cn] = (*cp)->getPrevLambda();
01034 memcpy(&lambda[numDOFLimits + numContacts + frictionEdgesCount],
01035 (*cp)->getPrevBetas(), (*cp)->numFrictionEdges * sizeof(double) );
01036 }
01037 frictionEdgesCount += (*cp)->numFrictionEdges;
01038 }
01039 }
01040
01041 void
01042 printLCPBasis(double *lambda, int Arows, int numDOFLimits, int numContacts)
01043 {
01044 int i,mz;
01045 fprintf(stderr,"[");
01046 for (i=0; i < Arows; i++) {
01047 mz = 0;
01048 if (lambda[i] > 0) mz = 1;
01049 if (i == numDOFLimits || i == numDOFLimits + numContacts || i == Arows - numContacts)
01050 fprintf(stderr," |");
01051 fprintf(stderr," %d",mz);
01052 }
01053 fprintf(stderr," ]\n");
01054 }
01055
01056
01057 void sortVector(int *v, int n)
01058 {
01059 bool done = false;
01060 while (!done) {
01061 done = true;
01062 for (int i=1; i<n; i++) {
01063 if (v[i] < v[i-1]) {
01064 double tmp = v[i];
01065 v[i] = v[i-1];
01066 v[i-1] = tmp;
01067 done = false;
01068 }
01069 }
01070 }
01071 }
01072
01081 int
01082 myLemke(double *M,int n,double *q,double *z, bool usePrediction, bool ldbg, int &iterations)
01083 {
01084
01085
01086 double zer_tol = 1.0e-11;
01087 double piv_tol = 1.0e-13;
01088
01089 int maxiter = MIN(1000, 25*n);
01090 int i,k,info,iter,err;
01091 int *ipiv,*bas,*j;
01092 double db0=0.0;
01093 double *tmpZ,*B,*tmpB,*Be,*x,*d;
01094 double rowSum,theta,tval,ratio;
01095 int t,entering,leaving,lvindex;
01096
01097 iterations = 0;
01098
01099 for (i=0;i<n && q[i]>=0.0;i++)
01100 z[i] = 0.0;
01101 if (i==n) return 0;
01102
01103 int *possibleLVindex = new int[n];
01104 tmpZ = new double[2*n];
01105 dcopy(2*n,&db0,0,tmpZ,1);
01106
01107 j = new int[n];
01108 for (i=0;i<n;i++) j[i] = 0;
01109
01110 bas = new int[n];
01111 B = new double[n*n];
01112 tmpB = new double[n*n];
01113 x = new double[n];
01114 ipiv = new int[n];
01115
01116
01117 if (!usePrediction) {
01118
01119 for (i=n;i<2*n;i++) bas[i-n] = i;
01120
01121 dcopy(n*n,&db0,0,B,1);
01122 for (i=0;i<n;i++)
01123 B[i*n+i] = -1.0;
01124
01125 dcopy(n,q,1,x,1);
01126 } else {
01127
01128
01129
01130 for (i=0;i<n;i++) {
01131 if ( z[i] > 0 )
01132 bas[i] = i;
01133 else
01134 bas[i] = n+i;
01135 }
01136 sortVector(bas, n);
01137
01138
01139
01140
01141
01142
01143
01144 dcopy(n*n, &db0, 0, B, 1);
01145 for (i=0; i<n; i++) {
01146 if ( bas[i] >= n ) {
01147 B[ i*n + bas[i]-n ] = -1;
01148 } else {
01149 for (k=0; k<n; k++)
01150 B[ i*n + k ] = M[ bas[i]*n + k];
01151 }
01152 }
01153
01154
01155 dcopy(n,q,1,x,1);
01156 dcopy(n*n, B, 1, tmpB, 1);
01157 dgesv(n, 1, tmpB, n, ipiv, x, n, &info);
01158 for (i=0; i<n; i++)
01159 x[i] = -1.0 * x[i];
01160 if (info!=0)
01161 fprintf(stderr,"Inversion failed when computing initial basis from user-supplied starting point!\n");
01162 }
01163
01164
01165
01166
01167
01168
01169
01170 for (i=0;i<n && x[i] >= 0.0;i++)
01171 tmpZ[bas[i]] = x[i];
01172
01173 if (i==n) {
01174 dcopy(n,tmpZ,1,z,1);
01175 delete [] tmpZ; delete [] j; delete [] bas; delete [] B; delete [] x;
01176 delete [] tmpB; delete [] ipiv; delete [] possibleLVindex;
01177 return 0;
01178 }
01179
01180
01181 t = 2*n;
01182 entering = t;
01183
01184
01185 tval = x[0];
01186 lvindex = 0;
01187 for (i=1;i<n;i++) {
01188 if (x[i] < tval) {
01189 tval = x[i];
01190 lvindex = i;
01191 }
01192 }
01193 tval = -tval;
01194 leaving = bas[lvindex];
01195
01196
01197 bas[lvindex] = t;
01198 for (i=0;i<n;i++) {
01199 x[i] = x[i] + tval;
01200 rowSum = 0.0;
01201 for (k=0;k<n;k++)
01202 rowSum += B[k*n+i];
01203 B[lvindex*n+i] = -rowSum;
01204 }
01205 x[lvindex] = tval;
01206
01207 Be = new double[n];
01208 d = new double[n];
01209
01210 #ifdef LEMKE_DBG
01211 if (ldbg) {
01212 printf("bas:\n");
01213 for (i=0;i<n;i++)
01214 printf("%d ",bas[i]);
01215 printf("\n");
01216 }
01217 #endif
01218
01219
01220 for (iter=1;iter<maxiter;iter++) {
01221 iterations = iter;
01222
01223
01224 if (leaving == t) break;
01225 if (leaving < n) {
01226 entering = n+leaving;
01227 dcopy(n,&db0,0,Be,1);
01228 Be[leaving] = -1.0;
01229 }
01230 else {
01231 entering = leaving - n;
01232 dcopy(n,&M[n*entering],1,Be,1);
01233 }
01234
01235 #ifdef LEMKE_DBG
01236 if (ldbg) {
01237 printf("entering: %d\n",entering);
01238
01239
01240 }
01241 #endif
01242
01243 dcopy(n,Be,1,d,1);
01244 dcopy(n*n,B,1,tmpB,1);
01245 dgesv(n,1,tmpB,n,ipiv,d,n,&info);
01246
01247
01248
01249
01250 #ifdef LEMKE_DBG
01251 if (ldbg) {
01252
01253
01254 printf("d:\n");
01255 disp_mat(stdout,d,1,n,0);
01256 }
01257 #endif
01258
01259 int definite=-1;
01260 double rat;
01261
01262 err = 2;
01263 theta = HUGE_VAL;
01264 for (i=0;i<n;i++) {
01265 if (ldbg)
01266 printf("i=%d x: %15.12le d: %15.12le",i,x[i],d[i]);
01267 if (d[i] > piv_tol) {
01268
01269 err=0;
01270 rat = (x[i]+zer_tol)/d[i];
01271 if (rat < theta) {
01272 theta=rat;
01273 definite = i;
01274 if (ldbg) printf("theta: %15.12le",theta);
01275 }
01276 }
01277 if (ldbg) printf("\n");
01278
01279 j[i] = -1;
01280 }
01281
01282 if (err) {
01283
01284 delete [] tmpZ; delete [] j; delete [] bas; delete [] B; delete [] Be;
01285 delete [] x; delete [] d; delete [] ipiv; delete [] tmpB;
01286 delete [] possibleLVindex;
01287 return err;
01288 }
01289
01290 for (i=0;i<n;i++) {
01291 if (d[i] > piv_tol) {
01292 if (theta - x[i]/d[i] > -zer_tol) j[i] = i;
01293 }
01294 }
01295
01296 j[definite] = definite;
01297
01298 #ifdef LEMKE_DBG
01299 if (ldbg) {
01300 printf("theta: %lf\n",theta);
01301 printf("j: ");
01302 for (i=0;i<n;i++) printf("%d ",j[i]);
01303 printf("\n");
01304 }
01305 #endif
01306
01307
01308 lvindex = -1;
01309 for (i=0;i<n;i++)
01310 if (j[i] >= 0 && bas[i] == t) lvindex = i;
01311
01312
01313 if (lvindex > -1) {
01314 lvindex = j[lvindex];
01315 if (ldbg) printf("artificial found\n");
01316 }
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331
01332 else {
01333 theta = -HUGE_VAL;
01334 for (i=0;i<n;i++) {
01335 if (j[i] >= 0 && d[i] > theta) theta = d[i];
01336 }
01337
01338 int count=0;
01339 for (i=0;i<n;i++) {
01340 if (j[i] >= 0 && fabs(d[i] - theta) < zer_tol) {
01341 possibleLVindex[count++] = j[i];
01342 }
01343 }
01344
01345 if (count > 1) {
01346
01347 count = (int)((double)rand()/(RAND_MAX+1.0)*count);
01348 lvindex = possibleLVindex[count];
01349 }
01350 else lvindex = possibleLVindex[0];
01351 }
01352 leaving = bas[lvindex];
01353
01354 #ifdef LEMKE_DBG
01355 if (ldbg) {
01356 printf("lvindex: %d\n",lvindex);
01357 printf("theta: %lf\n",theta);
01358 printf("leaving: %d\n",leaving);
01359 }
01360 #endif
01361
01362
01363 ratio = x[lvindex]/d[lvindex];
01364 daxpy(n,-ratio,d,1,x,1);
01365 x[lvindex] = ratio;
01366 dcopy(n,Be,1,&B[lvindex*n],1);
01367 bas[lvindex] = entering;
01368
01369 #ifdef LEMKE_DBG
01370 if (ldbg) {
01371 printf("ratio: %lf\n",ratio);
01372
01373
01374
01375
01376 printf("bas:\n");
01377 for (i=0;i<n;i++) printf("%d ",bas[i]);
01378 printf("\n");
01379 }
01380 #endif
01381 }
01382
01383 if (iter==maxiter) {
01384 DBGP("Max iterations reached in myLemke");
01385 delete [] tmpZ; delete [] j; delete [] bas; delete [] B; delete [] Be;
01386 delete [] x; delete [] d; delete [] ipiv; delete [] tmpB;
01387 delete [] possibleLVindex;
01388 return 1;
01389 }
01390
01391 for (i=0;i<n;i++) {
01392 if (bas[i] < n) {
01393 tmpZ[bas[i]] = x[i];
01394
01395 }
01396 }
01397
01398 dcopy(n,tmpZ,1,z,1);
01399
01400 dcopy(n,q,1,tmpZ,1);
01401 #ifdef LEMKEDBG
01402 printf("q:\n");
01403 disp_mat(stdout,q,1,n,0);
01404 #endif
01405 dgemv("N",n,n,1.0,M,n,z,1,1.0,tmpZ,1);
01406 #ifdef LEMKEDBG
01407 printf("Mz+q:\n");
01408 disp_mat(stdout,tmpZ,1,n,0);
01409 #endif
01410
01411 for (i=0;i<n;i++)
01412 if (tmpZ[i] < -100.0*MACHINE_ZERO) {
01413
01414 delete [] tmpZ; delete [] j; delete [] bas; delete [] B; delete [] Be;
01415 delete [] x; delete [] d; delete [] ipiv; delete [] tmpB;
01416 delete [] possibleLVindex;
01417 return 1;
01418 }
01419
01420
01421 delete [] tmpZ; delete [] j; delete [] bas; delete [] B; delete [] Be;
01422 delete [] x; delete [] d; delete [] ipiv; delete [] tmpB;
01423 delete [] possibleLVindex;
01424 return 0;
01425 }
01426