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