Blender V2.61 - r43446

Armature.cpp

Go to the documentation of this file.
00001 
00004 /*
00005  * Armature.cpp
00006  *
00007  *  Created on: Feb 3, 2009
00008  *      Author: benoitbolsee
00009  */
00010 
00011 #include "Armature.hpp"
00012 #include <algorithm>
00013 #include <string.h>
00014 #include <stdlib.h>
00015 
00016 namespace iTaSC {
00017 
00018 // a joint constraint is characterized by 5 values: tolerance, K, alpha, yd, yddot
00019 static const unsigned int constraintCacheSize = 5;
00020 std::string Armature::m_root = "root";
00021 
00022 Armature::Armature():
00023     ControlledObject(),
00024     m_tree(),
00025     m_njoint(0),
00026     m_nconstraint(0),
00027     m_noutput(0),
00028     m_neffector(0),
00029     m_finalized(false),
00030     m_cache(NULL),
00031     m_buf(NULL),
00032     m_qCCh(-1),
00033     m_qCTs(0),
00034     m_yCCh(-1),
00035     m_yCTs(0),
00036     m_qKdl(),
00037     m_oldqKdl(),
00038     m_newqKdl(),
00039     m_qdotKdl(),
00040     m_jac(NULL),
00041     m_armlength(0.0),
00042     m_jacsolver(NULL),
00043     m_fksolver(NULL)
00044 {
00045 }
00046 
00047 Armature::~Armature()
00048 {
00049     if (m_jac)
00050         delete m_jac;
00051     if (m_jacsolver)
00052         delete m_jacsolver;
00053     if (m_fksolver)
00054         delete m_fksolver;
00055     for (JointConstraintList::iterator it=m_constraints.begin(); it != m_constraints.end(); it++) {
00056         if (*it != NULL)
00057             delete (*it);
00058     }
00059     if (m_buf)
00060         delete [] m_buf;
00061     m_constraints.clear();
00062 }
00063 
00064 Armature::JointConstraint_struct::JointConstraint_struct(SegmentMap::const_iterator _segment, unsigned int _y_nr, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep):
00065     segment(_segment), value(), values(), function(_function), y_nr(_y_nr), param(_param), freeParam(_freeParam), substep(_substep)
00066 {
00067     memset(values, 0, sizeof(values));
00068     memset(value, 0, sizeof(value));
00069     values[0].feedback = 20.0;
00070     values[1].feedback = 20.0;
00071     values[2].feedback = 20.0;
00072     values[0].tolerance = 1.0;
00073     values[1].tolerance = 1.0;
00074     values[2].tolerance = 1.0;
00075     values[0].values = &value[0];
00076     values[1].values = &value[1];
00077     values[2].values = &value[2];
00078     values[0].number = 1;
00079     values[1].number = 1;
00080     values[2].number = 1;
00081     switch (segment->second.segment.getJoint().getType()) {
00082     case Joint::RotX:
00083         value[0].id = ID_JOINT_RX;      
00084         values[0].id = ID_JOINT_RX;     
00085         v_nr = 1;
00086         break;
00087     case Joint::RotY:
00088         value[0].id = ID_JOINT_RY;      
00089         values[0].id = ID_JOINT_RY;     
00090         v_nr = 1;
00091         break;
00092     case Joint::RotZ:
00093         value[0].id = ID_JOINT_RZ;      
00094         values[0].id = ID_JOINT_RZ;     
00095         v_nr = 1;
00096         break;
00097     case Joint::TransX:
00098         value[0].id = ID_JOINT_TX;      
00099         values[0].id = ID_JOINT_TX;     
00100         v_nr = 1;
00101         break;
00102     case Joint::TransY:
00103         value[0].id = ID_JOINT_TY;      
00104         values[0].id = ID_JOINT_TY;     
00105         v_nr = 1;
00106         break;
00107     case Joint::TransZ:
00108         value[0].id = ID_JOINT_TZ;      
00109         values[0].id = ID_JOINT_TZ;     
00110         v_nr = 1;
00111         break;
00112     case Joint::Sphere:
00113         values[0].id = value[0].id = ID_JOINT_RX;       
00114         values[1].id = value[1].id = ID_JOINT_RY;
00115         values[2].id = value[2].id = ID_JOINT_RZ;       
00116         v_nr = 3;
00117         break;
00118     case Joint::Swing:
00119         values[0].id = value[0].id = ID_JOINT_RX;       
00120         values[1].id = value[1].id = ID_JOINT_RZ;       
00121         v_nr = 2;
00122         break;
00123     case Joint::None:
00124         break;
00125     }
00126 }
00127 
00128 Armature::JointConstraint_struct::~JointConstraint_struct()
00129 {
00130     if (freeParam && param)
00131         free(param);
00132 }
00133 
00134 void Armature::initCache(Cache *_cache)
00135 {
00136     m_cache = _cache;
00137     m_qCCh = -1;
00138     m_yCCh = -1;
00139     m_buf = NULL;
00140     if (m_cache) {
00141         // add a special channel for the joint
00142         m_qCCh = m_cache->addChannel(this, "q", m_qKdl.rows()*sizeof(double));
00143 #if 0
00144         // for the constraints, instead of creating many different channels, we will
00145         // create a single channel for all the constraints
00146         if (m_nconstraint) {
00147             m_yCCh = m_cache->addChannel(this, "y", m_nconstraint*constraintCacheSize*sizeof(double));
00148             m_buf = new double[m_nconstraint*constraintCacheSize];
00149         }
00150         // store the initial cache position at timestamp 0
00151         pushConstraints(0);
00152 #endif
00153         pushQ(0);
00154     }
00155 }
00156 
00157 void Armature::pushQ(CacheTS timestamp)
00158 {
00159     if (m_qCCh >= 0) {
00160         // try to keep the cache if the joints are the same
00161         m_cache->addCacheVectorIfDifferent(this, m_qCCh, timestamp, &m_qKdl(0), m_qKdl.rows(), KDL::epsilon);
00162         m_qCTs = timestamp;
00163     }
00164 }
00165 
00166 /* return true if a m_cache position was loaded */
00167 bool Armature::popQ(CacheTS timestamp)
00168 {
00169     if (m_qCCh >= 0) {
00170         double* item;
00171         item = (double*)m_cache->getPreviousCacheItem(this, m_qCCh, &timestamp);
00172         if (item && m_qCTs != timestamp) {
00173             double& q = m_qKdl(0);
00174             memcpy(&q, item, m_qKdl.rows()*sizeof(q));
00175             m_qCTs = timestamp;
00176             // changing the joint => recompute the jacobian
00177             updateJacobian();
00178         }
00179         return (item) ? true : false;
00180     }
00181     return true;
00182 }
00183 #if 0
00184 void Armature::pushConstraints(CacheTS timestamp)
00185 {
00186     if (m_yCCh >= 0) {
00187         double *buf = NULL;
00188         if (m_nconstraint) {
00189             double *item = m_buf;
00190             for (unsigned int i=0; i<m_nconstraint; i++) {
00191                 JointConstraint_struct* pConstraint = m_constraints[i];
00192                 *item++ = pConstraint->values.feedback;
00193                 *item++ = pConstraint->values.tolerance;
00194                 *item++ = pConstraint->value.yd;
00195                 *item++ = pConstraint->value.yddot;
00196                 *item++ = pConstraint->values.alpha;
00197             }
00198         }
00199         m_cache->addCacheVectorIfDifferent(this, m_yCCh, timestamp, m_buf, m_nconstraint*constraintCacheSize, KDL::epsilon);
00200         m_yCTs = timestamp;
00201     }
00202 }
00203 
00204 /* return true if a cache position was loaded */
00205 bool Armature::popConstraints(CacheTS timestamp)
00206 {
00207     if (m_yCCh >= 0) {
00208         double *item = (double*)m_cache->getPreviousCacheItem(this, m_yCCh, &timestamp);
00209         if (item && m_yCTs != timestamp) {
00210             for (unsigned int i=0; i<m_nconstraint; i++) {
00211                 JointConstraint_struct* pConstraint = m_constraints[i];
00212                 if (pConstraint->function != Joint1DOFLimitCallback) {
00213                     pConstraint->values.feedback = *item++;
00214                     pConstraint->values.tolerance = *item++;
00215                     pConstraint->value.yd = *item++;
00216                     pConstraint->value.yddot = *item++;
00217                     pConstraint->values.alpha = *item++;
00218                 } else {
00219                     item += constraintCacheSize;
00220                 }
00221             }
00222             m_yCTs = timestamp;
00223         }
00224         return (item) ? true : false;
00225     }
00226     return true;
00227 }
00228 #endif
00229 
00230 bool Armature::addSegment(const std::string& segment_name, const std::string& hook_name, const Joint& joint, const double& q_rest, const Frame& f_tip, const Inertia& M)
00231 {
00232     if (m_finalized)
00233         return false;
00234 
00235     Segment segment(joint, f_tip, M);
00236     if (!m_tree.addSegment(segment, segment_name, hook_name))
00237         return false;
00238     int ndof = joint.getNDof();
00239     for (int dof=0; dof<ndof; dof++) {
00240         Joint_struct js(joint.getType(), ndof, (&q_rest)[dof]);
00241         m_joints.push_back(js);
00242     }
00243     m_njoint+=ndof;
00244     return true;
00245 }
00246 
00247 bool Armature::getSegment(const std::string& name, const unsigned int q_size, const Joint* &p_joint, double &q_rest, double &q, const Frame* &p_tip)
00248 {
00249     SegmentMap::const_iterator sit = m_tree.getSegment(name);
00250     if (sit == m_tree.getSegments().end())
00251         return false;
00252     p_joint = &sit->second.segment.getJoint();
00253     if (q_size < p_joint->getNDof())
00254         return false;
00255     p_tip = &sit->second.segment.getFrameToTip();
00256     for (unsigned int dof=0; dof<p_joint->getNDof(); dof++) {
00257         (&q_rest)[dof] = m_joints[sit->second.q_nr+dof].rest;
00258         (&q)[dof] = m_qKdl(sit->second.q_nr+dof);
00259     }
00260     return true;
00261 }
00262 
00263 double Armature::getMaxJointChange()
00264 {
00265     if (!m_finalized)
00266         return 0.0;
00267     double maxJoint = 0.0;
00268     for (unsigned int i=0; i<m_njoint; i++) {
00269         // this is a very rough calculation, it doesn't work well for spherical joint
00270         double joint = fabs(m_oldqKdl(i)-m_qKdl(i));
00271         if (maxJoint < joint)
00272             maxJoint = joint;
00273     }
00274     return maxJoint;
00275 }
00276 
00277 double Armature::getMaxEndEffectorChange()
00278 {
00279     if (!m_finalized)
00280         return 0.0;
00281     double maxDelta = 0.0;
00282     double delta;
00283     Twist twist;
00284     for (unsigned int i = 0; i<m_neffector; i++) {
00285         twist = diff(m_effectors[i].pose, m_effectors[i].oldpose);
00286         delta = twist.rot.Norm();
00287         if (delta > maxDelta)
00288             maxDelta = delta;
00289         delta = twist.vel.Norm();
00290         if (delta > maxDelta)
00291             maxDelta = delta;
00292     }
00293     return maxDelta;
00294 }
00295 
00296 int Armature::addConstraint(const std::string& segment_name, ConstraintCallback _function, void* _param, bool _freeParam, bool _substep)
00297 {
00298     SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
00299     // not suitable for NDof joints
00300     if (segment_it == m_tree.getSegments().end()) {
00301         if (_freeParam && _param)
00302             free(_param);
00303         return -1;
00304     }
00305     JointConstraintList::iterator constraint_it;
00306     JointConstraint_struct* pConstraint;
00307     int iConstraint;
00308     for (iConstraint=0, constraint_it=m_constraints.begin(); constraint_it != m_constraints.end(); constraint_it++, iConstraint++) {
00309         pConstraint = *constraint_it;
00310         if (pConstraint->segment == segment_it) {
00311             // redefining a constraint
00312             if (pConstraint->freeParam && pConstraint->param) {
00313                 free(pConstraint->param);
00314             }
00315             pConstraint->function = _function;
00316             pConstraint->param = _param;
00317             pConstraint->freeParam = _freeParam;
00318             pConstraint->substep = _substep;
00319             return iConstraint;
00320         }
00321     }
00322     if (m_finalized)  {
00323         if (_freeParam && _param)
00324             free(_param);
00325         return -1;
00326     }
00327     // new constraint, append
00328     pConstraint = new JointConstraint_struct(segment_it, m_noutput, _function, _param, _freeParam, _substep);
00329     m_constraints.push_back(pConstraint);
00330     m_noutput += pConstraint->v_nr;
00331     return m_nconstraint++;
00332 }
00333 
00334 int Armature::addLimitConstraint(const std::string& segment_name, unsigned int dof, double _min, double _max)
00335 {
00336     SegmentMap::const_iterator segment_it = m_tree.getSegment(segment_name);
00337     if (segment_it == m_tree.getSegments().end())
00338         return -1;
00339     const Joint& joint = segment_it->second.segment.getJoint();
00340     if (joint.getNDof() != 1 && joint.getType() != Joint::Swing) {
00341         // not suitable for Sphere joints
00342         return -1;
00343     }
00344     if ((joint.getNDof() == 1 && dof > 0) || (joint.getNDof() == 2 && dof > 1))
00345         return -1;
00346     Joint_struct& p_joint = m_joints[segment_it->second.q_nr+dof];
00347     p_joint.min = _min;
00348     p_joint.max = _max;
00349     p_joint.useLimit = true;
00350     return 0;
00351 }
00352 
00353 int Armature::addEndEffector(const std::string& name)
00354 {
00355     const SegmentMap& segments = m_tree.getSegments();
00356     if (segments.find(name) == segments.end())
00357         return -1;
00358 
00359     EffectorList::const_iterator it;
00360     int ee;
00361     for (it=m_effectors.begin(), ee=0; it!=m_effectors.end(); it++, ee++) {
00362         if (it->name == name)
00363             return ee;
00364     }
00365     if (m_finalized)
00366         return -1;
00367     Effector_struct effector(name);
00368     m_effectors.push_back(effector);
00369     return m_neffector++;
00370 }
00371 
00372 void Armature::finalize()
00373 {
00374     unsigned int i, j, c;
00375     if (m_finalized)
00376         return;
00377     initialize(m_njoint, m_noutput, m_neffector);
00378     for (i=c=0; i<m_nconstraint; i++) {
00379         JointConstraint_struct* pConstraint = m_constraints[i];
00380         for (j=0; j<pConstraint->v_nr; j++, c++) {
00381             m_Cq(c,pConstraint->segment->second.q_nr+j) = 1.0;
00382             m_Wy(c) = pConstraint->values[j].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
00383         }
00384     }
00385     m_jacsolver= new KDL::TreeJntToJacSolver(m_tree);
00386     m_fksolver = new KDL::TreeFkSolverPos_recursive(m_tree);
00387     m_jac = new Jacobian(m_njoint);
00388     m_qKdl.resize(m_njoint);
00389     m_oldqKdl.resize(m_njoint);
00390     m_newqKdl.resize(m_njoint);
00391     m_qdotKdl.resize(m_njoint);
00392     for (i=0; i<m_njoint; i++) {
00393         m_newqKdl(i) = m_oldqKdl(i) = m_qKdl(i) = m_joints[i].rest;
00394     }
00395     updateJacobian();
00396     // estimate the maximum size of the robot arms
00397     double length;
00398     m_armlength = 0.0;
00399     for (i=0; i<m_neffector; i++) {
00400         length = 0.0;
00401         KDL::SegmentMap::const_iterator sit = m_tree.getSegment(m_effectors[i].name);
00402         while (sit->first != "root") {
00403             Frame tip = sit->second.segment.pose(m_qKdl(sit->second.q_nr));
00404             length += tip.p.Norm();
00405             sit = sit->second.parent;
00406         }
00407         if (length > m_armlength)
00408             m_armlength = length;
00409     }
00410     if (m_armlength < KDL::epsilon)
00411         m_armlength = KDL::epsilon;
00412     m_finalized = true;
00413 }
00414 
00415 void Armature::pushCache(const Timestamp& timestamp)
00416 {
00417     if (!timestamp.substep && timestamp.cache) {
00418         pushQ(timestamp.cacheTimestamp);
00419         //pushConstraints(timestamp.cacheTimestamp);
00420     }
00421 }
00422 
00423 bool Armature::setJointArray(const KDL::JntArray& joints)
00424 {
00425     if (!m_finalized)
00426         return false;
00427     if (joints.rows() != m_qKdl.rows())
00428         return false;
00429     m_qKdl = joints;
00430     updateJacobian();
00431     return true;
00432 }
00433 
00434 const KDL::JntArray& Armature::getJointArray()
00435 {
00436     return m_qKdl;
00437 }
00438 
00439 bool Armature::updateJoint(const Timestamp& timestamp, JointLockCallback& callback)
00440 {
00441     if (!m_finalized)
00442         return false;
00443     
00444     // integration and joint limit
00445     // for spherical joint we must use a more sophisticated method
00446     unsigned int q_nr;
00447     double* qdot=&m_qdotKdl(0);
00448     double* q=&m_qKdl(0);
00449     double* newq=&m_newqKdl(0);
00450     double norm, qx, qz, CX, CZ, sx, sz;
00451     bool locked = false;
00452     int unlocked = 0;
00453 
00454     for (q_nr=0; q_nr<m_nq; ++q_nr)
00455         m_qdotKdl(q_nr)=m_qdot(q_nr);
00456 
00457     for (q_nr=0; q_nr<m_nq; ) {
00458         Joint_struct* joint = &m_joints[q_nr];
00459         if (!joint->locked) {
00460             switch (joint->type) {
00461             case KDL::Joint::Swing:
00462             {
00463                 KDL::Rotation base = KDL::Rot(KDL::Vector(q[0],0.0,q[1]));
00464                 (base*KDL::Rot(KDL::Vector(qdot[0],0.0,qdot[1])*timestamp.realTimestep)).GetXZRot().GetValue(newq);
00465                 if (joint[0].useLimit) {
00466                     if (joint[1].useLimit) {
00467                         // elliptical limit
00468                         sx = sz = 1.0;
00469                         qx = newq[0];
00470                         qz = newq[1];
00471                         // determine in which quadrant we are
00472                         if (qx > 0.0 && qz > 0.0) {
00473                             CX = joint[0].max;
00474                             CZ = joint[1].max;
00475                         } else if (qx <= 0.0 && qz > 0.0) {
00476                             CX = -joint[0].min;
00477                             CZ = joint[1].max;
00478                             qx = -qx;
00479                             sx = -1.0;
00480                         } else if (qx <= 0.0 && qz <= 0.0) {
00481                             CX = -joint[0].min;
00482                             CZ = -joint[1].min;
00483                             qx = -qx;
00484                             qz = -qz;
00485                             sx = sz = -1.0;
00486                         } else {
00487                             CX = joint[0].max;
00488                             CZ = -joint[0].min;
00489                             qz = -qz;
00490                             sz = -1.0;
00491                         }
00492                         if (CX < KDL::epsilon || CZ < KDL::epsilon) {
00493                             // quadrant is degenerated
00494                             if (qx > CX) {
00495                                 newq[0] = CX*sx;
00496                                 joint[0].locked = true;
00497                             }
00498                             if (qz > CZ) {
00499                                 newq[1] = CZ*sz;
00500                                 joint[0].locked = true;
00501                             }
00502                         } else {
00503                             // general case
00504                             qx /= CX;
00505                             qz /= CZ;
00506                             norm = KDL::sqrt(KDL::sqr(qx)+KDL::sqr(qz));
00507                             if (norm > 1.0) {
00508                                 norm = 1.0/norm;
00509                                 newq[0] = qx*norm*CX*sx;
00510                                 newq[1] = qz*norm*CZ*sz;
00511                                 joint[0].locked = true;
00512                             }
00513                         }
00514                     } else {
00515                         // limit on X only
00516                         qx = newq[0];
00517                         if (qx > joint[0].max) {
00518                             newq[0] = joint[0].max;
00519                             joint[0].locked = true;
00520                         } else if (qx < joint[0].min) {
00521                             newq[0] = joint[0].min;
00522                             joint[0].locked = true;
00523                         }
00524                     }
00525                 } else if (joint[1].useLimit) {
00526                     // limit on Z only
00527                     qz = newq[1];
00528                     if (qz > joint[1].max) {
00529                         newq[1] = joint[1].max;
00530                         joint[0].locked = true;
00531                     } else if (qz < joint[1].min) {
00532                         newq[1] = joint[1].min;
00533                         joint[0].locked = true;
00534                     }
00535                 }
00536                 if (joint[0].locked) {
00537                     // check the difference from previous position
00538                     locked = true;
00539                     norm = KDL::sqr(newq[0]-q[0])+KDL::sqr(newq[1]-q[1]);
00540                     if (norm < KDL::epsilon2) {
00541                         // joint didn't move, no need to update the jacobian
00542                         callback.lockJoint(q_nr, 2);
00543                     } else {
00544                         // joint moved, compute the corresponding velocity
00545                         double deltaq[2];
00546                         (base.Inverse()*KDL::Rot(KDL::Vector(newq[0],0.0,newq[1]))).GetXZRot().GetValue(deltaq);
00547                         deltaq[0] /= timestamp.realTimestep;
00548                         deltaq[1] /= timestamp.realTimestep;
00549                         callback.lockJoint(q_nr, 2, deltaq);
00550                         // no need to update the other joints, it will be done after next rerun
00551                         goto end_loop;
00552                     }
00553                 } else
00554                     unlocked++;
00555                 break;
00556             }
00557             case KDL::Joint::Sphere:
00558             {
00559                 (KDL::Rot(KDL::Vector(q))*KDL::Rot(KDL::Vector(qdot)*timestamp.realTimestep)).GetRot().GetValue(newq);
00560                 // no limit on this joint
00561                 unlocked++;
00562                 break;
00563             }
00564             default:
00565                 for (unsigned int i=0; i<joint->ndof; i++) {
00566                     newq[i] = q[i]+qdot[i]*timestamp.realTimestep;
00567                     if (joint[i].useLimit) {
00568                         if (newq[i] > joint[i].max) {
00569                             newq[i] = joint[i].max;
00570                             joint[0].locked = true;
00571                         } else if (newq[i] < joint[i].min) {
00572                             newq[i] = joint[i].min;
00573                             joint[0].locked = true;
00574                         }
00575                     }
00576                 }
00577                 if (joint[0].locked) {
00578                     locked = true;
00579                     norm = 0.0;
00580                     // compute delta to locked position
00581                     for (unsigned int i=0; i<joint->ndof; i++) {
00582                         qdot[i] = newq[i] - q[i];
00583                         norm += qdot[i]*qdot[i];
00584                     }
00585                     if (norm < KDL::epsilon2) {
00586                         // joint didn't move, no need to update the jacobian
00587                         callback.lockJoint(q_nr, joint->ndof);
00588                     } else {
00589                         // solver needs velocity, compute equivalent velocity
00590                         for (unsigned int i=0; i<joint->ndof; i++) {
00591                             qdot[i] /= timestamp.realTimestep;
00592                         }
00593                         callback.lockJoint(q_nr, joint->ndof, qdot);
00594                         goto end_loop;
00595                     }
00596                 } else 
00597                     unlocked++;
00598             }
00599         }
00600         qdot += joint->ndof;
00601         q    += joint->ndof;
00602         newq += joint->ndof;
00603         q_nr += joint->ndof;
00604     }
00605 end_loop:
00606     // check if there any other unlocked joint
00607     for ( ; q_nr<m_nq; ) {
00608         Joint_struct* joint = &m_joints[q_nr];
00609         if (!joint->locked)
00610             unlocked++;
00611         q_nr += joint->ndof;
00612     }
00613     // if all joints have been locked no need to run the solver again
00614     return (unlocked) ? locked : false;
00615 }
00616 
00617 void Armature::updateKinematics(const Timestamp& timestamp){
00618 
00619     //Integrate m_qdot
00620     if (!m_finalized)
00621         return;
00622 
00623     // the new joint value have been computed already, just copy
00624     memcpy(&m_qKdl(0), &m_newqKdl(0), sizeof(double)*m_qKdl.rows());
00625     pushCache(timestamp);
00626     updateJacobian();
00627     // here update the desired output.
00628     // We assume constant desired output for the joint limit constraint, no need to update it.
00629 }
00630 
00631 void Armature::updateJacobian()
00632 {
00633     //calculate pose and jacobian
00634     for (unsigned int ee=0; ee<m_nee; ee++) {
00635         m_fksolver->JntToCart(m_qKdl,m_effectors[ee].pose,m_effectors[ee].name,m_root);
00636         m_jacsolver->JntToJac(m_qKdl,*m_jac,m_effectors[ee].name);
00637         // get the jacobian for the base point, to prepare transformation to world reference
00638         changeRefPoint(*m_jac,-m_effectors[ee].pose.p,*m_jac);
00639         //copy to Jq:
00640         e_matrix& Jq = m_JqArray[ee];
00641         for(unsigned int i=0;i<6;i++) {
00642             for(unsigned int j=0;j<m_nq;j++)
00643                 Jq(i,j)=(*m_jac)(i,j);
00644         }
00645     }
00646     // remember that this object has moved 
00647     m_updated = true;
00648 }
00649 
00650 const Frame& Armature::getPose(const unsigned int ee)
00651 {
00652     if (!m_finalized)
00653         return F_identity;
00654     return (ee >= m_nee) ? F_identity : m_effectors[ee].pose;
00655 }
00656 
00657 bool Armature::getRelativeFrame(Frame& result, const std::string& segment_name, const std::string& base_name)
00658 {
00659     if (!m_finalized)
00660         return false;
00661     return (m_fksolver->JntToCart(m_qKdl,result,segment_name,base_name) < 0) ? false : true;
00662 }
00663 
00664 void Armature::updateControlOutput(const Timestamp& timestamp)
00665 {
00666     if (!m_finalized)
00667         return;
00668 
00669 
00670     if (!timestamp.substep && !timestamp.reiterate && timestamp.interpolate) {
00671         popQ(timestamp.cacheTimestamp);
00672         //popConstraints(timestamp.cacheTimestamp);
00673     }
00674 
00675     if (!timestamp.substep) {
00676         // save previous joint state for getMaxJointChange()
00677         memcpy(&m_oldqKdl(0), &m_qKdl(0), sizeof(double)*m_qKdl.rows());
00678         for (unsigned int i=0; i<m_neffector; i++) {
00679             m_effectors[i].oldpose = m_effectors[i].pose;
00680         }
00681     }
00682 
00683     // remove all joint lock
00684     for (JointList::iterator jit=m_joints.begin(); jit!=m_joints.end(); ++jit) {
00685         (*jit).locked = false;
00686     }
00687 
00688     JointConstraintList::iterator it;
00689     unsigned int iConstraint;
00690 
00691     // scan through the constraints and call the callback functions
00692     for (iConstraint=0, it=m_constraints.begin(); it!=m_constraints.end(); it++, iConstraint++) {
00693         JointConstraint_struct* pConstraint = *it;
00694         unsigned int nr, i;
00695         for (i=0, nr = pConstraint->segment->second.q_nr; i<pConstraint->v_nr; i++, nr++) {
00696             *(double*)&pConstraint->value[i].y = m_qKdl(nr);
00697             *(double*)&pConstraint->value[i].ydot = m_qdotKdl(nr);
00698         }
00699         if (pConstraint->function && (pConstraint->substep || (!timestamp.reiterate && !timestamp.substep))) {
00700             (*pConstraint->function)(timestamp, pConstraint->values, pConstraint->v_nr, pConstraint->param);
00701         }
00702         // recompute the weight in any case, that's the most likely modification
00703         for (i=0, nr=pConstraint->y_nr; i<pConstraint->v_nr; i++, nr++) {
00704             m_Wy(nr) = pConstraint->values[i].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
00705             m_ydot(nr)=pConstraint->value[i].yddot+pConstraint->values[i].feedback*(pConstraint->value[i].yd-pConstraint->value[i].y);
00706         }
00707     }
00708 }
00709 
00710 bool Armature::setControlParameter(unsigned int constraintId, unsigned int valueId, ConstraintAction action, double value, double timestep)
00711 {
00712     unsigned int lastid, i;
00713     if (constraintId == CONSTRAINT_ID_ALL) {
00714         constraintId = 0;
00715         lastid = m_nconstraint;
00716     } else if (constraintId < m_nconstraint) {
00717         lastid = constraintId+1;
00718     } else {
00719         return false;
00720     }
00721     for ( ; constraintId<lastid; ++constraintId) {
00722         JointConstraint_struct* pConstraint = m_constraints[constraintId];
00723         if (valueId == ID_JOINT) {
00724             for (i=0; i<pConstraint->v_nr; i++) {
00725                 switch (action) {
00726                 case ACT_TOLERANCE:
00727                     pConstraint->values[i].tolerance = value;
00728                     break;
00729                 case ACT_FEEDBACK:
00730                     pConstraint->values[i].feedback = value;
00731                     break;
00732                 case ACT_ALPHA:
00733                     pConstraint->values[i].alpha = value;
00734                     break;
00735                 default:
00736                     break;
00737                 }
00738             }
00739         } else {
00740             for (i=0; i<pConstraint->v_nr; i++) {
00741                 if (valueId == pConstraint->value[i].id) {
00742                     switch (action) {
00743                     case ACT_VALUE:
00744                         pConstraint->value[i].yd = value;
00745                         break;
00746                     case ACT_VELOCITY:
00747                         pConstraint->value[i].yddot = value;
00748                         break;
00749                     case ACT_TOLERANCE:
00750                         pConstraint->values[i].tolerance = value;
00751                         break;
00752                     case ACT_FEEDBACK:
00753                         pConstraint->values[i].feedback = value;
00754                         break;
00755                     case ACT_ALPHA:
00756                         pConstraint->values[i].alpha = value;
00757                         break;
00758                     case ACT_NONE:
00759                         break;
00760                     }
00761                 }
00762             }
00763         }
00764         if (m_finalized) {
00765             for (i=0; i<pConstraint->v_nr; i++) 
00766                 m_Wy(pConstraint->y_nr+i) = pConstraint->values[i].alpha/*/(pConstraint->values.tolerance*pConstraint->values.feedback)*/;
00767         }
00768     }
00769     return true;
00770 }
00771 
00772 }
00773