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