Blender V2.61 - r43446
|
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