Blender V2.61 - r43446

IK_QJacobianSolver.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Original Author: Laurence
00024  * Contributor(s): Brecht
00025  *
00026  * ***** END GPL LICENSE BLOCK *****
00027  */
00028 
00034 #include <stdio.h>
00035 #include "IK_QJacobianSolver.h"
00036 #include "MT_Quaternion.h"
00037 
00038 //#include "analyze.h"
00039 IK_QJacobianSolver::IK_QJacobianSolver()
00040 {
00041     m_poleconstraint = false;
00042     m_getpoleangle = false;
00043     m_rootmatrix.setIdentity();
00044 }
00045 
00046 MT_Scalar IK_QJacobianSolver::ComputeScale()
00047 {
00048     std::vector<IK_QSegment*>::iterator seg;
00049     float length = 0.0f;
00050 
00051     for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
00052         length += (*seg)->MaxExtension();
00053     
00054     if(length == 0.0f)
00055         return 1.0f;
00056     else
00057         return 1.0f/length;
00058 }
00059 
00060 void IK_QJacobianSolver::Scale(float scale, std::list<IK_QTask*>& tasks)
00061 {
00062     std::list<IK_QTask*>::iterator task;
00063     std::vector<IK_QSegment*>::iterator seg;
00064 
00065     for (task = tasks.begin(); task != tasks.end(); task++)
00066         (*task)->Scale(scale);
00067 
00068     for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
00069         (*seg)->Scale(scale);
00070     
00071     m_rootmatrix.getOrigin() *= scale;
00072     m_goal *= scale;
00073     m_polegoal *= scale;
00074 }
00075 
00076 void IK_QJacobianSolver::AddSegmentList(IK_QSegment *seg)
00077 {
00078     m_segments.push_back(seg);
00079 
00080     IK_QSegment *child;
00081     for (child = seg->Child(); child; child = child->Sibling())
00082         AddSegmentList(child);
00083 }
00084 
00085 bool IK_QJacobianSolver::Setup(IK_QSegment *root, std::list<IK_QTask*>& tasks)
00086 {
00087     m_segments.clear();
00088     AddSegmentList(root);
00089 
00090     // assign each segment a unique id for the jacobian
00091     std::vector<IK_QSegment*>::iterator seg;
00092     int num_dof = 0;
00093 
00094     for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
00095         (*seg)->SetDoFId(num_dof);
00096         num_dof += (*seg)->NumberOfDoF();
00097     }
00098 
00099     if (num_dof == 0)
00100         return false;
00101 
00102     // compute task id's and assing weights to task
00103     int primary_size = 0, primary = 0;
00104     int secondary_size = 0, secondary = 0;
00105     MT_Scalar primary_weight = 0.0, secondary_weight = 0.0;
00106     std::list<IK_QTask*>::iterator task;
00107 
00108     for (task = tasks.begin(); task != tasks.end(); task++) {
00109         IK_QTask *qtask = *task;
00110 
00111         if (qtask->Primary()) {
00112             qtask->SetId(primary_size);
00113             primary_size += qtask->Size();
00114             primary_weight += qtask->Weight();
00115             primary++;
00116         }
00117         else {
00118             qtask->SetId(secondary_size);
00119             secondary_size += qtask->Size();
00120             secondary_weight += qtask->Weight();
00121             secondary++;
00122         }
00123     }
00124 
00125     if (primary_size == 0 || MT_fuzzyZero(primary_weight))
00126         return false;
00127 
00128     m_secondary_enabled = (secondary > 0);
00129     
00130     // rescale weights of tasks to sum up to 1
00131     MT_Scalar primary_rescale = 1.0/primary_weight;
00132     MT_Scalar secondary_rescale;
00133     if (MT_fuzzyZero(secondary_weight))
00134         secondary_rescale = 0.0;
00135     else
00136         secondary_rescale = 1.0/secondary_weight;
00137     
00138     for (task = tasks.begin(); task != tasks.end(); task++) {
00139         IK_QTask *qtask = *task;
00140 
00141         if (qtask->Primary())
00142             qtask->SetWeight(qtask->Weight()*primary_rescale);
00143         else
00144             qtask->SetWeight(qtask->Weight()*secondary_rescale);
00145     }
00146 
00147     // set matrix sizes
00148     m_jacobian.ArmMatrices(num_dof, primary_size);
00149     if (secondary > 0)
00150         m_jacobian_sub.ArmMatrices(num_dof, secondary_size);
00151 
00152     // set dof weights
00153     int i;
00154 
00155     for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
00156         for (i = 0; i < (*seg)->NumberOfDoF(); i++)
00157             m_jacobian.SetDoFWeight((*seg)->DoFId()+i, (*seg)->Weight(i));
00158 
00159     return true;
00160 }
00161 
00162 void IK_QJacobianSolver::SetPoleVectorConstraint(IK_QSegment *tip, MT_Vector3& goal, MT_Vector3& polegoal, float poleangle, bool getangle)
00163 {
00164     m_poleconstraint = true;
00165     m_poletip = tip;
00166     m_goal = goal;
00167     m_polegoal = polegoal;
00168     m_poleangle = (getangle)? 0.0f: poleangle;
00169     m_getpoleangle = getangle;
00170 }
00171 
00172 static MT_Scalar safe_acos(MT_Scalar f)
00173 {
00174     // acos that does not return NaN with rounding errors
00175     if (f <= -1.0f) return MT_PI;
00176     else if (f >= 1.0f) return 0.0;
00177     else return acos(f);
00178 }
00179 
00180 static MT_Vector3 normalize(const MT_Vector3& v)
00181 {
00182     // a sane normalize function that doesn't give (1, 0, 0) in case
00183     // of a zero length vector, like MT_Vector3.normalize
00184     MT_Scalar len = v.length();
00185     return MT_fuzzyZero(len)?  MT_Vector3(0, 0, 0): v/len;
00186 }
00187 
00188 static float angle(const MT_Vector3& v1, const MT_Vector3& v2)
00189 {
00190     return safe_acos(v1.dot(v2));
00191 }
00192 
00193 void IK_QJacobianSolver::ConstrainPoleVector(IK_QSegment *root, std::list<IK_QTask*>& tasks)
00194 {
00195     // this function will be called before and after solving. calling it before
00196     // solving gives predictable solutions by rotating towards the solution,
00197     // and calling it afterwards ensures the solution is exact.
00198 
00199     if(!m_poleconstraint)
00200         return;
00201     
00202     // disable pole vector constraint in case of multiple position tasks
00203     std::list<IK_QTask*>::iterator task;
00204     int positiontasks = 0;
00205 
00206     for (task = tasks.begin(); task != tasks.end(); task++)
00207         if((*task)->PositionTask())
00208             positiontasks++;
00209     
00210     if (positiontasks >= 2) {
00211         m_poleconstraint = false;
00212         return;
00213     }
00214 
00215     // get positions and rotations
00216     root->UpdateTransform(m_rootmatrix);
00217 
00218     const MT_Vector3 rootpos = root->GlobalStart();
00219     const MT_Vector3 endpos = m_poletip->GlobalEnd();
00220     const MT_Matrix3x3& rootbasis = root->GlobalTransform().getBasis();
00221 
00222     // construct "lookat" matrices (like gluLookAt), based on a direction and
00223     // an up vector, with the direction going from the root to the end effector
00224     // and the up vector going from the root to the pole constraint position.
00225     MT_Vector3 dir = normalize(endpos - rootpos);
00226     MT_Vector3 rootx= rootbasis.getColumn(0);
00227     MT_Vector3 rootz= rootbasis.getColumn(2);
00228     MT_Vector3 up = rootx*cos(m_poleangle) + rootz*sin(m_poleangle);
00229 
00230     // in post, don't rotate towards the goal but only correct the pole up
00231     MT_Vector3 poledir = (m_getpoleangle)? dir: normalize(m_goal - rootpos);
00232     MT_Vector3 poleup = normalize(m_polegoal - rootpos);
00233 
00234     MT_Matrix3x3 mat, polemat;
00235 
00236     mat[0] = normalize(MT_cross(dir, up));
00237     mat[1] = MT_cross(mat[0], dir);
00238     mat[2] = -dir;
00239 
00240     polemat[0] = normalize(MT_cross(poledir, poleup));
00241     polemat[1] = MT_cross(polemat[0], poledir);
00242     polemat[2] = -poledir;
00243 
00244     if(m_getpoleangle) {
00245         // we compute the pole angle that to rotate towards the target
00246         m_poleangle = angle(mat[1], polemat[1]);
00247 
00248         if(rootz.dot(mat[1]*cos(m_poleangle) + mat[0]*sin(m_poleangle)) > 0.0f)
00249             m_poleangle = -m_poleangle;
00250 
00251         // solve again, with the pole angle we just computed
00252         m_getpoleangle = false;
00253         ConstrainPoleVector(root, tasks);
00254     }
00255     else {
00256         // now we set as root matrix the difference between the current and
00257         // desired rotation based on the pole vector constraint. we use
00258         // transpose instead of inverse because we have orthogonal matrices
00259         // anyway, and in case of a singular matrix we don't get NaN's.
00260         MT_Transform trans(MT_Point3(0, 0, 0), polemat.transposed()*mat);
00261         m_rootmatrix = trans*m_rootmatrix;
00262     }
00263 }
00264 
00265 bool IK_QJacobianSolver::UpdateAngles(MT_Scalar& norm)
00266 {
00267     // assing each segment a unique id for the jacobian
00268     std::vector<IK_QSegment*>::iterator seg;
00269     IK_QSegment *qseg, *minseg = NULL;
00270     MT_Scalar minabsdelta = 1e10, absdelta;
00271     MT_Vector3 delta, mindelta;
00272     bool locked = false, clamp[3];
00273     int i, mindof = 0;
00274 
00275     // here we check if any angle limits were violated. angles whose clamped
00276     // position is the same as it was before, are locked immediate. of the
00277     // other violation angles the most violating angle is rememberd
00278     for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
00279         qseg = *seg;
00280         if (qseg->UpdateAngle(m_jacobian, delta, clamp)) {
00281             for (i = 0; i < qseg->NumberOfDoF(); i++) {
00282                 if (clamp[i] && !qseg->Locked(i)) {
00283                     absdelta = MT_abs(delta[i]);
00284 
00285                     if (absdelta < MT_EPSILON) {
00286                         qseg->Lock(i, m_jacobian, delta);
00287                         locked = true;
00288                     }
00289                     else if (absdelta < minabsdelta) {
00290                         minabsdelta = absdelta;
00291                         mindelta = delta;
00292                         minseg = qseg;
00293                         mindof = i;
00294                     }
00295                 }
00296             }
00297         }
00298     }
00299 
00300     // lock most violating angle
00301     if (minseg) {
00302         minseg->Lock(mindof, m_jacobian, mindelta);
00303         locked = true;
00304 
00305         if (minabsdelta > norm)
00306             norm = minabsdelta;
00307     }
00308 
00309     if (locked == false)
00310         // no locking done, last inner iteration, apply the angles
00311         for (seg = m_segments.begin(); seg != m_segments.end(); seg++) {
00312             (*seg)->UnLock();
00313             (*seg)->UpdateAngleApply();
00314         }
00315     
00316     // signal if another inner iteration is needed
00317     return locked;
00318 }
00319 
00320 bool IK_QJacobianSolver::Solve(
00321     IK_QSegment *root,
00322     std::list<IK_QTask*> tasks,
00323     const MT_Scalar,
00324     const int max_iterations
00325 )
00326 {
00327     float scale = ComputeScale();
00328     bool solved = false;
00329     //double dt = analyze_time();
00330 
00331     Scale(scale, tasks);
00332 
00333     ConstrainPoleVector(root, tasks);
00334 
00335     root->UpdateTransform(m_rootmatrix);
00336 
00337     // iterate
00338     for (int iterations = 0; iterations < max_iterations; iterations++) {
00339         // update transform
00340         root->UpdateTransform(m_rootmatrix);
00341 
00342         std::list<IK_QTask*>::iterator task;
00343 
00344         // compute jacobian
00345         for (task = tasks.begin(); task != tasks.end(); task++) {
00346             if ((*task)->Primary())
00347                 (*task)->ComputeJacobian(m_jacobian);
00348             else
00349                 (*task)->ComputeJacobian(m_jacobian_sub);
00350         }
00351 
00352         MT_Scalar norm = 0.0;
00353 
00354         do {
00355             // invert jacobian
00356             try {
00357                 m_jacobian.Invert();
00358                 if (m_secondary_enabled)
00359                     m_jacobian.SubTask(m_jacobian_sub);
00360             }
00361             catch (...) {
00362                 fprintf(stderr, "IK Exception\n");
00363                 return false;
00364             }
00365 
00366             // update angles and check limits
00367         } while (UpdateAngles(norm));
00368 
00369         // unlock segments again after locking in clamping loop
00370         std::vector<IK_QSegment*>::iterator seg;
00371         for (seg = m_segments.begin(); seg != m_segments.end(); seg++)
00372             (*seg)->UnLock();
00373 
00374         // compute angle update norm
00375         MT_Scalar maxnorm = m_jacobian.AngleUpdateNorm();
00376         if (maxnorm > norm)
00377             norm = maxnorm;
00378 
00379         // check for convergence
00380         if (norm < 1e-3) {
00381             solved = true;
00382             break;
00383         }
00384     }
00385 
00386     if(m_poleconstraint)
00387         root->PrependBasis(m_rootmatrix.getBasis());
00388 
00389     Scale(1.0f/scale, tasks);
00390 
00391     //analyze_add_run(max_iterations, analyze_time()-dt);
00392 
00393     return solved;
00394 }
00395