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 "humanHand.h"
00027
00028 #include <QFile>
00029 #include <QTextStream>
00030 #include <list>
00031
00032 #include <Inventor/nodes/SoSphere.h>
00033 #include <Inventor/nodes/SoCylinder.h>
00034 #include <Inventor/nodes/SoMaterial.h>
00035 #include <Inventor/nodes/SoDrawStyle.h>
00036
00037 #include "SoArrow.h"
00038
00039 #include "grasp.h"
00040 #include "matrix.h"
00041 #include "tinyxml.h"
00042 #include "debug.h"
00043 #include "world.h"
00044
00045 #define WRAPPER_TOLERANCE 0.995
00046
00047
00048 #include "profiling.h"
00049
00050
00051
00052
00053 const double TendonInsertionPoint::INSERTION_POINT_RADIUS = 0.45;
00054 const double TendonInsertionPoint::CONNECTOR_RADIUS = 0.24;
00055
00059 double pointLineDistance(vec3 p0, vec3 l1, vec3 l2)
00060 {
00061 vec3 x01 = p0 - l1;
00062 vec3 x02 = p0 - l2;
00063 vec3 x21 = l2 - l1;
00064 return (x01 * x02).len() / x21.len();
00065 }
00066
00067 PROF_DECLARE(ROTATE_SO_TRANSFORM);
00068 void rotateSoTransform(SoTransform *tran, vec3 axis, double angle)
00069 {
00070 PROF_TIMER_FUNC(ROTATE_SO_TRANSFORM);
00071 transf tr(tran);
00072 Quaternion quat(angle, axis);
00073 transf rot(quat, vec3(0,0,0));
00074 tr = rot * tr;
00075 tr.toSoTransform(tran);
00076 }
00077
00078 TendonInsertionPoint::TendonInsertionPoint(Tendon *myOwner, int chain, int link, vec3 point, double mu, bool isPerm) :
00079 mAttachPoint(point),
00080 mPermanent(isPerm),
00081 mAttachChainNr(chain),
00082 mAttachLinkNr(link),
00083 mMu(mu),
00084 mOwner(myOwner)
00085 {
00086 createInsertionGeometry();
00087 createConnectorGeometry();
00088 }
00089
00090 void TendonInsertionPoint::setAttachPoint(vec3 attachPoint)
00091 {
00092 mAttachPoint = attachPoint;
00093 mIVInsertionTran->translation.setValue(mAttachPoint.x() , mAttachPoint.y() , mAttachPoint.z() );
00094 }
00095
00101 Link* TendonInsertionPoint::getAttachedLink()
00102 {
00103 if (mAttachChainNr == -1 || mAttachLinkNr == -1) {
00104
00105 return mOwner->getRobot()->getBase();
00106 } else {
00107 return mOwner->getRobot()->getChain(mAttachChainNr)->getLink(mAttachLinkNr);
00108 }
00109 }
00110
00111
00112 SbVec3f TendonInsertionPoint::getWorldPosition()
00113 {
00114
00115 position worldPos;
00116 worldPos = position(mAttachPoint.toSbVec3f()) * ( getAttachedLink()->getTran() );
00117 return worldPos.toSbVec3f();
00118 }
00119
00120 void TendonInsertionPoint::createInsertionGeometry()
00121 {
00122 mIVInsertion = new SoSeparator;
00123 mIVInsertionMaterial = new SoMaterial;
00124 mIVInsertionTran = new SoTransform;
00125 mIVInsertionGeom = new SoSphere;
00126
00127
00128
00129
00130
00131 mIVInsertion->addChild(getAttachedLink()->getIVTran());
00132
00133
00134 mIVInsertionTran->translation.setValue(mAttachPoint.x() , mAttachPoint.y() , mAttachPoint.z() );
00135 mIVInsertion->addChild(mIVInsertionTran);
00136
00137 if ( isPermanent() )
00138 {
00139 mIVInsertionMaterial->diffuseColor.setValue( (float)0.7 , (float)0.2 , (float)0.2);
00140 mIVInsertionGeom->radius=(float)INSERTION_POINT_RADIUS;
00141 }
00142 else
00143 {
00144 if (mOwner->isSelected())
00145 mIVInsertionMaterial->diffuseColor.setValue( (float)1.0 , (float)0.5 , (float)0.5);
00146 else
00147 mIVInsertionMaterial->diffuseColor.setValue( (float)0.5 , (float)0.5 , (float)0.5);
00148 mIVInsertionGeom->radius=(float)CONNECTOR_RADIUS;
00149 }
00150 mIVInsertion->addChild(mIVInsertionMaterial);
00151 mIVInsertion->addChild(mIVInsertionGeom);
00152 }
00153
00154 void TendonInsertionPoint::createConnectorGeometry()
00155 {
00156 mIVConnector = new SoSeparator;
00157 mIVConnectorTran = new SoTransform;
00158 mIVConnectorMaterial = new SoMaterial;
00159 mIVConnectorGeom = new SoCylinder;
00160
00161 if ( mOwner->isSelected() )
00162 mIVConnectorMaterial->diffuseColor.setValue(1.0 , 0.5 , 0.5);
00163 else
00164 mIVConnectorMaterial->diffuseColor.setValue(0.5 , 0.5 , 0.5);
00165
00166 mIVConnector->addChild( mIVConnectorTran );
00167 mIVConnector->addChild( mIVConnectorMaterial );
00168 mIVConnector->addChild( mIVConnectorGeom);
00169 }
00170
00171 void TendonInsertionPoint::removeAllGeometry()
00172 {
00173 mIVConnector->removeAllChildren();
00174 mIVInsertion->removeAllChildren();
00175 }
00176
00177 Tendon::Tendon(Robot *myOwner)
00178 {
00179 mOwner = myOwner;
00180 mActiveForce = 0;
00181 mIVRoot = new SoSeparator;
00182 mIVVisibleToggle = new SoDrawStyle();
00183 mIVVisibleToggle->style = SoDrawStyle::FILLED;
00184 mIVRoot->addChild(mIVVisibleToggle);
00185 mTendonName = "unnamed";
00186 mVisible = true;
00187 mForcesVisible = false;
00188 mSelected = false;
00189 mRestLength = 0;
00190 mCurrentLength = 0;
00191 mDefaultRestLength = -1;
00192 mPreTensionLength = -1;
00193 mApplyPassiveForce = true;
00194 mPassiveForce = 0;
00195 mK = 0.0;
00196
00197 mIVForceIndRoot = new SoSeparator;
00198 mIVRoot->addChild(mIVForceIndRoot);
00199 mIVForceIndToggle = new SoDrawStyle;
00200 mIVForceIndToggle->style = SoDrawStyle::INVISIBLE;
00201 mIVForceIndRoot->addChild(mIVForceIndToggle);
00202 mIVForceIndMaterial = new SoMaterial;
00203 mIVForceIndMaterial->diffuseColor.setValue(0.2f , 0.4f , 0.4f);
00204 mIVForceIndRoot->addChild(mIVForceIndMaterial);
00205 mIVForceIndicators = new SoSeparator;
00206 mIVForceIndRoot->addChild(mIVForceIndicators);
00207 }
00208
00209 void Tendon::setActiveForce(float f)
00210 {
00211 if (f>=0) mActiveForce = f;
00212 else mActiveForce = 0;
00213 updateInsertionForces();
00214 if (mVisible && mForcesVisible) updateForceIndicators();
00215 }
00216 void Tendon::setPassiveForce(float f)
00217 {
00218 if (f>=0) mPassiveForce = f;
00219 else mPassiveForce = 0;
00220 updateInsertionForces();
00221 if (mVisible && mForcesVisible) updateForceIndicators();
00222 }
00223
00224 PROF_DECLARE(TENDON_REMOVE_TEMP_INSERTION_POINTS);
00225 void Tendon::removeTemporaryInsertionPoints()
00226 {
00227 PROF_TIMER_FUNC(TENDON_REMOVE_TEMP_INSERTION_POINTS);
00228 std::list<TendonInsertionPoint*>::iterator it = mInsPointList.begin();
00229 while (it != mInsPointList.end())
00230 {
00231 if ( (*it)->isPermanent() ) it++;
00232 else it = removeInsertionPoint(it);
00233 }
00234 }
00235
00236 bool Tendon::insPointInsideWrapper()
00237 {
00238 int i=0;
00239 for (std::list<TendonInsertionPoint*>::iterator insPt = mInsPointList.begin();
00240 insPt != mInsPointList.end();
00241 insPt++)
00242 {
00243 if (!(*insPt)->isPermanent()) continue;
00244 vec3 p0((*insPt)->getWorldPosition());
00245 for (int j=0; j< ((HumanHand*)getRobot())->getNumTendonWrappers(); j++)
00246 {
00247 if ( ((HumanHand*)getRobot())->getTendonWrapper(j)->isExempt(mTendonName) ) continue;
00248 TendonWrapper *wrapper = ((HumanHand*)getRobot())->getTendonWrapper(j);
00249
00250 vec3 l1 = wrapper->location;
00251 vec3 l2 = l1 + wrapper->orientation;
00252
00253 Link* link = wrapper->getAttachedLink();
00254 position tmpPos = position (l1.toSbVec3f()) * ( link->getTran());
00255 l1 = vec3 ( tmpPos.toSbVec3f() );
00256 tmpPos = position (l2.toSbVec3f()) * ( link->getTran());
00257 l2 = vec3 ( tmpPos.toSbVec3f() );
00258
00259 double d = pointLineDistance(p0, l1, l2);
00260 if (d < wrapper->radius)
00261 {
00262
00263 return true;
00264 }
00265 }
00266 i++;
00267 }
00268 return false;
00269 }
00270
00271 double Tendon::minInsPointDistance()
00272 {
00273 double minDist = std::numeric_limits<double>::max();
00274 for (std::list<TendonInsertionPoint*>::iterator thisInsPt = mInsPointList.begin();
00275 thisInsPt != mInsPointList.end();
00276 thisInsPt++)
00277 {
00278 if (!(*thisInsPt)->isPermanent()) continue;
00279
00280 std::list<TendonInsertionPoint*>::iterator nextInsPt = thisInsPt;
00281 nextInsPt++;
00282 while( nextInsPt!=mInsPointList.end() && !(*nextInsPt)->isPermanent() ) nextInsPt++;
00283 if (nextInsPt == mInsPointList.end()) continue;
00284
00285 minDist = std::min( minDist, ( vec3((*thisInsPt)->getWorldPosition()) -
00286 vec3((*nextInsPt)->getWorldPosition()) ).len() );
00287 }
00288 return minDist;
00289 }
00290
00291 inline bool wrapperIntersection(TendonWrapper *wrapper, QString tendonName,
00292 vec3 pPrev, vec3 pNext, position &newInsPtPos)
00293 {
00294 if ( wrapper->isExempt(tendonName) ) return false;
00295
00296 vec3 P3 = wrapper->location;
00297 vec3 P4 = P3 + 0.5 * wrapper->length * wrapper->orientation;
00298 P3 = P3 - 0.5 * wrapper->length * wrapper->orientation;
00299
00300 Link* link = wrapper->getAttachedLink();
00301 position tmpPos = position (P3.toSbVec3f()) * ( link->getTran());
00302 P3 = vec3 ( tmpPos.toSbVec3f() );
00303 tmpPos = position (P4.toSbVec3f()) * ( link->getTran());
00304 P4 = vec3 ( tmpPos.toSbVec3f() );
00305
00306 vec3 Pa, Pb;
00307 double mua, mub;
00308 LineLineIntersect( pPrev , pNext , P3,P4 , &Pa, &Pb, &mua, &mub);
00309
00310
00311 if (mub<0 || mub>1) return false;
00312
00313
00314
00315 if (mua<=0 || mua>=1) return false;
00316
00317
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339 vec3 dPrev = Pa - Pb;
00340 if (dPrev.len() < WRAPPER_TOLERANCE * wrapper->radius)
00341 {
00342
00343 dPrev = normalise(dPrev);
00344 vec3 dRes = Pb + ( wrapper->radius ) * dPrev;
00345
00346 newInsPtPos = position ( dRes.toSbVec3f() ) * ( link->getTran().inverse() );
00347 return true;
00348 }
00349 return false;
00350 }
00351
00352 PROF_DECLARE(TENDON_REMOVE_INTERSECTIONS);
00353 void Tendon::removeWrapperIntersections()
00354 {
00355 PROF_TIMER_FUNC(TENDON_REMOVE_INTERSECTIONS);
00356 for (std::list<TendonInsertionPoint*>::iterator insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00357 {
00358 std::list<TendonInsertionPoint*>::iterator nextInsPt = insPt;
00359 nextInsPt ++;
00360 if ( !(*insPt)->isPermanent() && insPt!=mInsPointList.begin() && nextInsPt!=mInsPointList.end() )
00361 {
00362 std::list<TendonInsertionPoint*>::iterator prevInsPt = insPt;
00363 prevInsPt--;
00364 vec3 pPrev = vec3( (*prevInsPt)->getWorldPosition() );
00365 vec3 pNext = vec3( (*nextInsPt)->getWorldPosition() );
00366 bool needed = false;
00367 for (int j=0; j< ((HumanHand*)getRobot())->getNumTendonWrappers(); j++)
00368 {
00369 TendonWrapper *wrapper = ((HumanHand*)getRobot())->getTendonWrapper(j);
00370 position foo;
00371 if (wrapperIntersection(wrapper, mTendonName, pPrev, pNext, foo))
00372 {
00373 needed = true;
00374 break;
00375 }
00376 }
00377 if (!needed)
00378 {
00379 removeInsertionPoint(insPt);
00380 insPt = prevInsPt;
00381 }
00382 }
00383 }
00384 }
00385
00395 PROF_DECLARE(TENDON_CHECK_INTERSECTIONS);
00396 void Tendon::checkWrapperIntersections()
00397 {
00398 PROF_TIMER_FUNC(TENDON_CHECK_INTERSECTIONS);
00399 std::list<TendonInsertionPoint*>::iterator insPt = mInsPointList.begin();
00400 int num_insertions = 0;
00401 while (insPt!=mInsPointList.end())
00402 {
00403 bool new_insertion = false;
00404 std::list<TendonInsertionPoint*>::iterator nextInsPt = insPt;
00405 nextInsPt ++;
00406 if (nextInsPt != mInsPointList.end() ) {
00407 vec3 pCur = vec3( (*insPt)->getWorldPosition() );
00408 vec3 pNext = vec3 ( (*nextInsPt)->getWorldPosition() );
00409 for (int j=0; j< ((HumanHand*)getRobot())->getNumTendonWrappers(); j++)
00410 {
00411 TendonWrapper *wrapper = ((HumanHand*)getRobot())->getTendonWrapper(j);
00412 if ( wrapper->isExempt(mTendonName)) continue;
00413 position newInsPtPos;
00414 if ( wrapperIntersection(wrapper, mTendonName, pCur, pNext, newInsPtPos) ) {
00415 int chainNr = wrapper->getChainNr();
00416 int linkNr = wrapper->getLinkNr();
00417 insertInsertionPoint( nextInsPt, chainNr, linkNr, vec3(newInsPtPos.toSbVec3f()), wrapper->getMu(), false );
00418 new_insertion = true;
00419 }
00420 }
00421 }
00422 if (new_insertion && num_insertions++ > 10)
00423 {
00424 DBGA("More than 10 new tendon insertions in a single point; loop might be stuck, forcing continuation.");
00425 new_insertion = false;
00426 }
00427 if (!new_insertion)
00428 {
00429 insPt++;
00430 num_insertions = 0;
00431 }
00432 }
00433 }
00434
00441 PROF_DECLARE(TENDON_UPDATE_GEOMETRY);
00442 PROF_DECLARE(TENDON_COMPUTE_GEOMETRY_CORE);
00443 void Tendon::updateGeometry()
00444 {
00445 PROF_TIMER_FUNC(TENDON_UPDATE_GEOMETRY);
00446
00447 checkWrapperIntersections();
00448
00449
00450 removeWrapperIntersections();
00451
00452
00453 mCurrentLength = 0;
00454
00455 PROF_START_TIMER(TENDON_COMPUTE_GEOMETRY_CORE);
00456 std::list<TendonInsertionPoint*>::iterator insPt, prevInsPt, newInsPt;
00457 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00458 {
00459 prevInsPt = insPt;
00460 if (insPt!=mInsPointList.begin())
00461 {
00462 prevInsPt--;
00463 SbVec3f pPrev = (*prevInsPt)->getWorldPosition();
00464 SbVec3f pCur = (*insPt)->getWorldPosition();
00465 vec3 dPrev = vec3(pCur) - vec3(pPrev);
00466
00467 float m = dPrev.len();
00468
00469 mCurrentLength += m;
00470
00471
00472
00473 if (mVisible)
00474 {
00475
00476 vec3 c = vec3(pPrev) + dPrev*0.5;
00477 SoTransform* tran = (*insPt)->getIVConnectorTran();
00478 SoCylinder* geom = (*insPt)->getIVConnectorGeom();
00479 geom->radius=(float)TendonInsertionPoint::CONNECTOR_RADIUS;
00480 geom->height = m;
00481 tran->pointAt(c.toSbVec3f(),pPrev);
00482
00483 rotateSoTransform(tran, vec3(1.0, 0.0, 0.0), -1.5707);
00484 }
00485 }
00486 else if (mVisible)
00487 {
00488
00489 SoCylinder* geom = (*insPt)->getIVConnectorGeom();
00490 geom->radius=0.1f;
00491 geom->height = 0.1f;
00492 }
00493 }
00494 PROF_STOP_TIMER(TENDON_COMPUTE_GEOMETRY_CORE);
00495
00496
00497 computeSimplePassiveForces();
00498 updateInsertionForces();
00499 if (mVisible && mForcesVisible) updateForceIndicators();
00500 }
00501
00502 PROF_DECLARE(TENDON_UPDATE_FORCE_INDICATORS);
00503 void Tendon::updateForceIndicators()
00504 {
00505 PROF_TIMER_FUNC(TENDON_UPDATE_FORCE_INDICATORS);
00506 mIVForceIndicators->removeAllChildren();
00507 std::vector<transf> insPointTrans;
00508 std::vector<double> insPointMagn;
00509 getInsertionPointTransforms(insPointTrans);
00510 getInsertionPointForceMagnitudes(insPointMagn);
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535 if (insPointTrans.size() != insPointMagn.size())
00536 {
00537 DBGA("Error: number of ins point trans does not match number of ins point magn");
00538 return;
00539 }
00540 for (size_t i=0; i<insPointTrans.size(); i++)
00541 {
00542 SoTransform* forceTrans = new SoTransform;
00543 insPointTrans[i].toSoTransform(forceTrans);
00544
00545 rotateSoTransform(forceTrans, vec3(1.0, 0.0, 0.0), 1.5707);
00546 SoArrow *arrow = new SoArrow;
00547 arrow->height = 10.0 * 1.0e-6 * insPointMagn[i] * getTotalForce();
00548 arrow->cylRadius = 0.25;
00549 arrow->coneRadius = 0.5;
00550 if (arrow->height.getValue() < arrow->coneHeight.getValue()) {
00551 arrow->coneHeight = arrow->height.getValue() / 2.0;
00552 }
00553 SoSeparator* forceIndSep = new SoSeparator;
00554 forceIndSep->addChild(forceTrans);
00555 forceIndSep->addChild(arrow);
00556 mIVForceIndicators->addChild(forceIndSep);
00557 DBGP("Active force: " << mActiveForce << "; Passive force: " << mPassiveForce);
00558 DBGP("Added indicator of length" << 10.0 * 1.0e-6 * insPointMagn[i] * getTotalForce());
00559 }
00560 }
00561
00562 transf Tendon::getInsertionPointWorldTransform(std::list<TendonInsertionPoint*>::iterator insPt)
00563 {
00564 SbVec3f pCur = (*insPt)->getWorldPosition();
00565 std::list<TendonInsertionPoint*>::iterator prevInsPt = insPt; prevInsPt--;
00566 std::list<TendonInsertionPoint*>::iterator nextInsPt = insPt; nextInsPt++;
00567 vec3 dPrev(0,0,0), dNext(0,0,0);
00568
00569 if (insPt != mInsPointList.begin()) dPrev = normalise(vec3((*prevInsPt)->getWorldPosition()) - vec3(pCur));
00570 if (nextInsPt != mInsPointList.end()) dNext = normalise(vec3((*nextInsPt)->getWorldPosition()) - vec3(pCur));
00571
00572 SoTransform* tran = new SoTransform;
00573 tran->pointAt(pCur,(vec3(pCur)+dPrev + dNext).toSbVec3f());
00574
00575 rotateSoTransform(tran, vec3(1.0, 0.0, 0.0), -3.14159);
00576 transf tr(tran);
00577 tran->ref();
00578 tran->unref();
00579 return tr;
00580 }
00581
00582 PROF_DECLARE(TENDON_GET_INS_POINT_TRANSFORMS);
00583 void Tendon::getInsertionPointTransforms(std::vector<transf> &insPointTrans)
00584 {
00585 PROF_TIMER_FUNC(TENDON_GET_INS_POINT_TRANSFORMS);
00586 if (mInsPointList.size() <= 1) {
00587 DBGA("Insertion point transforms ill-defined, not enough insertion points");
00588 return;
00589 }
00590 std::list<TendonInsertionPoint*>::iterator insPt;
00591 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00592 {
00593 insPointTrans.push_back( getInsertionPointWorldTransform(insPt) );
00594 }
00595 }
00596
00598 void Tendon::getInsertionPointLinkTransforms(std::list< std::pair<transf, Link*> > &insPointLinkTrans)
00599 {
00600 if (mInsPointList.size() <= 1) {
00601 DBGA("Insertion point transforms ill-defined, not enough insertion points");
00602 return;
00603 }
00604 std::list<TendonInsertionPoint*>::iterator insPt;
00605 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00606 {
00607
00608 transf linkTrans = getInsertionPointWorldTransform(insPt) * (*insPt)->getAttachedLink()->getTran().inverse();
00609 insPointLinkTrans.push_back( std::pair<transf, Link*>(linkTrans, (*insPt)->getAttachedLink()) );
00610 }
00611 }
00612
00613 PROF_DECLARE(TENDON_GET_INS_POINT_FORCE_MAGNITUDES);
00614 void Tendon::getInsertionPointForceMagnitudes(std::vector<double> &magnitudes)
00615 {
00616 PROF_TIMER_FUNC(TENDON_GET_INS_POINT_FORCE_MAGNITUDES);
00617 if (mInsPointList.size() <= 1) {
00618 DBGA("Insertion point transforms ill-defined, not enough insertion points");
00619 return;
00620 }
00621 std::list<TendonInsertionPoint*>::iterator insPt;
00622 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00623 {
00624 SbVec3f pCur = (*insPt)->getWorldPosition();
00625 std::list<TendonInsertionPoint*>::iterator prevInsPt = insPt; prevInsPt--;
00626 std::list<TendonInsertionPoint*>::iterator nextInsPt = insPt; nextInsPt++;
00627 vec3 dPrev(0,0,0), dNext(0,0,0);
00628
00629 if (insPt != mInsPointList.begin()) dPrev = normalise( vec3(pCur) - vec3((*prevInsPt)->getWorldPosition()) );
00630 if (nextInsPt != mInsPointList.end()) dNext = normalise( vec3(pCur) - vec3((*nextInsPt)->getWorldPosition()) );
00631 magnitudes.push_back( vec3(dPrev + dNext).len() );
00632 }
00633 }
00634
00635 double Tendon::getTotalFrictionCoefficient()
00636 {
00637 return getFrictionCoefficientBetweenPermInsPoints(0, getNumPermInsPoints() - 1, true);
00638 }
00639
00640
00641 double Tendon::getFrictionCoefficientBetweenPermInsPoints(int start, int end, bool inclusive)
00642 {
00643 if (start < 0 || end >= getNumPermInsPoints() || start > end) {
00644 DBGA("Incorrect start or end for tendon friction interval");
00645 return -1.0;
00646 }
00647 std::vector<double> magnitudes;
00648 getInsertionPointForceMagnitudes(magnitudes);
00649 assert(magnitudes.size() == mInsPointList.size());
00650
00651 std::list<TendonInsertionPoint*>::const_iterator it;
00652 int num = 0, count = 0;
00653 double totalMu = 0.0;
00654 for (it=mInsPointList.begin(); it!=mInsPointList.end(); it++)
00655 {
00656 if (inclusive && num >= start)
00657 {
00658 totalMu += magnitudes.at(count) * (*it)->getMu();
00659 }
00660 else if (num > start && num < end) totalMu += magnitudes.at(count) * (*it)->getMu();
00661 if ((*it)->isPermanent()) num++;
00662 if (num > end) break;
00663 count++;
00664 }
00665 assert(num > end);
00666 return totalMu;
00667 }
00668
00677
00678 void Tendon::computeSimplePassiveForces()
00679 {
00680
00681
00682 if ( getExcursion() < 0 ) {
00683 mPassiveForce = 0;
00684 return;
00685 }
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695 mPassiveForce = getExcursion() * getStiffness();
00696 }
00697
00703 PROF_DECLARE(TENDON_UPDATE_INSERTION_FORCES);
00704 void Tendon::updateInsertionForces()
00705 {
00706 PROF_TIMER_FUNC(TENDON_UPDATE_INSERTION_FORCES);
00707 SbVec3f pPrev,pCur,pNext;
00708 position tmpPos;
00709 vec3 dPrev,dNext,dRes,c;
00710
00711 std::list<TendonInsertionPoint*>::iterator insPt, prevInsPt, nextInsPt, newInsPt;
00712
00713 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00714 {
00715 prevInsPt = insPt;
00716 nextInsPt = insPt;
00717 nextInsPt ++;
00718
00719 if (insPt!=mInsPointList.begin())
00720 {
00721 prevInsPt--;
00722 pPrev = (*prevInsPt)->getWorldPosition();
00723 }
00724
00725 pCur = (*insPt)->getWorldPosition();
00726
00727 if (nextInsPt != mInsPointList.end() )
00728 pNext = (*nextInsPt)->getWorldPosition();
00729
00730
00731 if (insPt == mInsPointList.begin())
00732 {
00733
00734 dNext = vec3(pNext) - vec3(pCur);
00735 dNext = ( (float)1 / dNext.len() ) * dNext;
00736 dRes = getTotalForce() * dNext;
00737 (*insPt)->mInsertionForce = dRes;
00738 }
00739 else if ( nextInsPt != mInsPointList.end() )
00740 {
00741
00742 dPrev = vec3(pPrev) - vec3(pCur);
00743 dNext = vec3(pNext) - vec3(pCur);
00744 dPrev = ( (float)1 / dPrev.len() ) * dPrev;
00745 dNext = ( (float)1 / dNext.len() ) * dNext;
00746 dRes = getTotalForce() * (dPrev + dNext);
00747 (*insPt)->mInsertionForce = dRes;
00748 }
00749 else
00750 {
00751
00752 dPrev = vec3(pPrev) - vec3(pCur);
00753 dPrev = ( (float)1 / dPrev.len() ) * dPrev;
00754 dRes = getTotalForce() * dPrev;
00755 (*insPt)->mInsertionForce = dRes;
00756 }
00757 }
00758 }
00759
00760 void Tendon::setRestLength(double length)
00761 {
00762 if (length==0) DBGA("WARNING: length 0 set on tendon");
00763 mRestLength = length;
00764 computeSimplePassiveForces();
00765 updateInsertionForces();
00766 if (mVisible && mForcesVisible) updateForceIndicators();
00767 }
00768
00769 void Tendon::select()
00770 {
00771 std::list<TendonInsertionPoint*>::iterator insPt;
00772 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00773 {
00774 SoMaterial* mat = (*insPt)->getIVInsertionMaterial();
00775 if ( (*insPt)->isPermanent() ) mat->diffuseColor.setValue(1.0f,0.7f,0.7f);
00776 else mat->diffuseColor.setValue(1.0f,0.5f,0.5f);
00777 if (insPt!=mInsPointList.begin())
00778 {
00779 mat = (*insPt)->getIVConnectorMaterial();
00780 mat->diffuseColor.setValue(1.0f,0.5f,0.5f);
00781 }
00782 }
00783 mIVForceIndMaterial->diffuseColor.setValue(0.5f , 0.8f , 0.8f);
00784 mSelected = true;
00785 }
00786
00787 void Tendon::deselect()
00788 {
00789 std::list<TendonInsertionPoint*>::iterator insPt;
00790 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00791 {
00792 SoMaterial* mat = (*insPt)->getIVInsertionMaterial();
00793 if ((*insPt)->isPermanent()) mat->diffuseColor.setValue(0.7f,0.2f,0.2f);
00794 else mat->diffuseColor.setValue(0.5f,0.5f,0.5f);
00795 if (insPt!=mInsPointList.begin())
00796 {
00797 mat = (*insPt)->getIVConnectorMaterial();
00798 mat->diffuseColor.setValue(0.5f,0.5f,0.5f);
00799 }
00800 }
00801 mIVForceIndMaterial->diffuseColor.setValue(0.2f , 0.4f , 0.4f);
00802 mSelected = false;
00803 }
00804
00805 void Tendon::setVisible(bool v)
00806 {
00807
00808 mVisible = v;
00809 if (v) {
00810 updateGeometry();
00811 mIVVisibleToggle->style = SoDrawStyle::FILLED;
00812 if (mForcesVisible) mIVForceIndToggle->style = SoDrawStyle::FILLED;
00813 } else {
00814 mIVVisibleToggle->style = SoDrawStyle::INVISIBLE;
00815 mIVForceIndToggle->style = SoDrawStyle::INVISIBLE;
00816 }
00817 }
00818
00819 void Tendon::setForcesVisible(bool v)
00820 {
00821 if (v && !mVisible) return;
00822 mForcesVisible = v;
00823 if (v) {
00824 updateForceIndicators();
00825 mIVForceIndToggle->style = SoDrawStyle::FILLED;
00826 } else {
00827 mIVForceIndToggle->style = SoDrawStyle::INVISIBLE;
00828 }
00829 }
00830
00831 void Tendon::addInsertionPoint(int chain, int link, vec3 point, double mu, bool isPerm)
00832 {
00833 insertInsertionPoint( mInsPointList.end(), chain, link, point, mu, isPerm);
00834 }
00835
00836 std::list<TendonInsertionPoint*>::iterator
00837 Tendon::insertInsertionPoint(std::list<TendonInsertionPoint*>::iterator itPos,
00838 int chain, int link, vec3 point, double mu, bool isPerm)
00839 {
00840 std::list<TendonInsertionPoint*>::iterator newInsPt;
00841 newInsPt = mInsPointList.insert( itPos, new TendonInsertionPoint(this,chain,link,point,mu,isPerm) );
00842 mIVRoot->addChild( (*newInsPt)->getIVInsertion() );
00843 mIVRoot->addChild( (*newInsPt)->getIVConnector() );
00844 return newInsPt;
00845 }
00846
00847 int Tendon::getNumPermInsPoints() const
00848 {
00849 std::list<TendonInsertionPoint*>::const_iterator it;
00850 int num = 0;
00851 for (it=mInsPointList.begin(); it!=mInsPointList.end(); it++)
00852 {
00853 if ((*it)->isPermanent()) num++;
00854 }
00855 return num;
00856 }
00857
00858 TendonInsertionPoint* Tendon::getPermInsPoint(int n)
00859 {
00860 std::list<TendonInsertionPoint*>::const_iterator it;
00861 int num = 0;
00862 for (it=mInsPointList.begin(); it!=mInsPointList.end(); it++)
00863 {
00864 if ((*it)->isPermanent() && num++ == n) return *it;
00865 }
00866 DBGA("Requested tendon insertion point not found");
00867 return NULL;
00868 }
00869
00870 PROF_DECLARE(TENDON_REMOVE_INS_POINT);
00871 std::list<TendonInsertionPoint*>::iterator
00872 Tendon::removeInsertionPoint(std::list<TendonInsertionPoint*>::iterator itPos)
00873 {
00874 PROF_TIMER_FUNC(TENDON_REMOVE_INS_POINT);
00875 (*itPos)->removeAllGeometry();
00876 mIVRoot->removeChild( (*itPos)->getIVConnector() );
00877 mIVRoot->removeChild( (*itPos)->getIVInsertion() );
00878 if ( (*itPos)->isPermanent() ) DBGA("WARNING: removing a permanent insertion point!");
00879 delete *itPos;
00880 std::list<TendonInsertionPoint*>::iterator newIt = mInsPointList.erase( itPos );
00881 return newIt;
00882
00883
00884 }
00885 void Tendon::applyForces()
00886 {
00887 if (getTotalForce() <= 0) return;
00888 std::list<TendonInsertionPoint*>::iterator insPt;
00889 for (insPt=mInsPointList.begin(); insPt!=mInsPointList.end(); insPt++)
00890 {
00891 Link* link = (*insPt)->getAttachedLink();
00892
00893 SbVec3f tmp = ( (*insPt)->getAttachPoint() ).toSbVec3f();
00894 position pos = position(tmp) * ( link->getTran() );
00895
00896
00897 vec3 force = (*insPt)->mInsertionForce;
00898 link->addForceAtPos( force , pos );
00899 }
00900 }
00901
00902 bool Tendon::loadFromXml(const TiXmlElement *root)
00903 {
00904 QString name = root->Attribute("name");
00905 if(name.isNull()){
00906 DBGA("Tendon name undefined");
00907 return false;
00908 }
00909 setName(name);
00910
00911 double stiffness;
00912 if (!getDouble(root, "stiffness", stiffness)) stiffness = 0.0;
00913 setStiffness(stiffness * 1.0e6);
00914
00915 double defaultRestLength;
00916 if (!getDouble(root, "restLength", defaultRestLength)) mDefaultRestLength = -1.0;
00917 else mDefaultRestLength = defaultRestLength;
00918
00919 double preTensionLength;
00920 if (!getDouble(root, "preTensionLength", preTensionLength)) mPreTensionLength = -1.0;
00921 else mPreTensionLength = preTensionLength;
00922
00923 int nrInsPoints=countXmlElements(root, "insertionPoint");
00924 if (nrInsPoints<2){
00925 DBGA("Incorrect number of Ins Points");
00926 return false;
00927 }
00928
00929 std::list<const TiXmlElement*> elementList2 = findAllXmlElements(root, "insertionPoint");
00930 std::list<const TiXmlElement*>::iterator p2;
00931 int j;
00932 for (p2 = elementList2.begin(), j=0; p2!=elementList2.end(); p2++,j++) {
00933 int chain;
00934 if(!getInt(*p2,"chain",chain)){
00935 DBGA("Failed to read chain on ins point"<<j);
00936 return false;
00937 }
00938 int link;
00939 if(!getInt(*p2,"link",link)){
00940 DBGA("Failed to read link on ins point"<<j);
00941 return false;
00942 }
00943 const TiXmlElement* element = findXmlElement(*p2,"position");
00944 if(!element){
00945 DBGA("Failed to read position on ins point"<<j);
00946 return false;
00947 }
00948 vec3 position;
00949 if(!getPosition(element,position)){
00950 DBGA("Failed to read position on ins point"<<j);
00951 return false;
00952 }
00953 double friction;
00954 if (!getDouble(*p2, "friction", friction)) friction = 0.0;
00955 addInsertionPoint(chain,link,position,friction,true);
00956 }
00957 return true;
00958 }
00959
00960 TendonWrapper::TendonWrapper(Robot *myOwner) :
00961 mMu(0.0),
00962 owner(myOwner)
00963 {
00964 }
00965
00970 Link* TendonWrapper::getAttachedLink()
00971 {
00972 if (attachChainNr == -1 || attachLinkNr == -1){
00973
00974 return owner->getBase();
00975 } else {
00976 return owner->getChain(attachChainNr)->getLink(attachLinkNr);
00977 }
00978 }
00979
00980 void TendonWrapper::createGeometry()
00981 {
00982 IVWrapper = new SoSeparator;
00983 IVWrapperMaterial = new SoMaterial;
00984 IVWrapperTran = new SoTransform;
00985 IVWrapperGeom = new SoCylinder;
00986
00987
00988 SoDrawStyle *ds = new SoDrawStyle;
00989 IVWrapper->addChild(ds);
00990 ds->style = SoDrawStyle::LINES;
00991
00992
00993
00994
00995
00996 IVWrapper->addChild( getAttachedLink()->getIVTran() );
00997
00998
00999 IVWrapper->addChild(IVWrapperTran);
01000
01001
01002 IVWrapper->addChild(IVWrapperMaterial);
01003 IVWrapper->addChild(IVWrapperGeom);
01004 IVWrapperMaterial->diffuseColor.setValue(0.7f , 0.1f , 0.1f);
01005 }
01006
01007 void TendonWrapper::updateGeometry()
01008 {
01009 IVWrapperTran->pointAt(location.toSbVec3f(),location.toSbVec3f() + orientation.toSbVec3f());
01010
01011 rotateSoTransform(IVWrapperTran, vec3(1.0, 0.0, 0.0), -1.5707);
01012 IVWrapperGeom->radius=radius;
01013 IVWrapperGeom->height=length;
01014 }
01015
01016 void TendonWrapper::setLocation(vec3 loc)
01017 {
01018 location = loc;
01019 updateGeometry();
01020 }
01021
01022 void TendonWrapper::setOrientation(vec3 orient)
01023 {
01024 orientation = orient;
01025 updateGeometry();
01026 }
01027
01028 void TendonWrapper::setRadius(double r)
01029 {
01030 radius = r;
01031 updateGeometry();
01032 }
01033
01034 bool TendonWrapper::wrappingSide(QString tendonName, vec3 &direction)
01035 {
01036 for (size_t i=0; i<mWrappingSideVec.size(); i++) {
01037 if (mWrappingSideVec[i].mTendonName == tendonName) {
01038 direction = mWrappingSideVec[i].mDirection;
01039 return true;
01040 }
01041 }
01042 return false;
01043 }
01044
01045 bool TendonWrapper::loadFromXml(const TiXmlElement* root)
01046 {
01047 int chain;
01048 if(!getInt(root,"chain",chain)){
01049 DBGA("Failed to read chain on tendon wrapper");
01050 return false;
01051 }
01052 int link;
01053 if(!getInt(root,"link",link)){
01054 DBGA("Failed to read link on tendon wrapper");
01055 return false;
01056 }
01057 double mu;
01058 if (!getDouble(root, "friction", mu)) mu = 0.0;
01059 const TiXmlElement* element = findXmlElement(root,"position");
01060 if(!element){
01061 DBGA("Failed to read position on tendon wrapper");
01062 return false;
01063 }
01064 vec3 loc;
01065 if(!getPosition(element,loc)){
01066 DBGA("Failed to read position tendon wrapper");
01067 return false;
01068 }
01069 element = findXmlElement(root,"orientation");
01070 if(!element){
01071 DBGA("Failed to read orientation on tendon wrapper");
01072 return false;
01073 }
01074 vec3 ort;
01075 if(!getPosition(element,ort)){
01076 DBGA("Failed to read orientation tendon wrapper");
01077 return false;
01078 }
01079 double rad;
01080 if(!getDouble(root,"radius",rad)){
01081 DBGA("Failed to read radius on tendon wrapper");
01082 return false;
01083 }
01084 double len;
01085 if(!getDouble(root,"length",len)){
01086 DBGA("Tendon wrapper with no specified length, using default");
01087 len = 10.0;
01088 }
01089 attachChainNr = chain;
01090 attachLinkNr = link;
01091 location = loc;
01092 orientation = ort;
01093 radius = rad;
01094 length = len;
01095 mMu = mu;
01096
01097
01098 std::list<const TiXmlElement*> elementList = findAllXmlElements(root,"exemption");
01099 std::list<const TiXmlElement*>::iterator p;
01100 for (p = elementList.begin(); p != elementList.end(); p++) {
01101 QString name = (*p)->Attribute("tendon");
01102 if(name.isNull()){
01103 DBGA("Warning: tendon name undefined for wrapper exemption");
01104 continue;
01105 }
01106 mExemptList.push_back(name);
01107 }
01108
01109
01110 elementList = findAllXmlElements(root,"wrapping_side");
01111 for (p = elementList.begin(); p != elementList.end(); p++) {
01112 QString name = (*p)->Attribute("tendon");
01113 if(name.isNull()){
01114 DBGA("Warning: tendon name undefined for wrapping side");
01115 continue;
01116 }
01117 const TiXmlElement* element = findXmlElement(*p,"orientation");
01118 if(!element){ DBGA("Failed to find orientation on tendon wrapper"); continue;}
01119 vec3 side_dir;
01120 if (!getPosition(element, side_dir)) { DBGA("Warning: incorrect wrapping side direction"); continue;}
01121 WrappingSide side;
01122 side.mTendonName = name;
01123 side.mDirection = side_dir;
01124 mWrappingSideVec.push_back(side);
01125 }
01126
01127 return true;
01128 }
01129
01130 bool TendonWrapper::isExempt(QString name)
01131 {
01132 for (std::list<QString>::iterator it=mExemptList.begin(); it!=mExemptList.end(); it++) {
01133 if ( *it == name ) return true;
01134 }
01135 return false;
01136 }
01137
01138 HumanHand::HumanHand(World *w,const char *name) : Hand(w,name)
01139 {
01140 }
01141
01146 int HumanHand::loadFromXml(const TiXmlElement* root, QString rootPath)
01147 {
01148 if ( Hand::loadFromXml(root, rootPath) != SUCCESS) return FAILURE;
01149 std::list<const TiXmlElement*> elementList = findAllXmlElements(root,"tendon");
01150 std::list<const TiXmlElement*>::iterator p;
01151 int i;
01152 for (p = elementList.begin(), i=0; p != elementList.end(); p++,i++) {
01153 Tendon* newTendon = new Tendon(this);
01154 if (!newTendon->loadFromXml(*p)) {
01155 DBGA("Failed to read tendon " << i);
01156 delete newTendon;
01157 } else {
01158 mTendonVec.push_back(newTendon);
01159 }
01160 }
01161 for (size_t t=0; t<mTendonVec.size(); t++)
01162 {
01163 IVRoot->addChild( mTendonVec[t]->getIVRoot() );
01164 DBGA("Tendon "<< mTendonVec[t]->getName().ascii()<<" read and added");
01165 }
01166
01167 elementList = findAllXmlElements(root,"tendonWrapper");
01168 for (p = elementList.begin(), i=0; p != elementList.end(); p++,i++){
01169 TendonWrapper* newTW = new TendonWrapper(this);
01170 if (!newTW->loadFromXml(*p)) {
01171 DBGA("Failed to load tendon wrapper " << i);
01172 delete newTW;
01173 } else {
01174 newTW->createGeometry();
01175 IVRoot->addChild( newTW->getIVRoot() );
01176 newTW->updateGeometry();
01177 DBGA("TendonWrapper " << i << " geometry added");
01178 mTendonWrapperVec.push_back(newTW);
01179 }
01180 }
01181 updateTendonGeometry();
01182 setRestPosition();
01183 return SUCCESS;
01184 }
01185
01186 void HumanHand::updateTendonGeometry()
01187 {
01188 for (size_t i=0; i<mTendonVec.size(); i++) {
01189 mTendonVec[i]->updateGeometry();
01190 }
01191 }
01192
01193 void HumanHand::applyTendonForces()
01194 {
01195 for (size_t i=0; i<mTendonVec.size(); i++) {
01196 mTendonVec[i]->applyForces();
01197 }
01198 }
01199
01201 void HumanHand::DOFController(double)
01202 {
01203 applyTendonForces();
01204 }
01205
01211 Matrix insPtForceBlockMatrix(unsigned int numInsPoints)
01212 {
01213 if (!numInsPoints) return Matrix(0,0);
01214 Matrix D(Matrix::ZEROES<Matrix>(6*numInsPoints, numInsPoints));
01215 for(unsigned int i=0; i<numInsPoints; i++)
01216 {
01217 D.elem(6*i + 2, i) = 1.0;
01218 }
01219 return D;
01220 }
01221
01222 PROF_DECLARE(HH_TENDON_EQUILIBRIUM);
01223 int HumanHand::tendonEquilibrium(const std::set<size_t> &activeTendons,
01224 const std::set<size_t> &passiveTendons,
01225 bool compute_tendon_forces,
01226 std::vector<double> &activeTendonForces,
01227 std::vector<double> &jointResiduals,
01228 double& unbalanced_magnitude,
01229 bool useJointSprings)
01230 {
01231 PROF_TIMER_FUNC(HH_TENDON_EQUILIBRIUM);
01232 std::list<Joint*> joints;
01233 for(int c=0; c<getNumChains(); c++)
01234 {
01235 std::list<Joint*> chainJoints = getChain(c)->getJoints();
01236 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
01237 }
01238
01239 if (activeTendons.empty() && passiveTendons.empty())
01240 {
01241 DBGA("Need either active or passive tendons (or both) for analysis");
01242 return -1;
01243 }
01244
01245 Matrix LeftHand(Matrix::ZEROES<Matrix>(joints.size(), activeTendons.size()));
01246 Matrix RightHand(Matrix::ZEROES<Matrix>(joints.size(), 1));
01247 for (size_t i=0; i<mTendonVec.size(); i++)
01248 {
01249 std::list< std::pair<transf, Link*> > insPointLinkTrans;
01250 mTendonVec[i]->getInsertionPointLinkTransforms(insPointLinkTrans);
01251 Matrix J( grasp->contactJacobian(joints, insPointLinkTrans) );
01252 Matrix JTran( J.transposed() );
01253 Matrix D( insPtForceBlockMatrix( insPointLinkTrans.size() ) );
01254 Matrix JTD( JTran.rows(), D.cols() );
01255 matrixMultiply( JTran, D, JTD );
01256
01257 std::vector<double> magnitudes;
01258 mTendonVec[i]->getInsertionPointForceMagnitudes(magnitudes);
01259 Matrix M(&magnitudes[0], magnitudes.size(), 1, true);
01260 assert(M.rows() == JTD.cols());
01261 Matrix JTDM( JTD.rows(), M.cols());
01262 matrixMultiply( JTD, M, JTDM);
01263
01264 if (activeTendons.find(i) != activeTendons.end())
01265 {
01266 assert( JTDM.rows() == LeftHand.rows());
01267 assert( JTDM.cols() == 1);
01268 LeftHand.copySubMatrix(0, i, JTDM);
01269 }
01270 else if (passiveTendons.find(i) != passiveTendons.end())
01271 {
01272 JTDM.multiply( mTendonVec[i]->getPassiveForce() );
01273 matrixAdd(RightHand, JTDM, RightHand);
01274 }
01275 else
01276 {
01277 DBGP("Warning: tendon " << i << " is not active or passive");
01278 }
01279 }
01280
01281
01282 if (useJointSprings)
01283 {
01284 std::list<Joint*>::iterator jit;
01285 size_t j_num;
01286 for (jit=joints.begin(),j_num=0; jit!=joints.end(); jit++,j_num++)
01287 {
01288 RightHand.elem(j_num,0) = RightHand.elem(j_num,0) - (*jit)->getSpringForce();
01289 }
01290 }
01291
01292 Matrix x(LeftHand.cols(), 1);
01293
01294 if (compute_tendon_forces)
01295 {
01296
01297
01298 double scale = std::max(1.0, RightHand.absMax());
01299 RightHand.multiply(1.0/scale);
01300 RightHand.multiply(-1.0);
01301 if ( linearSolveSVD(LeftHand, RightHand, x) != 0 )
01302 {
01303 DBGA("SVD decomposition solving failed");
01304 return -1;
01305 }
01306 x.multiply(scale);
01307 RightHand.multiply(-1.0);
01308 RightHand.multiply(scale);
01309 }
01310 else
01311 {
01312
01313 if ((int)activeTendonForces.size() != x.rows())
01314 {
01315 DBGA("Incorrect active tendon forces passed in");
01316 return -1;
01317 }
01318 int t=0;
01319 for (size_t i=0; i<mTendonVec.size(); i++)
01320 {
01321 if (activeTendons.find(i) != activeTendons.end())
01322 {
01323 x.elem(t,0) = activeTendonForces.at(t);
01324 t++;
01325 }
01326 }
01327 }
01328
01329
01330 Matrix tau(LeftHand.rows(), 1);
01331 matrixMultiply(LeftHand, x, tau);
01332 matrixAdd(tau, RightHand, tau);
01333 tau.getData(&jointResiduals);
01334 DBGP("Joint residuals: " << jointResiduals[0] << " " <<jointResiduals[1]);
01335 unbalanced_magnitude = tau.fnorm();
01336
01337
01338 if (compute_tendon_forces)
01339 {
01340 activeTendonForces.resize( activeTendons.size(), 0.0 );
01341 int t=0;
01342 for (size_t i=0; i<mTendonVec.size(); i++)
01343 {
01344 if (activeTendons.find(i) != activeTendons.end())
01345 {
01346 activeTendonForces.at(t) = x.elem(t,0);
01347 t++;
01348 }
01349 }
01350 }
01351
01352 return 0;
01353 }
01354
01360 int HumanHand::contactTorques(std::list<Contact*> contacts,
01361 std::vector<double> &jointTorques)
01362 {
01363 std::list<Joint*> joints;
01364 for(int c=0; c<getNumChains(); c++)
01365 {
01366 std::list<Joint*> chainJoints = getChain(c)->getJoints();
01367 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
01368 }
01369 Matrix RightHand(joints.size(), 1);
01370 {
01371 Matrix J( grasp->contactJacobian(joints, contacts) );
01372 Matrix JTran( J.transposed() );
01373 Matrix D( insPtForceBlockMatrix( contacts.size() ) );
01374 Matrix JTD( JTran.rows(), D.cols() );
01375 matrixMultiply( JTran, D, JTD );
01376
01377 std::vector<double> magnitudes;
01378
01379
01380 magnitudes.resize(contacts.size(), -1.0);
01381 Matrix M(&magnitudes[0], magnitudes.size(), 1, true);
01382 assert(M.rows() == JTD.cols());
01383 Matrix JTDM( JTD.rows(), M.cols());
01384 matrixMultiply( JTD, M, JTDM);
01385
01386 RightHand.copyMatrix(JTDM);
01387 }
01388
01389 double scale = 1.0e6;
01390 RightHand.multiply(-1.0);
01391 jointTorques.resize(RightHand.rows());
01392 for (size_t i=0; i<jointTorques.size(); i++)
01393 {
01394 jointTorques[i] = RightHand.elem(i,0) * scale;
01395 }
01396 return 0;
01397 }
01398
01405 PROF_DECLARE(HH_CONTACT_EQUILIBRIUM);
01406 int HumanHand::contactEquilibrium(std::list<Contact*> contacts,
01407 const std::set<size_t> &activeTendons,
01408 std::vector<double> &activeTendonForces,
01409 double &unbalanced_magnitude)
01410 {
01411 PROF_TIMER_FUNC(HH_CONTACT_EQUILIBRIUM);
01412 std::list<Joint*> joints;
01413 for(int c=0; c<getNumChains(); c++)
01414 {
01415 std::list<Joint*> chainJoints = getChain(c)->getJoints();
01416 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
01417 }
01418
01419 activeTendonForces.resize( activeTendons.size(), 0.0 );
01420 if (activeTendons.empty())
01421 {
01422 DBGA("Need active tendons for analysis");
01423 return -1;
01424 }
01425 if (contacts.empty())
01426 {
01427 DBGA("Contact list empty for contact equilibrium");
01428 return -1;
01429 }
01430
01431 Matrix LeftHand(joints.size(), activeTendons.size());
01432 for (size_t i=0; i<mTendonVec.size(); i++)
01433 {
01434 if (activeTendons.find(i) == activeTendons.end()) continue;
01435
01436 std::list< std::pair<transf, Link*> > insPointLinkTrans;
01437 mTendonVec[i]->getInsertionPointLinkTransforms(insPointLinkTrans);
01438 Matrix J( grasp->contactJacobian(joints, insPointLinkTrans) );
01439 Matrix JTran( J.transposed() );
01440 Matrix D( insPtForceBlockMatrix( insPointLinkTrans.size() ) );
01441 Matrix JTD( JTran.rows(), D.cols() );
01442 matrixMultiply( JTran, D, JTD );
01443
01444 std::vector<double> magnitudes;
01445 mTendonVec[i]->getInsertionPointForceMagnitudes(magnitudes);
01446 Matrix M(&magnitudes[0], magnitudes.size(), 1, true);
01447 assert(M.rows() == JTD.cols());
01448 Matrix JTDM( JTD.rows(), M.cols());
01449 matrixMultiply( JTD, M, JTDM);
01450
01451 assert( JTDM.rows() == LeftHand.rows());
01452 assert( JTDM.cols() == 1);
01453 LeftHand.copySubMatrix(0, i, JTDM);
01454 }
01455
01456 Matrix RightHand(joints.size(), 1);
01457 {
01458 Matrix J( grasp->contactJacobian(joints, contacts) );
01459 Matrix JTran( J.transposed() );
01460 Matrix D( insPtForceBlockMatrix( contacts.size() ) );
01461 Matrix JTD( JTran.rows(), D.cols() );
01462 matrixMultiply( JTran, D, JTD );
01463
01464 std::vector<double> magnitudes;
01465
01466
01467 magnitudes.resize(contacts.size(), -1.0);
01468 Matrix M(&magnitudes[0], magnitudes.size(), 1, true);
01469 assert(M.rows() == JTD.cols());
01470 Matrix JTDM( JTD.rows(), M.cols());
01471 matrixMultiply( JTD, M, JTDM);
01472
01473 RightHand.copyMatrix(JTDM);
01474 }
01475
01476 double scale = 1.0e6;
01477 RightHand.multiply(-1.0);
01478
01479 DBGA("Joint torques: " << RightHand.elem(0,0) << " " << RightHand.elem(1,0));
01480
01481 Matrix x(LeftHand.cols(), 1);
01482 if ( linearSolveSVD(LeftHand, RightHand, x) != 0 )
01483 {
01484 DBGA("SVD decomposition solving failed");
01485 return -1;
01486 }
01487
01488
01489 Matrix tau(LeftHand.rows(), 1);
01490 matrixMultiply(LeftHand, x, tau);
01491 RightHand.multiply(-1.0);
01492 matrixAdd(tau, RightHand, tau);
01493
01494
01495 unbalanced_magnitude = tau.fnorm()*scale;
01496
01497
01498 x.multiply(scale);
01499
01500 int t=0;
01501 for (size_t i=0; i<mTendonVec.size(); i++)
01502 {
01503 if (activeTendons.find(i) != activeTendons.end())
01504 {
01505
01506 activeTendonForces.at(t) = x.elem(t,0);
01507 t++;
01508 }
01509 }
01510
01511
01512 return 0;
01513 }
01514
01521 int HumanHand::contactForcesFromTendonForces(std::list<Contact*> contacts,
01522 std::vector<double> &contactForces,
01523 const std::set<size_t> &activeTendons,
01524 const std::vector<double> &activeTendonForces)
01525 {
01526 std::list<Joint*> joints;
01527 for(int c=0; c<getNumChains(); c++)
01528 {
01529 std::list<Joint*> chainJoints = getChain(c)->getJoints();
01530 joints.insert(joints.end(), chainJoints.begin(), chainJoints.end());
01531 }
01532
01533 if (activeTendons.empty())
01534 {
01535 DBGA("Need active tendons for analysis");
01536 return -1;
01537 }
01538 if (contacts.empty())
01539 {
01540 DBGA("Contact list empty for contact equilibrium");
01541 return -1;
01542 }
01543
01544 Matrix LeftHand(joints.size(), activeTendons.size());
01545 int t=0;
01546 for (size_t i=0; i<mTendonVec.size(); i++)
01547 {
01548 if (activeTendons.find(i) == activeTendons.end()) continue;
01549
01550 std::list< std::pair<transf, Link*> > insPointLinkTrans;
01551 mTendonVec[i]->getInsertionPointLinkTransforms(insPointLinkTrans);
01552 Matrix J( grasp->contactJacobian(joints, insPointLinkTrans) );
01553 Matrix JTran( J.transposed() );
01554 Matrix D( insPtForceBlockMatrix( insPointLinkTrans.size() ) );
01555 Matrix JTD( JTran.rows(), D.cols() );
01556 matrixMultiply( JTran, D, JTD );
01557
01558 std::vector<double> magnitudes;
01559 mTendonVec[i]->getInsertionPointForceMagnitudes(magnitudes);
01560 Matrix M(&magnitudes[0], magnitudes.size(), 1, true);
01561 assert(M.rows() == JTD.cols());
01562 Matrix JTDM( JTD.rows(), M.cols());
01563 matrixMultiply( JTD, M, JTDM);
01564
01565 assert( JTDM.rows() == LeftHand.rows());
01566 assert( JTDM.cols() == 1);
01567 LeftHand.copySubMatrix(0, t, JTDM);
01568 t++;
01569 }
01570
01571
01572 Matrix x(LeftHand.cols(), 1);
01573 if ((int)activeTendonForces.size() != x.rows())
01574 {
01575 DBGA("Incorrect active tendon forces passed in");
01576 return -1;
01577 }
01578 t=0;
01579 for (size_t i=0; i<mTendonVec.size(); i++)
01580 {
01581 if (activeTendons.find(i) != activeTendons.end())
01582 {
01583 x.elem(t,0) = activeTendonForces.at(t);
01584 t++;
01585 }
01586 }
01587
01588 Matrix tau(LeftHand.rows(), 1);
01589 matrixMultiply(LeftHand, x, tau);
01590 DBGP("Joint torques: " << tau.elem(0,0) << " " << tau.elem(1,0));
01591
01592 Matrix RightHand(joints.size(), contacts.size());
01593 {
01594 Matrix J( grasp->contactJacobian(joints, contacts) );
01595 Matrix JTran( J.transposed() );
01596 Matrix D( insPtForceBlockMatrix( contacts.size() ) );
01597 Matrix JTD( JTran.rows(), D.cols() );
01598 matrixMultiply( JTran, D, JTD );
01599 RightHand.copyMatrix(JTD);
01600 }
01601
01602
01603
01604
01605
01606 double scale = std::max(1.0, tau.absMax());
01607 tau.multiply(1.0/scale);
01608
01609 DBGP("Joint torques scaled: " << tau.elem(0,0) << " " << tau.elem(1,0));
01610
01611 Matrix c(RightHand.cols(), 1);
01612 if ( linearSolveSVD(RightHand, tau, c) != 0 )
01613 {
01614 DBGA("SVD decomposition solving failed");
01615 return -1;
01616 }
01617
01618
01619
01620
01621
01622
01623
01624
01625
01626
01627 DBGP("Contact forces computed for " << contacts.size() << "contacts");
01628 Matrix test(RightHand.rows(),1);
01629 matrixMultiply(RightHand, c, test);
01630 test.multiply(-1);
01631 matrixAdd(test, tau, test);
01632 if (test.fnorm() > 1.0e-5) {DBGA("Warning: norm of error " << test.fnorm());}
01633
01634 c.multiply(scale);
01635 contactForces.resize( contacts.size() );
01636 for (size_t i=0; i<contacts.size(); i++)
01637 {
01638 contactForces[i] = c.elem(i,0);
01639 }
01640
01641 return 0;
01642 }
01643
01644 bool HumanHand::insPointInsideWrapper()
01645 {
01646 for(size_t i=0; i<mTendonVec.size(); i++)
01647 {
01648 if (mTendonVec[i]->insPointInsideWrapper())
01649 {
01650
01651 return true;
01652 }
01653 }
01654 return false;
01655 }
01656