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 <stdlib.h>
00032 #include <math.h>
00033 #ifdef USE_DMALLOC
00034 #include "dmalloc.h"
00035 #endif
00036
00037 #include <Inventor/nodes/SoCone.h>
00038 #include <Inventor/nodes/SoCoordinate3.h>
00039 #include <Inventor/nodes/SoCylinder.h>
00040 #include <Inventor/nodes/SoIndexedFaceSet.h>
00041 #include <Inventor/nodes/SoMaterial.h>
00042 #include <Inventor/nodes/SoTransform.h>
00043 #include <Inventor/nodes/SoTranslation.h>
00044 #include <Inventor/nodes/SoSeparator.h>
00045 #include <Inventor/nodes/SoSphere.h>
00046
00047 #include "matvec3D.h"
00048 #include "contact.h"
00049 #include "world.h"
00050 #include "body.h"
00051 #include "mytools.h"
00052 #include "matrix.h"
00053 #include "FitParabola.h"
00054
00055
00056 #include "debug.h"
00057
00058 const double Contact::THRESHOLD = 0.1;
00059 const double Contact::INHERITANCE_THRESHOLD = 1;
00060 const double Contact::INHERITANCE_ANGULAR_THRESHOLD = 0.984;
00061
00067 Contact::Contact(Body *b1, Body *b2, position pos, vec3 norm)
00068 {
00069 body1 = b1;
00070 body2 = b2;
00071 mate = NULL;
00072 wrench = NULL;
00073 body1Tran = b1->getTran();
00074 body2Tran = b2->getTran();
00075
00076 updateCof();
00077 normal = normalise(norm);
00078 loc = pos;
00079 vec3 tangentX,tangentY;
00080
00081 if (fabs(normal % vec3(1,0,0)) > 1.0 - MACHINE_ZERO) {
00082 tangentX = normalise(normal * vec3(0,0,1));
00083 } else {
00084 tangentX = normalise(normal * vec3(1,0,0));
00085 }
00086 tangentY = normalise(normal * tangentX);
00087 frame = coordinate_transf(loc,tangentX,tangentY);
00088 coneMat = NULL;
00089 prevBetas = NULL;
00090 inheritanceInfo = false;
00091 for (int i=0; i<6; i++) {
00092 dynamicForce[i] = 0;
00093 }
00094 }
00095
00102 Contact::~Contact()
00103 {
00104 if (optimalCoeffs) delete [] optimalCoeffs;
00105 if (wrench) delete [] wrench;
00106 if (prevBetas) delete [] prevBetas;
00107
00108 if (mate) {
00109 mate->setMate(NULL);
00110 body2->removeContact(mate);
00111 }
00112 DBGP("Contact deleted");
00113 }
00114
00124 void Contact::wrenchFromFrictionEdge(double *edge, const vec3 &radius, Wrench *wr)
00125 {
00126 vec3 tangentX = frame.affine().row(0);
00127 vec3 tangentY = frame.affine().row(1);
00128
00129 GraspableBody *object = (GraspableBody *)body1;
00130
00131
00132
00133 vec3 forceVec = normal + (tangentX*cof*edge[0])+ (tangentY*cof*edge[1]);
00134
00135
00136
00137
00138 vec3 torqueVec = ( (radius*forceVec) + normal*cof*edge[5] )/object->getMaxRadius();
00139
00140 wr->torque = torqueVec;
00141 wr->force = forceVec;
00142 }
00143
00150 void Contact::computeWrenches()
00151 {
00152 DBGP("COMPUTING WRENCHES");
00153
00154 if (wrench) delete [] wrench;
00155
00156 numFCWrenches = numFrictionEdges;
00157 wrench = new Wrench[numFCWrenches];
00158
00159 vec3 radius = loc - ((GraspableBody*)body1)->getCoG();
00160 for (int i=0;i<numFCWrenches;i++) {
00161 wrenchFromFrictionEdge( &frictionEdges[6*i], radius, &wrench[i] );
00162 }
00163 }
00164
00165
00180 int
00181 Contact::setUpFrictionEllipsoid(int numLatitudes, int numDirs[], double phi[], double eccen[])
00182 {
00183 numFrictionEdges = 0;
00184 for (int i=0;i<numLatitudes;i++) {
00185 numFrictionEdges += numDirs[i];
00186 }
00187 if (numFrictionEdges > MAX_FRICTION_EDGES) return FAILURE;
00188 prevBetas = new double[numFrictionEdges];
00189
00190 int col = 0;
00191 for (int i=0;i<numLatitudes;i++) {
00192 double cosphi = cos(phi[i]);
00193 double sinphi = sin(phi[i]);
00194 for (int j=0;j<numDirs[i];j++) {
00195 double theta = j * 2*M_PI/numDirs[i];
00196
00197 double num = cos(theta)*cosphi;
00198 double denom = num*num/(eccen[0]*eccen[0]);
00199 num = sin(theta)*cosphi;
00200 denom += num*num/(eccen[1]*eccen[1]);
00201 num = sinphi;
00202 denom += num*num/(eccen[2]*eccen[2]);
00203 denom = sqrt(denom);
00204
00205 frictionEdges[col*6] = cos(theta)*cosphi/denom;
00206 frictionEdges[col*6+1] = sin(theta)*cosphi/denom;
00207 frictionEdges[col*6+2] = 0;
00208 frictionEdges[col*6+3] = 0;
00209 frictionEdges[col*6+4] = 0;
00210 frictionEdges[col*6+5] = sinphi/denom;
00211 col++;
00212 }
00213 }
00214 return SUCCESS;
00215 }
00216
00223 Matrix
00224 Contact::frictionConstraintsMatrix() const
00225 {
00226 Matrix F(1, 1+numFrictionEdges);
00227 F.setAllElements(1.0);
00228 F.elem(0,0) = -1.0 * getCof();
00229 return F;
00230 }
00231
00237 Matrix
00238 Contact::frictionForceMatrix() const
00239 {
00240 Matrix Rfi(6, numFrictionEdges + 1);
00241
00242
00243 Rfi.elem(0,0) = Rfi.elem(1,0) = 0.0; Rfi.elem(2,0) = 1.0;
00244 Rfi.elem(3,0) = Rfi.elem(4,0) = Rfi.elem(5,0) = 0.0;
00245
00246 for(int edge=0; edge<numFrictionEdges; edge++) {
00247 for(int i=0; i<6; i++) {
00248 Rfi.elem(i, edge+1) = frictionEdges[6*edge+i];
00249 }
00250 }
00251
00252 Rfi.multiply(-1.0);
00253 return Rfi;
00254 }
00255
00259 Matrix
00260 Contact::frictionForceBlockMatrix(const std::list<Contact*> &contacts)
00261 {
00262 if (contacts.empty()) {
00263 return Matrix(0,0);
00264 }
00265 std::list<Matrix*> blocks;
00266 std::list<Contact*>::const_iterator it;
00267 for (it=contacts.begin(); it!=contacts.end(); it++) {
00268 blocks.push_back( new Matrix((*it)->frictionForceMatrix()) );
00269 }
00270 Matrix Rf(Matrix::BLOCKDIAG<Matrix>(&blocks));
00271 while (!blocks.empty()) {
00272 delete blocks.back();
00273 blocks.pop_back();
00274 }
00275 return Rf;
00276 }
00277
00282 Matrix
00283 Contact::frictionConstraintsBlockMatrix(const std::list<Contact*> &contacts)
00284 {
00285 if (contacts.empty()) {
00286 return Matrix(0,0);
00287 }
00288 std::list<Matrix*> blocks;
00289 std::list<Contact*>::const_iterator it;
00290 for (it=contacts.begin(); it!=contacts.end(); it++) {
00291 blocks.push_back( new Matrix((*it)->frictionConstraintsMatrix()) );
00292 }
00293 Matrix blockF(Matrix::BLOCKDIAG<Matrix>(&blocks));
00294 while (!blocks.empty()) {
00295 delete blocks.back();
00296 blocks.pop_back();
00297 }
00298 return blockF;
00299 }
00300
00306 Matrix
00307 Contact::normalForceSumMatrix(const std::list<Contact*> &contacts)
00308 {
00309 if (contacts.empty()) {
00310 return Matrix(0,0);
00311 }
00312 std::list<Matrix*> blocks;
00313 std::list<Contact*>::const_iterator it;
00314 for (it=contacts.begin(); it!=contacts.end(); it++) {
00315 blocks.push_back( new Matrix(Matrix::ZEROES<Matrix>(1, (*it)->numFrictionEdges+1)) );
00316 blocks.back()->elem(0,0) = 1.0;
00317 }
00318 Matrix blockF(Matrix::BLOCKROW<Matrix>(&blocks));
00319 while (!blocks.empty()) {
00320 delete blocks.back();
00321 blocks.pop_back();
00322 }
00323 return blockF;
00324 }
00325
00336 Matrix
00337 Contact::localToWorldWrenchMatrix() const
00338 {
00339 Matrix Ro(Matrix::ZEROES<Matrix>(6,6));
00340 transf contactTran = getContactFrame() * getBody1()->getTran();
00341 mat3 R; contactTran.rotation().ToRotationMatrix(R);
00342 Matrix Rot( Matrix::ROTATION(R) );
00343
00344 Ro.copySubMatrix(0, 0, Rot);
00345 Ro.copySubMatrix(3, 3, Rot);
00346
00347 vec3 worldLocation = contactTran.translation();
00348 vec3 cog = getBody2()->getTran().translation();
00349 mat3 C; C.setCrossProductMatrix(worldLocation - cog);
00350 Matrix CR(3,3);
00351 matrixMultiply(Matrix::ROTATION(C.transpose()), Rot, CR);
00352
00353
00354 double scale = 1.0;
00355 if (getBody2()->isA("GraspableBody")) {
00356 scale = scale / static_cast<GraspableBody*>(getBody2())->getMaxRadius();
00357 }
00358 CR.multiply(scale);
00359 Ro.copySubMatrix(3, 0, CR);
00360 return Ro;
00361 }
00362
00366 Matrix
00367 Contact::localToWorldWrenchBlockMatrix(const std::list<Contact*> &contacts)
00368 {
00369 if (contacts.empty()) {
00370 return Matrix(0,0);
00371 }
00372 std::list<Matrix*> blocks;
00373 std::list<Contact*>::const_iterator it;
00374 for (it=contacts.begin(); it!=contacts.end(); it++) {
00375 blocks.push_back( new Matrix((*it)->localToWorldWrenchMatrix()) );
00376 }
00377 Matrix Ro(Matrix::BLOCKDIAG<Matrix>(&blocks));
00378 while (!blocks.empty()) {
00379 delete blocks.back();
00380 blocks.pop_back();
00381 }
00382 return Ro;
00383 }
00384
00391 bool Contact::preventsMotion(const transf& motion) const
00392 {
00393 if ( (loc*motion - loc) % normal < -MACHINE_ZERO) return true;
00394 return false;
00395 }
00396
00397
00402 void
00403 Contact::updateCof()
00404 {
00405 cof = body1->getWorld()->getCOF(body1->getMaterial(),body2->getMaterial());
00406 kcof = body1->getWorld()->getKCOF(body1->getMaterial(),body2->getMaterial());
00407 body1->setContactsChanged();
00408 body2->setContactsChanged();
00409 }
00410
00417 double
00418 Contact::getCof() const
00419 {
00420 DynamicBody *db;
00421 vec3 radius,vel1(vec3::ZERO),vel2(vec3::ZERO),rotvel;
00422
00423 if (body1->isDynamic()) {
00424 db = (DynamicBody *)body1;
00425 radius = db->getTran().rotation() * (loc - db->getCoG());
00426 vel1.set(db->getVelocity()[0],db->getVelocity()[1],db->getVelocity()[2]);
00427 rotvel.set(db->getVelocity()[3],db->getVelocity()[4],db->getVelocity()[5]);
00428 vel1 += radius * rotvel;
00429 }
00430 if (body2->isDynamic()) {
00431 db = (DynamicBody *)body2;
00432 radius = db->getTran().rotation() * (mate->loc - db->getCoG());
00433 vel2.set(db->getVelocity()[0],db->getVelocity()[1],db->getVelocity()[2]);
00434 rotvel.set(db->getVelocity()[3],db->getVelocity()[4],db->getVelocity()[5]);
00435 vel2 += radius * rotvel;
00436 }
00437 if ((vel1 - vel2).len() > 1.0) {
00438 DBGP("SLIDING!");
00439 return kcof;
00440 }
00441 else return cof;
00442 }
00443
00450 void
00451 Contact::setContactForce (double *optmx)
00452 {
00453 for (int i=0;i<contactDim;i++)
00454 optimalCoeffs[i] = optmx[i];
00455 }
00456
00468 double
00469 Contact::getConstraintError()
00470 {
00471 transf cf = frame * body1->getTran();
00472 transf cf2 = mate->getContactFrame() * body2->getTran();
00473 return MAX(0.0,Contact::THRESHOLD/2.0 - (cf.translation() - cf2.translation()).len());
00474 }
00475
00481 void
00482 Contact::inherit(Contact *c)
00483 {
00484 inheritanceInfo = true;
00485 setLCPInfo( c->getPrevCn(), c->getPrevLambda(), c->getPrevBetas() );
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497 }
00498
00499 void
00500 Contact::setLCPInfo(double cn, double l, double *betas)
00501 {
00502 prevCn = cn;
00503 prevLambda = l;
00504 for (int i=0; i<numFrictionEdges; i++) {
00505 prevBetas[i] = betas[i];
00506 }
00507
00508 if (l>0) mSlip = true;
00509 else mSlip = false;
00510 }
00511
00513
00515
00516 PointContact::PointContact(Body *b1,Body *b2,position pos, vec3 norm) :
00517 Contact( b1, b2, pos, norm )
00518 {
00519
00520 if (cof == 0.0) {
00521 frictionType = FL;
00522 contactDim = 1;
00523 lmiDim = 1;
00524 } else {
00525 frictionType = PCWF;
00526 contactDim = 3;
00527 lmiDim = 3;
00528 }
00529 optimalCoeffs = new double[contactDim];
00530 setUpFrictionEdges();
00531 }
00532
00533 PointContact::~PointContact()
00534 {
00535 }
00536
00542 int PointContact::setUpFrictionEdges(bool dynamicsOn)
00543 {
00544
00545 if (dynamicsOn) {
00546
00547
00548 return 0;
00549 }
00550 double eccen[3] = {1,1,1};
00551 int numDirs[1] = {8};
00552 double phi[1] = {0.0};
00553 return setUpFrictionEllipsoid(1,numDirs,phi,eccen);
00554 }
00555
00557 SoSeparator*
00558 PointContact::getVisualIndicator()
00559 {
00560 double height,alpha,cof;
00561 SoSeparator *cne;
00562 SoTransform *tran;
00563 SoIndexedFaceSet *ifs;
00564 SoCoordinate3 *coords;
00565
00566 SbVec3f *points = new SbVec3f[numFrictionEdges+1];
00567 int32_t *cIndex = new int32_t[5*numFrictionEdges+1];
00568 int i;
00569
00570 points[0].setValue(0,0,0);
00571
00572
00573 coneMat = new SoMaterial;
00574
00575 coneMat->diffuseColor = SbColor(0.8f,0.0f,0.0f);
00576 coneMat->ambientColor = SbColor(0.2f,0.0f,0.0f);
00577 coneMat->emissiveColor = SbColor(0.4f,0.0f,0.0f);
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587 coneMat->transparency = 0.8f;
00588
00589 SoMaterial* zaxisMat = new SoMaterial;
00590 zaxisMat->diffuseColor = SbColor(0,0,0);
00591 zaxisMat->ambientColor = SbColor(0,0,0);
00592
00593 cof = getCof();
00594
00595 height = Body::CONE_HEIGHT;
00596 cne = new SoSeparator;
00597 coords = new SoCoordinate3;
00598 ifs = new SoIndexedFaceSet;
00599 tran = new SoTransform;
00600
00601 alpha = 0.0;
00602 for (i=0;i<numFrictionEdges;i++) {
00603 points[i+1].setValue(cos(alpha)*cof,sin(alpha)*cof,1.0);
00604 points[i+1] *= height;
00605 cIndex[4*i] = 0;
00606 cIndex[4*i+1] = (i+2 <= numFrictionEdges ? i+2 : 1);
00607 cIndex[4*i+2] = i+1;
00608 cIndex[4*i+3] = -1;
00609 cIndex[4*numFrictionEdges+i] = i+1;
00610 alpha += 2.0*M_PI/numFrictionEdges;
00611 }
00612 cIndex[5*numFrictionEdges] = -1;
00613
00614 coords->point.setValues(0,numFrictionEdges+1,points);
00615 ifs->coordIndex.setValues(0,5*numFrictionEdges+1,cIndex);
00616 delete [] points;
00617 delete [] cIndex;
00618
00619 getContactFrame().toSoTransform(tran);
00620
00621 SoCylinder *zaxisCyl = new SoCylinder;
00622 zaxisCyl->radius = 0.05f;
00623 zaxisCyl->height = height;
00624
00625 SoTransform *zaxisTran = new SoTransform;
00626 zaxisTran->translation.setValue(0,0,height/2.0);
00627 zaxisTran->rotation.setValue(SbVec3f(1,0,0),(float)M_PI/2.0f);
00628
00629 SoSeparator *zaxisSep = new SoSeparator;
00630 zaxisSep->addChild(zaxisTran);
00631 zaxisSep->addChild(zaxisMat);
00632 zaxisSep->addChild(zaxisCyl);
00633
00634 cne->addChild(tran);
00635 cne->addChild(zaxisSep);
00636 cne->addChild(coneMat);
00637 cne->addChild(coords);
00638 cne->addChild(ifs);
00639 return cne;
00640 }
00641
00643
00645
00650 SoftContact::SoftContact( Body *b1, Body *b2, position pos, vec3 norm,
00651 Neighborhood *bn ) : Contact(b1, b2, pos, norm)
00652 {
00653 frictionType = SFCL;
00654 contactDim = 4;
00655 lmiDim = 4;
00656 optimalCoeffs = new double[contactDim];
00657
00658 bodyNghbd = new vec3[ (int) bn->size() ];
00659 Neighborhood::iterator itr;
00660 int i = 0;
00661 vec3 temp;
00662
00663 for( itr = bn->begin(); itr != bn->end(); itr++ ) {
00664 temp.set(itr->x(), itr->y(), itr->z());
00665
00666
00667 position posit;
00668 posit = position( temp.toSbVec3f() ) * frame.inverse();
00669 bodyNghbd[i] = vec3( posit.toSbVec3f() );
00670 i++;
00671 }
00672 numPts = (int) bn->size();
00673 majorAxis = 0.0;
00674 minorAxis = 0.0;
00675 relPhi = 0.0;
00676 a = 0; b = 0; c = 0;
00677 r1 = 0; r2 = 0;
00678 r1prime = 0; r2prime = 0;
00679
00680 FitPoints();
00681
00682
00683
00684 }
00685
00686 SoftContact::~SoftContact()
00687 {
00688 delete[]bodyNghbd;
00689 }
00690
00695 int SoftContact::setUpFrictionEdges(bool dynamicsOn )
00696 {
00697 if( !getMate() ) {
00698 fprintf(stderr,"Trying to set up friction edges for a contact with no mate!!\n");
00699 return 1;
00700 }
00701
00702 DBGP("Setting up SOFT contact friction edges");
00703 double eccen[3];
00704
00705
00706 eccen[0]=1;
00707 eccen[1]=1;
00708
00709 double torquedivN;
00710
00711
00712 CalcRprimes();
00713
00714 if (!dynamicsOn) {
00715
00716 torquedivN = CalcContact_Mattress( 5 );
00717 eccen[2] = torquedivN*1000;
00718 } else {
00719
00720 double nForce = dynamicForce[2];
00721
00722
00723
00724
00725 torquedivN = CalcContact_Mattress( nForce );
00726 eccen[2] = torquedivN*1000;
00727 }
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 int numDirs[5] = {1,5,8,5,1};
00746 double phi[5] = {M_PI_2, M_PI_2*0.50, 0.0, -M_PI_2*0.50, -M_PI_2};
00747 return Contact::setUpFrictionEllipsoid( 5, numDirs, phi, eccen );
00748 }
00749
00756 void SoftContact::computeWrenches()
00757 {
00758 bool approxPlaneMoments = false;
00759
00760 if (!approxPlaneMoments) {
00761 Contact::computeWrenches();
00762 return;
00763 }
00764
00765
00766
00767
00768
00769
00770
00771
00772
00773
00774
00775 if (wrench) delete [] wrench;
00776 numFCWrenches = 4 * numFrictionEdges;
00777 wrench = new Wrench[numFCWrenches];
00778
00779 vec3 tangentX = frame.affine().row(0);
00780 vec3 tangentY = frame.affine().row(1);
00781
00782 vec3 radius;
00783 vec3 baseRadius = loc - ((GraspableBody*)body1)->getCoG();
00784
00785 float a,b;
00786 a = b = 1000 * sqrt(majorAxis * minorAxis);
00787 a = b = 1000 * std::max(majorAxis, minorAxis);
00788
00789 DBGA("Soft contact size: " << a);
00790
00791 for (int i=0;i<numFrictionEdges;i++) {
00792 radius = baseRadius + ( a * tangentX );
00793 wrenchFromFrictionEdge( &frictionEdges[6*i], radius, &wrench[4*i+0] );
00794
00795 radius = baseRadius - ( a * tangentX );
00796 wrenchFromFrictionEdge( &frictionEdges[6*i], radius, &wrench[4*i+1] );
00797
00798 radius = baseRadius + ( b * tangentY );
00799 wrenchFromFrictionEdge( &frictionEdges[6*i], radius, &wrench[4*i+2] );
00800
00801 radius = baseRadius - ( b * tangentY );
00802 wrenchFromFrictionEdge( &frictionEdges[6*i], radius, &wrench[4*i+3] );
00803 }
00804 DBGA("Soft wrenches computed");
00805 }
00806
00811 void SoftContact::FitPoints( )
00812 {
00813 double *coeffs = new double [3];
00814 FitParaboloid( bodyNghbd, numPts, coeffs );
00815
00816 a = coeffs[0];
00817 b = coeffs[1];
00818 c = coeffs[2];
00819
00820 RotateParaboloid( coeffs, &r1, &r2, &fitRot, &fitRotAngle );
00821 DBGP(getBody1()->getName().latin1() << ": " << "a=" << a << " b=" << b << " c=" <<c);
00822 DBGP("r1=" << r1 << " r2=" <<r2);
00823 }
00824
00828 int SoftContact::CalcRelPhi( )
00829 {
00830 vec3 temp, t;
00831 vec3 R11, R12;
00832
00833 temp.set( 1, 0 , 0);
00834 t = fitRot * temp;
00835 R11 = t * frame;
00836 R11 = R11 * body1->getTran();
00837
00838 temp.set( 1, 0 , 0);
00839 t = ((SoftContact *)getMate())->fitRot * temp;
00840 R12 = t * ((SoftContact *)getMate())->frame;
00841 R12 = R12 * body2->getTran();
00842
00843 relPhi = acos( (R11%R12)/(R11.len()*R12.len()) );
00844 ((SoftContact *)getMate())->relPhi = relPhi ;
00845
00846
00847 return 0;
00848 }
00849
00854 int SoftContact::CalcRprimes()
00855 {
00856 if( !(getMate()) ) {
00857 DBGA("Contact doesn't have mate, not calculating curvature...");
00858 return 1;
00859 }
00860
00861 SoftContact *m = (SoftContact *)getMate();
00862
00863 CalcRelPhi();
00864
00865 DBGP("Body 1" << getBody1()->getName().latin1() << " Body 2 " << m->getBody1()->getName().latin1());
00866
00867
00868
00869
00870 double x,y,w,z;
00871 if( r1 < 0.0 )
00872 w = 0.0;
00873 else
00874 w = 1/r1;
00875
00876 if( r2 < 0.0 )
00877 x = 0.0;
00878 else
00879 x = 1/r2;
00880
00881 if( m->r1 < 0.0 )
00882 y = 0.0;
00883 else
00884 y = 1/m->r1;
00885
00886 if( m->r2 < 0.0 )
00887 z = 0.0;
00888 else
00889 z = 1/m->r2;
00890
00891 DBGP("x: " << x << " y: " << y << " w: " << w << " z: " << z);
00892
00893 double ApB = 0.5*( w + x + y + z );
00894
00895 DBGP("Apb: " << ApB);
00896
00897 double AmB = 0.5*sqrt( (w - x)*(w - x) + (y - z)*(y - z) +
00898 2*cos(2*relPhi)*(w - x)*(y - z) );
00899
00900 DBGP("Amb: " << AmB << " relPhi: " << relPhi);
00901
00902 if( AmB > ApB ) {
00903 printf( "Invalid relative curvature, ending calculation...\n" );
00904 return 1;
00905 }
00906
00907
00908 if (ApB + AmB != 0)
00909 r1prime = 1/( ApB + AmB );
00910 else
00911 r1prime = -1.0;
00912
00913 if( ApB == AmB)
00914 r2prime = -1.0;
00915 else
00916 r2prime = 1/(ApB - AmB );
00917
00918 m->r1prime = r1prime;
00919 m->r2prime = r2prime;
00920
00921
00922
00923 return 0;
00924 }
00925
00932 double SoftContact::CalcContact_Mattress( double nForce )
00933 {
00934 if (r1prime < 0) {
00935 DBGA("Degenerate soft contact");
00936 r1prime = 20;
00937 }
00938 if (r2prime < 0) {
00939 DBGA("Degenerate soft contact");
00940 r2prime = 20;
00941 }
00942
00943
00944
00945 double h = 0.003;
00946 double delta = sqrt( nForce*h/(MAX(body1->getYoungs(), body2->getYoungs())
00947 * M_PI * sqrt(r1prime*0.001*r2prime*0.001)) );
00948
00949 majorAxis = sqrt( 2*delta*r1prime*0.001 );
00950 minorAxis = sqrt( 2*delta*r2prime*0.001 );
00951 DBGP("Axes: " << majorAxis << " " << minorAxis);
00952
00953
00954
00955 SoftContact *m = (SoftContact *)getMate();
00956 m->majorAxis = majorAxis;
00957 m->minorAxis = minorAxis;
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968 return 8*sqrt( majorAxis*minorAxis )/15;
00969 }
00970
00975 SoSeparator* SoftContact::getVisualIndicator()
00976 {
00977 double height,radius;
00978 SoSeparator *cne;
00979 SoTransform *tran;
00980 SoCoordinate3 *coords;
00981 cne = new SoSeparator;
00982
00983 int sampling_n = 10, sampling_m = 10;
00984
00985
00986
00987
00988 double sampleSize_n = 0.7;
00989 double sampleSize_m = 0.7;
00990
00991
00992 DBGP("Major " << majorAxis << " minor " << minorAxis);
00993
00994
00995 SbVec3f *points = new SbVec3f[(2*sampling_n + 1)*(2*sampling_m + 1) ];
00996
00997 coneMat = new SoMaterial;
00998 coneMat->diffuseColor = SbColor(0.8f,0.0f,0.0f);
00999 coneMat->ambientColor = SbColor(0.2f,0.0f,0.0f);
01000 coneMat->emissiveColor = SbColor(0.4f,0.0f,0.0f);
01001 coneMat->transparency = 0.8f;
01002
01003 SoMaterial* zaxisMat = new SoMaterial;
01004 zaxisMat->diffuseColor = SbColor(0,0,0);
01005 zaxisMat->ambientColor = SbColor(0,0,0);
01006
01007 radius = Body::CONE_HEIGHT / 5;
01008 height = Body::CONE_HEIGHT;
01009
01010 tran = new SoTransform;
01011 getContactFrame().toSoTransform(tran);
01012
01013 SoCylinder *zaxisCyl = new SoCylinder;
01014 zaxisCyl->radius = 0.05f;
01015 zaxisCyl->height = 0.2 * height;
01016
01017 SoTransform *zaxisTran = new SoTransform;
01018 zaxisTran->translation.setValue(0,0,0.2 * height/2.0);
01019 zaxisTran->rotation.setValue(SbVec3f(1,0,0),(float)M_PI/2.0f);
01020
01021 SoSeparator *zaxisSep = new SoSeparator;
01022 zaxisSep->addChild(zaxisTran);
01023 zaxisSep->addChild(zaxisMat);
01024 zaxisSep->addChild(zaxisCyl);
01025
01026 int n_squares = 2 * sampling_n * 2 *sampling_m;
01027 int32_t *cIndex = new int32_t[5*n_squares];
01028
01029 int count = 0;
01030 int count_sq = 0;
01031 for( int i = -sampling_n; i <= sampling_n; i++ )
01032 {
01033 for( int j = -sampling_m; j <= sampling_m; j++ )
01034 {
01035 double x = i*sampleSize_n;
01036 double y = j*sampleSize_m;
01037
01038 double z = 0;
01039 if (r1 > 0) z+= x*x*1.0/(2*r1);
01040 if (r2 > 0) z+= y*y*1.0/(2*r2);
01041 points[ count ].setValue( x, y, z );
01042 if (x>0 && y == 0){
01043 points[count].setValue(x,y,z+0.4);
01044 }
01045
01046 if ( i > -sampling_n && j > -sampling_m)
01047 {
01048 cIndex[5*count_sq + 0] = count - (2*sampling_m + 1);
01049 cIndex[5*count_sq + 1] = count - (2*sampling_m + 1) - 1;
01050 cIndex[5*count_sq + 2] = count - 1;
01051 cIndex[5*count_sq + 3] = count;
01052 cIndex[5*count_sq + 4] = -1;
01053 count_sq++;
01054 }
01055 count++;
01056 }
01057 }
01058 if (count != (2*sampling_n + 1)*(2*sampling_m + 1) || count_sq != n_squares)
01059 exit(0);
01060
01061 coords = new SoCoordinate3;
01062 coords->point.setValues( 0, count, points );
01063
01064 SoIndexedFaceSet *ifs = new SoIndexedFaceSet;
01065 ifs->coordIndex.setValues(0, 5*n_squares, cIndex);
01066
01067
01068 cne->addChild(tran);
01069
01070
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087 cne->addChild(zaxisSep);
01088
01089
01090
01091 SoTransform* axisAlignTran = new SoTransform;
01092 axisAlignTran->rotation.setValue(SbVec3f(0,0,1), -fitRotAngle);
01093 cne->addChild(axisAlignTran);
01094
01095 cne->addChild(coneMat);
01096 cne->addChild(coords);
01097 cne->addChild(ifs);
01098
01099
01100
01101
01102
01103 SoTransform* phiAlignTran = new SoTransform;
01104 phiAlignTran->rotation.setValue(SbVec3f(0,0,1), relPhi);
01105 cne->addChild(phiAlignTran);
01106
01107 SoCylinder *xaxisCyl = new SoCylinder;
01108 xaxisCyl->radius = 0.05f;
01109 xaxisCyl->height = height / 2.0;
01110
01111 SoTransform *xaxisTran = new SoTransform;
01112 xaxisTran->translation.setValue(height/4.0, 0.0, 0.0);
01113 xaxisTran->rotation.setValue(SbVec3f(0,0,1),-(float)M_PI/2.0f);
01114
01115 SoSeparator *xaxisSep = new SoSeparator;
01116 xaxisSep->addChild(xaxisTran);
01117 xaxisSep->addChild(zaxisMat);
01118 xaxisSep->addChild(xaxisCyl);
01119
01120
01121 return cne;
01122 }
01123
01125
01127
01132 void
01133 VirtualContact::init()
01134 {
01135 mFingerNum = -2;
01136 mLinkNum = 0;
01137 mZaxisMat = NULL;
01138 mWorldInd = NULL;
01139 mate = this;
01140 body1 = NULL;
01141 body2 = NULL;
01142 }
01143
01147 VirtualContact::VirtualContact() : Contact()
01148 {
01149 init();
01150 }
01151
01157 VirtualContact::VirtualContact(const VirtualContact *original) : Contact()
01158 {
01159 init();
01160 mFingerNum = original->mFingerNum;
01161 mLinkNum = original->mLinkNum;
01162
01163
01164 numFrictionEdges = original->numFrictionEdges;
01165 memcpy( frictionEdges, original->frictionEdges, 6 * numFrictionEdges * sizeof(double) );
01166
01167 loc = original->loc;
01168 frame = original->frame;
01169 normal = original->normal;
01170 cof = original->cof;
01171 body1 = original->body1;
01172 body2 = original->body2;
01173 }
01174
01179 VirtualContact::VirtualContact(int f, int l, Contact *original) : Contact()
01180 {
01181 init();
01182 mFingerNum = f;
01183 mLinkNum = l;
01184
01185 numFrictionEdges = original->numFrictionEdges;
01186 memcpy( frictionEdges, original->frictionEdges, 6 * numFrictionEdges * sizeof(double) );
01187 cof = original->cof;
01188
01189 loc = original->loc;
01190 frame = original->frame;
01191
01192 Quaternion q(3.14159, vec3(1,0,0));
01193 transf newRot(q, vec3(0,0,0) );
01194 frame = newRot * frame;
01195 normal = -1 * original->normal;
01196 body1 = original->body1;
01197 body2 = original->body2;
01198 }
01199
01203 VirtualContact::~VirtualContact()
01204 {
01205 mate = NULL;
01206 }
01207
01208 position
01209 VirtualContact::getWorldLocation()
01210 {
01211 return loc * body1->getTran();
01212 }
01213
01214 vec3
01215 VirtualContact::getWorldNormal()
01216 {
01217 return normal * body1->getTran();
01218 }
01219
01227 int
01228 VirtualContact::setUpFrictionEdges(bool dynamicsOn)
01229 {
01230 (void*)&dynamicsOn;
01231 return 1;
01232 }
01233
01249 void
01250 VirtualContact::computeWrenches(bool useObjectData, bool simplify)
01251 {
01252 int i;
01253
01254 vec3 radius, forceVec,torqueVec,tangentX,tangentY;
01255
01256
01257 position worldLoc;
01258 vec3 worldNormal;
01259
01260 if (!useObjectData) {
01261 worldLoc = getWorldLocation();
01262 worldNormal = getWorldNormal();
01263 transf worldFrame = frame * body1->getTran();
01264 tangentX = worldFrame.affine().row(0);
01265 tangentY = worldFrame.affine().row(1);
01266 } else {
01267
01268 worldLoc = getWorldLocation();
01269 worldNormal = getWorldNormal();
01270 tangentX = vec3(0,1,0) * worldNormal;
01271 tangentX = normalise(tangentX);
01272 tangentY = worldNormal * tangentX;
01273 }
01274
01275
01276 radius = worldLoc - mCenter;
01277 if (wrench) delete [] wrench;
01278
01279 if (simplify) {
01280 numFCWrenches = 1;
01281 wrench = new Wrench[1];
01282 wrench[0].force = worldNormal;
01283 wrench[0].torque = (radius*worldNormal) / mMaxRadius;
01284 return;
01285 }
01286
01287 numFCWrenches = numFrictionEdges;
01288 wrench = new Wrench[numFrictionEdges];
01289
01290
01291 for (i=0;i<numFCWrenches;i++) {
01292 forceVec = worldNormal + (tangentX*cof*frictionEdges[6*i])+ (tangentY*cof*frictionEdges[6*i+1]);
01293
01294
01295
01296 wrench[i].force = forceVec;
01297
01298 wrench[i].torque = ( (radius*forceVec) + worldNormal*cof*frictionEdges[6*i+5] )/mMaxRadius;
01299
01300
01301
01302 }
01303 }
01304
01312 void
01313 VirtualContact::scaleWrenches(double factor)
01314 {
01315 int i;
01316 for (i=0; i<numFCWrenches; i++) {
01317 wrench[i].force = factor * wrench[i].force;
01318 wrench[i].torque = factor * wrench[i].torque;
01319 }
01320 }
01321
01329 void
01330 VirtualContact::getWorldIndicator(bool useObjectData)
01331 {
01332 vec3 forceVec;
01333 position worldLoc;
01334
01335 if (!useObjectData) {
01336 worldLoc = getWorldLocation();
01337 } else {
01338 vec3 objDist;
01339 getObjectDistanceAndNormal(body2, &objDist, NULL);
01340 worldLoc = getWorldLocation() + objDist;
01341 }
01342
01343 SoTransform* tran = new SoTransform;
01344 SbMatrix tr;
01345 tr.setTranslate( worldLoc.toSbVec3f() );
01346 tran->setMatrix( tr );
01347
01348 SbVec3f *points = (SbVec3f*)calloc(numFCWrenches+1, sizeof(SbVec3f) );
01349 int32_t *cIndex = (int32_t*)calloc(4*numFCWrenches, sizeof(int32_t) );
01350
01351 points[0].setValue(0,0,0);
01352
01353 for (int i=0;i<numFCWrenches;i++) {
01354
01355 forceVec = wrench[i].force;
01356 forceVec = Body::CONE_HEIGHT * forceVec;
01357 points[i+1].setValue( forceVec.x(), forceVec.y(), forceVec.z() );
01358 cIndex[4*i] = 0;
01359 cIndex[4*i+1] = i + 2;
01360 if ( i == numFCWrenches-1) cIndex[4*i+1] = 1;
01361 cIndex[4*i+2] = i + 1;
01362 cIndex[4*i+3] = -1;
01363 }
01364
01365 SoCoordinate3* coords = new SoCoordinate3;
01366 SoIndexedFaceSet* ifs = new SoIndexedFaceSet;
01367 coords->point.setValues(0,numFCWrenches+1,points);
01368 ifs->coordIndex.setValues(0,4*numFCWrenches,cIndex);
01369 free(points);
01370 free(cIndex);
01371
01372 SoMaterial *coneMat = new SoMaterial;
01373 coneMat->diffuseColor = SbColor(0.0f,0.0f,0.8f);
01374 coneMat->ambientColor = SbColor(0.0f,0.0f,0.2f);
01375 coneMat->emissiveColor = SbColor(0.0f,0.0f,0.4f);
01376
01377 if (mWorldInd) {
01378 body1->getWorld()->getIVRoot()->removeChild(mWorldInd);
01379 }
01380
01381 mWorldInd = new SoSeparator;
01382 mWorldInd->addChild(tran);
01383 mWorldInd->addChild(coneMat);
01384 mWorldInd->addChild(coords);
01385 mWorldInd->addChild(ifs);
01386 body1->getWorld()->getIVRoot()->addChild(mWorldInd);
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399 }
01400
01401 SoSeparator*
01402 VirtualContact::getVisualIndicator()
01403 {
01404 SoTransform *tran;
01405
01406
01407 if (!mZaxisMat) {
01408 mZaxisMat = new SoMaterial;
01409 mZaxisMat->ref();
01410 }
01411 mZaxisMat->diffuseColor = SbColor(0.8f,0,0);
01412 mZaxisMat->ambientColor = SbColor(0.8f,0,0);
01413
01414 tran = new SoTransform;
01415 getContactFrame().toSoTransform(tran);
01416
01417 SoCylinder *zaxisCyl = new SoCylinder;
01418 zaxisCyl->radius = 0.2f;
01419 zaxisCyl->height = Body::CONE_HEIGHT;
01420
01421 SoSphere *zaxisSphere = new SoSphere;
01422 zaxisSphere->radius = 3.0f;
01423
01424 SoTransform *zaxisTran = new SoTransform;
01425 zaxisTran->translation.setValue(0,0,Body::CONE_HEIGHT/2.0);
01426
01427 zaxisTran->rotation.setValue(SbVec3f(1,0,0),(float)M_PI/2.0f);
01428
01429 SoSeparator *zaxisSep = new SoSeparator;
01430 zaxisSep->addChild(zaxisTran);
01431 zaxisSep->addChild(mZaxisMat);
01432 zaxisSep->addChild(zaxisCyl);
01433
01434
01435 SoSeparator* cne = new SoSeparator;
01436 cne->addChild(tran);
01437 cne->addChild(zaxisSep);
01438 return cne;
01439 }
01440
01444 void
01445 VirtualContact::mark(bool m)
01446 {
01447 if (!mZaxisMat) return;
01448 if (m) {
01449 mZaxisMat->diffuseColor = SbColor(0,0,0.8f);
01450 mZaxisMat->ambientColor = SbColor(0,0,0.8f);
01451 } else {
01452 mZaxisMat->diffuseColor = SbColor(0.8f,0,0);
01453 mZaxisMat->ambientColor = SbColor(0.8f,0,0);
01454 }
01455 }
01456
01461 void
01462 VirtualContact::writeToFile(FILE *fp)
01463 {
01464
01465 fprintf(fp,"%d %d\n",mFingerNum, mLinkNum);
01466
01467
01468 fprintf(fp,"%d\n",numFrictionEdges);
01469
01470
01471 for (int i=0; i<numFrictionEdges; i++) {
01472 for (int j=0; j<6; j++)
01473 fprintf(fp,"%f ",frictionEdges[6*i+j]);
01474 fprintf(fp,"\n");
01475 }
01476
01477
01478 fprintf(fp,"%f %f %f\n",loc.x(), loc.y(), loc.z());
01479
01480
01481 Quaternion q = frame.rotation();
01482 vec3 t = frame.translation();
01483 fprintf(fp,"%f %f %f %f\n",q.w,q.x,q.y,q.z);
01484 fprintf(fp,"%f %f %f\n",t.x(), t.y(), t.z());
01485
01486
01487 fprintf(fp,"%f %f %f\n",normal.x(), normal.y(), normal.z());
01488
01489
01490 fprintf(fp,"%f\n",cof);
01491 }
01492
01496 void
01497 VirtualContact::readFromFile(FILE *fp)
01498 {
01499 float v,x,y,z;
01500
01501
01502 fscanf(fp,"%d %d",&mFingerNum, &mLinkNum);
01503
01504
01505 fscanf(fp,"%d",&numFrictionEdges);
01506
01507
01508 for (int i=0; i<numFrictionEdges; i++) {
01509 for (int j=0; j<6; j++) {
01510 fscanf(fp,"%f",&v);
01511 frictionEdges[6*i+j] = v;
01512 }
01513 }
01514
01515
01516 fscanf(fp,"%f %f %f",&x, &y, &z);
01517 loc = position(x,y,z);
01518
01519
01520 Quaternion q;
01521 vec3 t;
01522 fscanf(fp,"%f %f %f %f",&v,&x,&y,&z);
01523 q.set(v,x,y,z);
01524 fscanf(fp,"%f %f %f",&x, &y, &z);
01525 t.set(x,y,z);
01526 frame.set(q,t);
01527
01528
01529 fscanf(fp,"%f %f %f",&x, &y, &z);
01530 normal.set(x,y,z);
01531
01532
01533 fscanf(fp,"%f",&v);
01534 cof = v;
01535 }
01536
01541 void
01542 VirtualContact::getObjectDistanceAndNormal(Body *body, vec3 *objDistance, vec3 *objNormal)
01543 {
01544 position loc = getWorldLocation();
01545 *objDistance = body->getWorld()->pointDistanceToBody(loc, body, objNormal);
01546 }
01547
01548
01549 VirtualContactOnObject::VirtualContactOnObject()
01550 {
01551 wrench = NULL;
01552 body2 = NULL;
01553 mate = this;
01554 prevBetas = NULL;
01555 }
01556
01557 VirtualContactOnObject::~VirtualContactOnObject()
01558 {
01559 }
01560
01561 void
01562 VirtualContactOnObject::readFromFile(FILE *fp)
01563 {
01564 float w,x,y,z;
01565
01566
01567 fscanf(fp,"%d",&numFrictionEdges);
01568
01569
01570 for (int i=0; i<numFrictionEdges; i++) {
01571 for (int j=0; j<6; j++) {
01572 fscanf(fp,"%f",&w);
01573 frictionEdges[6*i+j] = w;
01574 }
01575 }
01576 fprintf(stderr,"\n<frictionEdges scanned successfully>");
01577
01578
01579
01580 Quaternion q;
01581 vec3 t;
01582 fscanf(fp,"%f %f %f %f",&w,&x,&y,&z);
01583 q.set(w,x,y,z);
01584 fscanf(fp,"%f %f %f",&x, &y, &z);
01585 t.set(x,y,z);
01586 loc = position(x,y,z);
01587 frame.set(q,t);
01588
01589
01590 fscanf(fp,"%f %f %f",&x, &y, &z);
01591 normal.set(x,y,z);
01592
01593
01594 fscanf(fp,"%f",&w);
01595 cof = w;
01596 }
01597
01598 #ifdef ARIZONA_PROJECT_ENABLED
01599 void
01600 VirtualContactOnObject::readFromRawData(ArizonaRawExp* are, QString file, int index, bool flipNormal)
01601 {
01602
01603 float v;
01604 FILE *fp = fopen(file.latin1(), "r");
01605 if (!fp) {
01606 fprintf(stderr,"Could not open filename %s\n",file.latin1());
01607 return;
01608 }
01609
01610
01611 fscanf(fp,"%d",&numFrictionEdges);
01612
01613
01614 for (int i=0; i<numFrictionEdges; i++) {
01615 for (int j=0; j<6; j++) {
01616 fscanf(fp,"%f",&v);
01617 frictionEdges[6*i+j] = v;
01618 }
01619 }
01620
01621 Quaternion q;
01622 vec3 t;
01623 q = are->getQuaternion(index);
01624 t = are->getContact(index);
01625 loc = position(t.x(),t.y(),t.z());
01626 frame.set(q,t);
01627
01628
01629 normal = are->getNormal(index);
01630 if(flipNormal){
01631 std::cout << "flipped normal" << std::endl;
01632 normal = - normal;
01633 }
01634
01635
01636 cof = 0.5;
01637
01638 fclose(fp);
01639
01640 }
01641 #endif
01642
01643 void
01644 VirtualContactOnObject::writeToFile(FILE *fp){
01645
01646 fprintf(fp,"%d\n",numFrictionEdges);
01647
01648
01649 for (int i=0; i<numFrictionEdges; i++) {
01650 for (int j=0; j<6; j++)
01651 fprintf(fp,"%f ",frictionEdges[6*i+j]);
01652 fprintf(fp,"\n");
01653 }
01654
01655
01656 Quaternion q = frame.rotation();
01657 vec3 t = frame.translation();
01658 fprintf(fp,"%f %f %f %f\n",q.w,q.x,q.y,q.z);
01659 fprintf(fp,"%f %f %f\n",t.x(), t.y(), t.z());
01660
01661
01662 fprintf(fp,"%f %f %f\n",normal.x(), normal.y(), normal.z());
01663
01664
01665 fprintf(fp,"%f\n",cof);
01666 }