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 "dof.h"
00027
00028 #include <QTextStream>
00029
00030 #include "robot.h"
00031 #include "joint.h"
00032 #include "dynJoint.h"
00033 #include "body.h"
00034 #include "world.h"
00035
00036
00037 #include "debug.h"
00038
00040 DOF::DOF() : owner(NULL), q(0.0),desiredq(0.0), desiredVelocity(0.0),defaultVelocity(0.0),
00041 actualVelocity(0.0), maxAccel(10.0), force(0.0),maxForce(0.0),
00042 extForce(0.0), Kv(0.0),Kp(0.0),mHistoryMaxSize(10), mDynStartTime(0.0), currTrajPt(0),
00043 draggerScale(20.0)
00044 {
00045 }
00046
00051 DOF::DOF(const DOF *original)
00052 {
00053 owner = NULL;
00054 dofNum = original->dofNum;
00055 maxq = original->maxq;
00056 minq = original->minq;
00057 q = 0.0;
00058 desiredq = 0.0;
00059
00060 defaultVelocity = original->defaultVelocity;
00061 maxAccel = original->maxAccel;
00062 desiredVelocity = 0.0;
00063 actualVelocity = 0.0;
00064
00065 maxForce = original->maxForce;
00066 force = 0.0;
00067 extForce = 0.0;
00068
00069 Kv = original->Kv;
00070 Kp = original->Kp;
00071
00072 mHistoryMaxSize = original->mHistoryMaxSize;
00073 draggerScale = original->draggerScale;
00074 currTrajPt = 0;
00075 }
00076
00082 void
00083 DOF::initDOF(Robot *myRobot,const std::list<Joint *>& jList)
00084 {
00085 owner = myRobot;
00086 jointList = jList;
00087 updateMinMax();
00088 }
00089
00092 void DOF::updateMinMax()
00093 {
00094 maxq = (*jointList.begin())->getMax()/getStaticRatio(*jointList.begin());
00095 minq = (*jointList.begin())->getMin()/getStaticRatio(*jointList.begin());
00096 if (maxq < minq) std::swap(maxq, minq);
00097 std::list<Joint *>::iterator j;
00098 double testMin, testMax;
00099 int num = 0;
00100 for(j=++jointList.begin();j!=jointList.end();j++) {
00101 testMax = (*j)->getMax()/getStaticRatio(*j);
00102 testMin = (*j)->getMin()/getStaticRatio(*j);
00103
00104 if (testMax < testMin) std::swap(testMin, testMax);
00105 DBGP("Joint " << num++ << " min " << testMin << " max " << testMax);
00106 maxq = ( testMax < maxq ? testMax : maxq);
00107 minq = ( testMin > minq ? testMin : minq);
00108 DBGP("maxq " << maxq << " minq " << minq);
00109 }
00110 }
00111
00118 void
00119 DOF::updateSetPoint() {
00120 if (!trajectory.empty()) {
00121 setPoint = trajectory[currTrajPt++];
00122 if (trajectory.begin()+currTrajPt==trajectory.end()) {
00123 trajectory.clear();
00124 }
00125 }else if (setPoint != desiredq) {
00126 setPoint=desiredq;
00127 }
00128 DBGP("Update set point: " << setPoint);
00129 }
00130
00135 void
00136 DOF::setTrajectory(double *traj,int numPts)
00137 {
00138 trajectory.clear();
00139 currTrajPt = 0;
00140 trajectory.reserve(numPts);
00141 for (int i=0;i<numPts;i++) {
00142 trajectory.push_back(traj[i]);
00143 }
00144 desiredq = traj[numPts-1];
00145 mErrorHistory.clear();
00146 mPositionHistory.clear();
00147 mForceHistory.clear();
00148
00149 mDynStartTime = owner->getWorld()->getWorldTime();
00150 }
00151
00153 void
00154 DOF::addToTrajectory(double *traj,int numPts)
00155 {
00156 for (int i=0;i<numPts;i++){
00157 trajectory.push_back(traj[i]);
00158 }
00159 desiredq = trajectory.back();
00160 }
00161
00165 void
00166 DOF::callController(double timeStep)
00167 {
00168
00169
00170 updateFromJointValues();
00171
00172
00173 mErrorHistory.push_front(setPoint - q);
00174 while ((int)mErrorHistory.size() > mHistoryMaxSize) {
00175 mErrorHistory.pop_back();
00176 }
00177
00178
00179
00180
00181
00182
00183
00184
00185 if (!mPositionHistory.empty()) {
00186 mVelocityHistory.push_front( (q - mPositionHistory.front() ) / timeStep );
00187 while ((int)mVelocityHistory.size() > mHistoryMaxSize) {
00188 mVelocityHistory.pop_back();
00189 }
00190 }
00191
00192 mPositionHistory.push_front(q);
00193 while ((int)mPositionHistory.size() > mHistoryMaxSize) {
00194 mPositionHistory.pop_back();
00195 }
00196
00197
00198 double newForce = PDPositionController(timeStep);
00199
00200 setForce(newForce);
00201
00202 mForceHistory.push_front(newForce);
00203 while ((int)mForceHistory.size() > mHistoryMaxSize) {
00204 mForceHistory.pop_back();
00205 }
00206 }
00207
00214 double
00215 DOF::PDPositionController(double timeStep)
00216 {
00217 double error = mErrorHistory.front(), lastError;
00218 if (mErrorHistory.size() >= 2) {
00219 lastError = *(++mErrorHistory.begin());
00220 } else {
00221 lastError = error;
00222 }
00223
00224 double newForce;
00225
00226 newForce = Kp * error + Kv * (error-lastError)/timeStep;
00227
00228 DBGP("DOF " << getDOFNum() );
00229 DBGP("setPoint ="<<setPoint<<" error ="<<error<<" edot = "<<(error-lastError));
00230 DBGP("proportional: "<<error<<"*"<<Kp<<"="<<error*Kp);
00231 DBGP("derivative: "<<Kv<<"*"<<(error-lastError)/timeStep);
00232 DBGP("cap: "<<getMaxForce()*0.8 << " Force: "<<newForce);
00233 DBGP("e " << error << " de " << error-lastError << " ts " << timeStep << " f " << newForce);
00234 return newForce;
00235 }
00236
00241 bool
00242 DOF::dynamicsProgress()
00243 {
00244 return true;
00245 }
00246
00251 bool
00252 DOF::readParametersFromXml(const TiXmlElement* root)
00253 {
00254 if(!getDouble(root,"defaultVelocity", defaultVelocity))
00255 return false;
00256 if(!getDouble(root,"maxEffort", maxForce))
00257 return false;
00258 if(!getDouble(root,"Kp", Kp))
00259 return false;
00260 if(!getDouble(root,"Kd", Kv))
00261 return false;
00262 if(!getDouble(root,"draggerScale", draggerScale))
00263 return false;
00264 return true;
00265 }
00266
00270 bool
00271 DOF::writeToStream(QTextStream &stream)
00272 {
00273 stream << q;
00274 return true;
00275 }
00276
00280 bool
00281 DOF::readFromStream(QTextStream &stream)
00282 {
00283 if (stream.atEnd()) return false;
00284 stream >> q;
00285 return true;
00286 }
00287
00293 void
00294 RigidDOF::setForce(double f)
00295 {
00296 Joint *activeJoint = *(jointList.begin());
00297 if (f > maxForce) force = maxForce;
00298 else if (f < -maxForce) force = -maxForce;
00299 else force = f;
00300
00301
00302 activeJoint->applyInternalWrench(force);
00303 DBGP("Applied force = " << force);
00304 }
00305
00312 double
00313 RigidDOF::getClosestJointLimit(int *direction)
00314 {
00315 bool firstTime = true;
00316 double closestLimit = 0.0;
00317 *direction = 0.0;
00318 std::list<Joint*>::iterator j;
00319 for (j=jointList.begin(); j!=jointList.end(); j++) {
00320 double val = (*j)->getVal();
00321 double maxError = val - (*j)->getMax();
00322 double minError = (*j)->getMin() - val;
00323 double error; int jdir;
00324 if (maxError > minError) {
00325 error = maxError;
00326 jdir = -1;
00327 } else {
00328 error = minError;
00329 jdir = +1;
00330 }
00331 error /= getStaticRatio(*j);
00332 if (firstTime || fabs(error) > fabs(closestLimit)) {
00333 closestLimit = error;
00334 *direction = jdir;
00335 firstTime = false;
00336 }
00337 }
00338 return closestLimit;
00339 }
00340
00344 int
00345 RigidDOF::getNumLimitConstraints()
00346 {
00347 int d;
00348 if (getClosestJointLimit(&d) < -0.01) return 0;
00349 return 1;
00350 }
00351
00356 void
00357 RigidDOF::buildDynamicLimitConstraints(std::map<Body*,int> &islandIndices, int numBodies,
00358 double* H, double *g, int &hcn)
00359 {
00360 int dir;
00361 double error = getClosestJointLimit(&dir);
00362 if ( error < -0.01) return;
00363
00364 g[hcn] = MIN(0.0, -error - 0.005);
00365 DBGP("adding dof limit constraint for DOF " << dofNum << " in dir " << dir << "; error: "<<g[hcn]);
00366
00367
00368 Joint *currentJoint = jointList.front();
00369 DynamicBody *prevLink = currentJoint->dynJoint->getPrevLink();
00370 DynamicBody *nextLink = currentJoint->dynJoint->getNextLink();
00371
00372 assert( islandIndices[prevLink]>=0 );
00373 int row = 6*islandIndices[prevLink];
00374 H[(hcn)*6*numBodies + row+3] -= dir * currentJoint->getWorldAxis()[0];
00375 H[(hcn)*6*numBodies + row+4] -= dir * currentJoint->getWorldAxis()[1];
00376 H[(hcn)*6*numBodies + row+5] -= dir * currentJoint->getWorldAxis()[2];
00377
00378 assert( islandIndices[nextLink]>=0 );
00379 row = 6*islandIndices[nextLink];
00380 H[(hcn)*6*numBodies + row+3] += dir * currentJoint->getWorldAxis()[0];
00381 H[(hcn)*6*numBodies + row+4] += dir * currentJoint->getWorldAxis()[1];
00382 H[(hcn)*6*numBodies + row+5] += dir * currentJoint->getWorldAxis()[2];
00383
00384 hcn++;
00385 }
00386
00391 void
00392 RigidDOF::buildDynamicCouplingConstraints(std::map<Body*,int> &islandIndices, int numBodies,
00393 double* Nu, double*, int &ncn)
00394 {
00395
00396 Joint *masterJoint = jointList.front();
00397
00398 DynamicBody *masterPrevLink = masterJoint->dynJoint->getPrevLink();
00399 DynamicBody *masterNextLink = masterJoint->dynJoint->getNextLink();
00400 double masterRatio = getStaticRatio(masterJoint);
00401 vec3 masterFreeRotAxis = masterJoint->getWorldAxis();
00402
00403 std::list<Joint*>::iterator it = jointList.begin();
00404 while(++it != jointList.end()) {
00405 Joint *currentJoint = (*it);
00406
00407
00408
00409
00410
00411 if (currentJoint->getType() != REVOLUTE) continue;
00412
00413 DynamicBody *prevLink = currentJoint->dynJoint->getPrevLink();
00414 DynamicBody *nextLink = currentJoint->dynJoint->getNextLink();
00415 vec3 freeRotAxis = currentJoint->getWorldAxis();
00416
00417
00418 double ratio = 1.0/getStaticRatio(currentJoint);
00419 assert( islandIndices[prevLink] >= 0 );
00420 int row = 6*islandIndices[prevLink];
00421 Nu[(ncn)*6*numBodies + row+3] -= ratio * freeRotAxis[0];
00422 Nu[(ncn)*6*numBodies + row+4] -= ratio * freeRotAxis[1];
00423 Nu[(ncn)*6*numBodies + row+5] -= ratio * freeRotAxis[2];
00424 assert( islandIndices[nextLink] >= 0 );
00425 row = 6*islandIndices[nextLink];
00426 Nu[(ncn)*6*numBodies + row+3] += ratio * freeRotAxis[0];
00427 Nu[(ncn)*6*numBodies + row+4] += ratio * freeRotAxis[1];
00428 Nu[(ncn)*6*numBodies + row+5] += ratio * freeRotAxis[2];
00429
00430
00431 ratio = 1.0/masterRatio;
00432 assert( islandIndices[masterPrevLink] >= 0 );
00433 row = 6*islandIndices[masterPrevLink];
00434 Nu[(ncn)*6*numBodies + row+3] += ratio * masterFreeRotAxis[0];
00435 Nu[(ncn)*6*numBodies + row+4] += ratio * masterFreeRotAxis[1];
00436 Nu[(ncn)*6*numBodies + row+5] += ratio * masterFreeRotAxis[2];
00437 assert( islandIndices[masterNextLink] >= 0 );
00438 row = 6*islandIndices[masterNextLink];
00439 Nu[(ncn)*6*numBodies + row+3] += - ratio * masterFreeRotAxis[0];
00440 Nu[(ncn)*6*numBodies + row+4] += - ratio * masterFreeRotAxis[1];
00441 Nu[(ncn)*6*numBodies + row+5] += - ratio * masterFreeRotAxis[2];
00442
00443 ncn++;
00444
00445
00446 }
00447 }
00448
00449 double
00450 RigidDOF::getStaticRatio(Joint *j) const
00451 {
00452 return j->getCouplingRatio();
00453 }
00454
00455 void
00456 RigidDOF::getJointValues(double *jointVals) const
00457 {
00458 std::list<Joint*>::const_iterator j;
00459 for(j=jointList.begin();j!=jointList.end();j++) {
00460 jointVals[ (*j)->getNum() ] = q * getStaticRatio(*j);
00461 }
00462 }
00463
00466 bool
00467 RigidDOF::accumulateMove(double q1, double *jointVals, int *stoppedJoints)
00468 {
00469 if ( fabs(q-q1) < 1.0e-5 ) return false;
00470 std::list<Joint*>::iterator j;
00471 if (stoppedJoints) {
00472 for(j=jointList.begin();j!=jointList.end();j++) {
00473 if ( stoppedJoints[ (*j)->getNum()] ) return false;
00474 }
00475 }
00476 for(j=jointList.begin();j!=jointList.end();j++) {
00477 jointVals[ (*j)->getNum() ] = q1 * getStaticRatio(*j);
00478 }
00479 return true;
00480 }
00481
00487 void
00488 RigidDOF::updateFromJointValues(const double *jointVals)
00489 {
00490 assert(!jointList.empty());
00491 double val;
00492 if (jointVals) {
00493 val = jointVals[ jointList.front()->getNum() ];
00494 }
00495 else {
00496 val = jointList.front()->getVal();
00497 }
00498 q = val / getStaticRatio(jointList.front());
00499 DBGP("DOF " << getDOFNum() << ": set value " << q);
00500 }
00501
00502 BreakAwayDOF::~BreakAwayDOF()
00503 {
00504 if (mInBreakAway) delete [] mInBreakAway;
00505 if (mBreakAwayValues) delete [] mBreakAwayValues;
00506 }
00507
00508 void BreakAwayDOF::initDOF(Robot *myRobot, const std::list<Joint*> &jList)
00509 {
00510 DOF::initDOF(myRobot, jList);
00511 int size = (int)jList.size();
00512 assert(size>0);
00513 mInBreakAway = new int[size];
00514 mBreakAwayValues = new double[size];
00515 for (int i=0; i<size; i++) {
00516 mInBreakAway[i] = 0;
00517
00518 mBreakAwayValues[i] = -10;
00519 }
00520 }
00521
00525 void
00526 BreakAwayDOF::getJointValues(double *jointVals) const
00527 {
00528 int index = -1;
00529 std::list<Joint*>::const_iterator j;
00530 for (j=jointList.begin(); j!=jointList.end(); j++) {
00531 index++;
00532 if (mInBreakAway[index] && q > mBreakAwayValues[index]) {
00533 jointVals[ (*j)->getNum() ] = mBreakAwayValues[index] * getStaticRatio(*j);
00534 } else {
00535 jointVals[ (*j)->getNum() ] = q * getStaticRatio(*j);
00536 }
00537 }
00538 }
00539
00543 bool
00544 BreakAwayDOF::accumulateMove(double q1, double *jointVals, int *stoppedJoints)
00545 {
00546 if ( fabs(q-q1) < 1.0e-5 ) {
00547 DBGP("DOF new value same as current value");
00548 return false;
00549 }
00550 std::list<Joint*>::iterator j;
00551
00552 for (j=jointList.begin(); j!=jointList.end(); j++) {
00553 if (stoppedJoints && stoppedJoints[ (*j)->getNum()] ) {
00554 if (q1 < q){
00555 DBGP("Joint stopped in the negative direction; stopping all movement");
00556 return false;
00557 }
00558 }
00559 }
00560
00561
00562 bool movement = false;
00563 int index = -1;
00564 for (j=jointList.begin(); j!=jointList.end(); j++) {
00565 index++;
00566 if (mInBreakAway[index] && q1 > mBreakAwayValues[index]) {
00567 DBGP("Joint " << index << " is in break away");
00568 continue;
00569 }
00570 double newVal = q1 * getStaticRatio(*j);
00571 DBGP("q1 " << q1 << " * ratio " << getStaticRatio(*j) << " = " << newVal);
00572 double oldVal = (*j)->getVal();
00573 if (stoppedJoints) {
00574 if (newVal > oldVal && (stoppedJoints[ (*j)->getNum()] & 1) ) {
00575 DBGP("Joint " << index << " is stopped in the positive direction");
00576 continue;
00577 }
00578 if (newVal < oldVal && (stoppedJoints[ (*j)->getNum()] & 2) ) {
00579 DBGP("Joint " << index << " is stopped in the negative direction");
00580 continue;
00581 }
00582 }
00583 jointVals[ (*j)->getNum() ] = newVal;
00584 movement = true;
00585 }
00586 return movement;
00587 }
00588
00589 void
00590 BreakAwayDOF::updateVal(double q1)
00591 {
00592 std::list<Joint*>::iterator j;
00593 int index;
00594 for(j=jointList.begin(), index=0; j!=jointList.end(); j++,index++) {
00595 double jVal = (*j)->getVal() / getStaticRatio(*j);
00596 if (mInBreakAway[index]) {
00597 if (q1 < mBreakAwayValues[index] - 1.0e-5) {
00598 mInBreakAway[index] = false;
00599 DBGP("DOF " << dofNum << " joint " << index << " re-engaged");
00600 }
00601 } else {
00602 if (jVal < q1 - 1.0e-5) {
00603 DBGP("DOF " << dofNum << " joint " << index << " disengaged at " << jVal);
00604 mInBreakAway[index] = true;
00605 mBreakAwayValues[index] = jVal;
00606 }
00607 }
00608 }
00609 q = q1;
00610 }
00611
00615 void
00616 BreakAwayDOF::updateFromJointValues(const double *jointVals)
00617 {
00618 std::list<Joint*>::iterator j;
00619 int index;
00620 double val;
00621 for(j=jointList.begin(),index=0; j!=jointList.end(); j++,index++) {
00622 if (mInBreakAway[index]) continue;
00623 if (!jointVals) {
00624 val = (*j)->getVal() / getStaticRatio(*j);
00625 } else {
00626 val = jointVals[ (*j)->getNum() ] / getStaticRatio(*j);
00627 }
00628 break;
00629 }
00630
00631 assert( j!= jointList.end() );
00632 q = val;
00633 DBGP("DOF " << getDOFNum() << ": set value " << q);
00634 }
00635
00637 void
00638 BreakAwayDOF::reset()
00639 {
00640 if (!mInBreakAway) return;
00641 for (int j=0; j<(int)jointList.size(); j++) {
00642 mInBreakAway[j] = false;
00643 }
00644 }
00645
00646 bool
00647 BreakAwayDOF::writeToStream(QTextStream &stream)
00648 {
00649 stream << q;
00650 for (int j=0; j<(int)jointList.size(); j++) {
00651 if (!mInBreakAway || !mInBreakAway[j]) {
00652 stream << " " << 0;
00653 } else {
00654 stream << " " << 1 << " " << mBreakAwayValues[j];
00655 }
00656 }
00657 return true;
00658 }
00659
00663 double
00664 BreakAwayDOF::getSaveVal() const
00665 {
00666 if (!mInBreakAway) return q;
00667 double val = q;
00668 for (int j=0; j<(int)jointList.size(); j++) {
00669 if ( mInBreakAway[j] ) {
00670 if ( mBreakAwayValues[j] < val ) {
00671 val = mBreakAwayValues[j];
00672 }
00673 }
00674 }
00675 return val;
00676 }
00677
00678 bool
00679 BreakAwayDOF::readFromStream(QTextStream &stream)
00680 {
00681 if (stream.atEnd()) return false;
00682 stream >> q;
00683 DBGP("Value: " << q);
00684 for (int j=0; j<(int)jointList.size(); j++) {
00685 assert(mInBreakAway);
00686 stream >> mInBreakAway[j];
00687 DBGP(" bway: " << mInBreakAway[j]);
00688 if (mInBreakAway[j] == 1) {
00689 stream >> mBreakAwayValues[j];
00690 } else if (mInBreakAway[j]==0) {
00691 mBreakAwayValues[j] = -10;
00692 } else {
00693 return false;
00694 }
00695 }
00696 return true;
00697 }
00698
00699 bool
00700 BreakAwayDOF::readParametersFromXml(const TiXmlElement* root)
00701 {
00702 if (!DOF::readParametersFromXml(root)) return false;
00703 if(!getDouble(root,"breakAwayTorque", mBreakAwayTorque)||mBreakAwayTorque < 0){
00704
00705 DBGA("BreakAway torque missing or negative, using default value 0.0");
00706 mBreakAwayTorque = 0.0f;
00707 } else {
00708
00709 mBreakAwayTorque *= 1.0e3;
00710 }
00711 return true;
00712 }
00713
00719 bool
00720 BreakAwayDOF::computeStaticJointTorques(double *jointTorques, double)
00721 {
00722 std::list<Joint*>::iterator j;
00723 int index;
00724 for(j=jointList.begin(), index=0; j!=jointList.end(); j++,index++) {
00725 if (mInBreakAway[index]) {
00726 jointTorques[ (*j)->getNum() ] += mBreakAwayTorque;
00727 }
00728 }
00729 return true;
00730 }
00731
00732 void
00733 CompliantDOF::initDOF(Robot *myRobot, const std::list<Joint*> &jList)
00734 {
00735 DOF::initDOF(myRobot, jList);
00736 std::list<Joint*>::iterator j;
00737 for(j=jointList.begin(); j!=jointList.end(); j++) {
00738 if ( (*j)->getSpringStiffness() == 0.0 ) {
00739 DBGA("ERROR: Compliant joint has no stiffness! DEFAULT VALUE will be used!");
00740 }
00741 }
00742 }
00743
00744 double
00745 CompliantDOF::getStaticRatio(Joint *j) const {
00746 double ref = jointList.front()->getSpringStiffness();
00747 assert(ref!=0.0);
00748 double k = j->getSpringStiffness();
00749 if (k == 0.0) k = ref;
00750
00751
00752
00753 int jn = j->getNum();
00754 if (jn==0 || jn==2 || jn== 4 || jn==6) {
00755 return j->getCouplingRatio();
00756 } else {
00757 double tau2 = j->getCouplingRatio();
00758 double tau1 = jointList.front()->getCouplingRatio();
00759 return (ref / k) * ( tau1 * tau2) / (tau1 + tau2);
00760 }
00761 }
00762
00763 void
00764 CompliantDOF::getJointValues(double* jointVals) const
00765 {
00766 std::list<Joint*>::const_iterator j;
00767 for (j=jointList.begin(); j!=jointList.end(); j++) {
00768 jointVals[ (*j)->getNum() ] = q * getStaticRatio(*j);
00769 }
00770 }
00771
00777 void
00778 CompliantDOF::updateFromJointValues(const double* jointVals)
00779 {
00780 double max = -1.0e5;
00781 std::list<Joint*>::const_iterator j;
00782 for (j=jointList.begin(); j!=jointList.end(); j++) {
00783 double v;
00784 if (jointVals) {
00785 v = jointVals[ (*j)->getNum() ] / getStaticRatio(*j);
00786 } else {
00787 v = (*j)->getVal() / getStaticRatio(*j);
00788 }
00789 max = std::max(max,v);
00790 }
00791 q = max;
00792 }
00793
00795 bool
00796 CompliantDOF::accumulateMove(double q1, double *jointVals, int *stoppedJoints)
00797 {
00798 if ( fabs(q-q1) < 1.0e-5 ) {
00799 DBGP("DOF is already at desired value");
00800 return false;
00801 }
00802
00803 bool movement = false;
00804 std::list<Joint*>::const_iterator j; int index;
00805 for (j=jointList.begin(), index=0; j!=jointList.end(); j++, index++) {
00806 double newVal = q1 * getStaticRatio(*j);
00807 double oldVal = (*j)->getVal();
00808 if (stoppedJoints) {
00809 if (newVal > oldVal && (stoppedJoints[ (*j)->getNum()] & 1) ) {
00810 DBGP("Joint " << index << " is stopped in the positive direction");
00811 continue;
00812 }
00813 if (newVal < oldVal && (stoppedJoints[ (*j)->getNum()] & 2) ) {
00814 DBGP("Joint " << index << " is stopped in the negative direction");
00815 continue;
00816 }
00817 }
00818 jointVals[ (*j)->getNum() ] = newVal;
00819 movement = true;
00820 }
00821 return movement;
00822 }
00823
00824
00830 bool
00831 CompliantDOF::computeStaticJointTorques(double *jointTorques, double dofForce)
00832 {
00833
00834
00835
00836
00837
00838 bool retVal = true;
00839
00840 double maxDofTorque = 0.0;
00841 std::list<Joint*>::iterator j;
00842 Joint *pj = NULL;
00843 int count = 0;
00844 for(j=jointList.begin(); j!=jointList.end(); j++) {
00845 double springTorque = (*j)->getSpringForce();
00846 DBGP("Inner spring: " << springTorque);
00847 jointTorques[ (*j)->getNum() ] -= springTorque;
00848
00849 if (count==1 || count==3 || count==5 || count==7) {
00850 assert(pj);
00851 vec3 axis1 = (*j)->dynJoint->getPrevLink()->getTran().affine().row(2);
00852 vec3 axis2 = pj->dynJoint->getPrevLink()->getTran().affine().row(2);
00853 double t = fabs(axis1 % axis2);
00854
00855 jointTorques[pj->getNum()] += springTorque * t;
00856 }
00857 pj = (*j);
00858 count++;
00859 }
00860
00861
00862
00863
00864
00865
00866
00867
00868 for(j=jointList.begin(); j!=jointList.end(); j++) {
00869 double springTorque = - jointTorques[(*j)->getNum()];
00870 double dofTorque = springTorque / (*j)->getCouplingRatio();
00871 if (fabs(dofTorque) > fabs(maxDofTorque)) {
00872 maxDofTorque = dofTorque;
00873 }
00874 }
00875 DBGP("Max dof torque: " << maxDofTorque);
00876
00877 double dofTorque;
00878 if (dofForce < 0) {
00879
00880
00881
00882 dofTorque = maxDofTorque;
00883 } else {
00884
00885
00886
00887 dofTorque = force * 40.0;
00888 if (dofTorque < maxDofTorque) {
00889 DBGA("For now, dof torque must at least balance spring forces!");
00890
00891 dofTorque = maxDofTorque + 3.0e7;
00892 }
00893 }
00894
00895
00896 for(j=jointList.begin(); j!=jointList.end(); j++) {
00897 double jointTorque = dofTorque * (*j)->getCouplingRatio();
00898 jointTorques[ (*j)->getNum() ] += jointTorque;
00899 if ( jointTorques[ (*j)->getNum() ] < -1.0e-5) {
00900 DBGP("Error: negative torque on joint " << (*j)->getNum());
00901
00902
00903 }
00904
00905 if ( fabs(jointTorques[(*j)->getNum()]) < 1.0e-5) {
00906 jointTorques[ (*j)->getNum() ] = 0.0;
00907 }
00908 DBGP(jointTorques[ (*j)->getNum() ]);
00909 }
00910
00911
00912
00913
00914
00915
00916
00917 return retVal;
00918 }
00919
00922 int
00923 CompliantDOF::getNumLimitConstraints()
00924 {
00925 int numCon = 0;
00926 std::list<Joint*>::iterator j;
00927 for(j=jointList.begin(); j!=jointList.end(); j++) {
00928 if ( (*j)->getVal() >= (*j)->getMax() - 0.01) numCon ++;
00929 else if ( (*j)->getVal() <= (*j)->getMin() + 0.01) numCon ++;
00930 }
00931 return numCon;
00932 }
00933
00938 void
00939 CompliantDOF::buildDynamicLimitConstraints(std::map<Body*,int> &islandIndices, int numBodies,
00940 double* H, double *g, int &hcn)
00941 {
00942 std::list<Joint*>::iterator j;
00943 int count = 0;
00944 for(j=jointList.begin(); j!=jointList.end(); j++) {
00945 Joint *currentJoint = *j;
00946 DynamicBody *prevLink = currentJoint->dynJoint->getPrevLink();
00947 DynamicBody *nextLink = currentJoint->dynJoint->getNextLink();
00948 int row, dir;
00949 double error;
00950 if (currentJoint->getVal() >= currentJoint->getMax()-0.01) {
00951 error = currentJoint->getMax() - currentJoint->getVal();
00952 dir = -1;
00953 } else if (currentJoint->getVal() <= currentJoint->getMin()+0.01) {
00954 error = currentJoint->getVal() - currentJoint->getMin();
00955 dir = +1;
00956 } else continue;
00957
00958 g[hcn] = MIN(0.0, error - 0.005);
00959 DBGP("adding dof limit constraint for DOF " << dofNum << " error: "<<g[hcn]);
00960
00961 assert( islandIndices[prevLink]>=0 );
00962 row = 6*islandIndices[prevLink];
00963 H[(hcn)*6*numBodies + row+3] -= dir * currentJoint->getWorldAxis()[0];
00964 H[(hcn)*6*numBodies + row+4] -= dir * currentJoint->getWorldAxis()[1];
00965 H[(hcn)*6*numBodies + row+5] -= dir * currentJoint->getWorldAxis()[2];
00966
00967 assert( islandIndices[nextLink]>=0 );
00968 row = 6*islandIndices[nextLink];
00969 H[(hcn)*6*numBodies + row+3] += dir * currentJoint->getWorldAxis()[0];
00970 H[(hcn)*6*numBodies + row+4] += dir * currentJoint->getWorldAxis()[1];
00971 H[(hcn)*6*numBodies + row+5] += dir * currentJoint->getWorldAxis()[2];
00972
00973 hcn++;
00974 count++;
00975 }
00976 }
00977
00978 void
00979 CompliantDOF::setForce(double f)
00980 {
00981
00982 if (f > maxForce) force = maxForce;
00983 if (force < 0) force = 0;
00984 else if (f < -maxForce) force = -maxForce;
00985 else force = f;
00986
00987
00988
00989 std::list<Joint*>::iterator j;
00990 for(j=jointList.begin(); j!=jointList.end(); j++) {
00991 double torqueRatio = (*j)->getCouplingRatio();
00992 DynamicBody* body = (*j)->dynJoint->getNextLink();
00993
00994
00995
00996
00997 double jointTorque = force * 40.0 * torqueRatio;
00998
00999
01000 body->addTorque(jointTorque * (*j)->getWorldAxis());
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011
01012
01013
01014
01015
01016
01017
01018
01019
01020 }
01021 }
01022
01027 double
01028 CompliantDOF::PDPositionController(double timeStep)
01029 {
01030
01031 return smoothProfileController(timeStep);
01032
01033
01034 }
01035
01039 bool
01040 CompliantDOF::dynamicsProgress()
01041 {
01042 double eps = 1.0e-5;
01043 if ((int)mPositionHistory.size() < mHistoryMaxSize) return true;
01044 std::list<double>::iterator it = mPositionHistory.begin();
01045 double ref = *it; it++;
01046
01047 while (it!=mPositionHistory.end()) {
01048
01049 if ( fabs(*it-ref) > eps) {
01050
01051 return true;
01052 }
01053 it++;
01054 }
01055
01056 return false;
01057 }
01058
01063 double
01064 CompliantDOF::smoothProfileController(double)
01065 {
01066 double time = owner->getWorld()->getWorldTime() - mDynStartTime;
01067 time = std::min(time, 1.0);
01068 if (time < 0) {
01069 DBGA("Zero elapsed time in CD controller");
01070 }
01071 time = std::max(time, 0.0);
01072 return time * getMaxForce();
01073 }