Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | File List | Namespace Members | Class Members | File Members | Related Pages

robot/control/kinematics/AnalyticLagrangianFSBetaOptimizer.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002   Copyright (C)2002 David Jung <opensim@pobox.com>
00003 
00004   This program/file is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU General Public License as published by
00006   the Free Software Foundation; either version 2 of the License, or
00007   (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. (http://www.gnu.org)
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
00016   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017 
00018   $Id: AnalyticLagrangianFSBetaOptimizer.cpp 1036 2004-02-11 20:48:55Z jungd $
00019   $Revision: 1.11 $
00020   $Date: 2004-02-11 15:48:55 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022 
00023 ****************************************************************************/
00024 
00025 #include <robot/control/kinematics/AnalyticLagrangianFSBetaOptimizer>
00026 #include <robot/control/kinematics/ReferenceOpVectorFormObjective>
00027 #include <robot/control/kinematics/solution_error>
00028 
00029 using base::transpose;
00030 using robot::control::kinematics::AnalyticLagrangianFSBetaOptimizer;
00031 
00032 using robot::control::kinematics::ReferenceOpVectorFormObjective;
00033 using robot::control::kinematics::BetaFormConstraints;
00034 using robot::control::kinematics::solution_error;
00035 
00036 
00037 
00038 base::Vector AnalyticLagrangianFSBetaOptimizer::optimize(ref<const Objective> objective,
00039                                                          ref<const Constraints> constraints) const
00040 {
00041   if (!instanceof(*objective, const ReferenceOpVectorFormObjective))
00042     throw std::invalid_argument(Exception("objective is not in the required form (ReferenceOpVectorFormObjective)"));
00043   ref<const ReferenceOpVectorFormObjective> rovfObjective(narrow_ref<const ReferenceOpVectorFormObjective>(objective));
00044 
00045   if (!instanceof(*constraints, const BetaFormConstraints))
00046     throw std::invalid_argument(Exception("constraints are not of the required form (BetaFormConstraints)"));
00047   ref<const BetaFormConstraints> betaConstraints(narrow_ref<const BetaFormConstraints>(constraints));
00048 
00049   if (!gs)
00050     throw std::runtime_error(Exception("no Gs supplied via setGs()"));
00051   const Matrix& gs(*(this->gs));
00052 
00053   const Int span = gs.size2();
00054 
00055 
00056   // first calculate the Matrix G and the Vector H (from paper)
00057   Matrix B( rovfObjective->getB() );
00058   Vector dZr( rovfObjective->getdZr() );
00059 
00060   Matrix G(span,span);
00061   Matrix BtB( transpose(B) * B ); 
00062   for(Int j=0; j<span; j++) {
00063     Vector gj( matrixColumn(gs,j) );
00064     Vector BtBgj( BtB*gj );
00065     for(Int i=0; i<span; i++) {
00066       Vector gi( matrixColumn(gs,i) );
00067       G(i,j) = dot( gi, BtBgj ); // i.e. Gij = gi.Bt.B.gj ; eqn. (1-12)
00068     }
00069   }
00070 
00071   Matrix Ginv;
00072   try { 
00073     Ginv = Math::inverse(G); 
00074   } catch (std::exception& e) {
00075     throw solution_error(Exception("unable to invert Grammian G:"+String(e.what())));
00076   }
00077   
00078 
00079   Vector H(span);
00080   if (equals(dZr,zeroVector(dZr.size()))) {
00081     H = zeroVector(span); // if dZr=0, so does H
00082   }
00083   else {
00084     Vector dZrtB( dZr*B );
00085     for(Int k=0; k<span; k++)
00086       H[k] = dot( dZrtB, matrixColumn(gs,k) ); // eqn. (1-11)
00087   }
00088 
00089   
00090   // compute t so that we can get dq.
00091 
00092   // convenience
00093   o.reset(zeroVector(span));
00094   e.resize(span);
00095   for(Int i=0; i<span; i++) e[i]=1;
00096 
00097   Vector t( calct(Ginv, H, betaConstraints, nullSpace) );
00098   Assert(t.size() == span);
00099 
00100   // check the tis sum appropriately
00101   Real s=0;
00102   for(Int i=0; i<t.size(); i++) s+=t[i];
00103   if (!Math::equals(s,nullSpace?0:1,0.00001))
00104     throw solution_error(Exception("failed to find a solution meeting the criteria and constraints (sum of tis=" 
00105                              + base::realToString(s) +"), but should be "+base::realToString(nullSpace?0:1)));
00106 
00107   // finally, we can calculate dq
00108   Vector dq( gs.size1() );
00109   dq = zeroVector( gs.size1() );
00110   for(Int i=0; i<span; i++)
00111     dq += t[i]*matrixColumn(gs,i);
00112 
00113   return dq;
00114 }
00115 
00116 
00117 
00118 base::Vector AnalyticLagrangianFSBetaOptimizer::calct(const Matrix& Ginv, const Vector& H, ref<const BetaFormConstraints> betaConstraints, bool nullSpace) const
00119 {
00120   //
00121   // 4 cases:
00122   //  1)   no betas &   no alpha (alpha is the non-holonomic constraint) 
00123   //  2)      betas but no alpha
00124   //  3)   no betas but an alpha
00125   //  4) both betas and an alpha
00126   //
00127 
00128   const Int span = Ginv.size1();
00129   Vector t(span);  // solution coeffs
00130 
00131   
00132   if (betaConstraints->numBetaConstraints() == 0) { // cases 1&3 - no betas
00133     
00134     // computations common to both cases
00135     
00136     // a = eT.Ginv.e  - i.e. the sum of the elements of Ginv
00137     Real a = dot( e, Ginv*e );
00138     Vector GinvH( Ginv * H );
00139     
00140     
00141     if (!betaConstraints->isAlphaConstraint()) { // case 1 - no betas &   no alpha
00142       
00143       if (Math::equals(a,0))
00144         throw solution_error(Exception("optimization failed: a=0"));
00145       
00146       Real etGinvH = dot(e, GinvH);
00147       
00148       Real b = -( (nullSpace?0:1) + etGinvH)/a; // (NB: this isn't the b from paper - it's analogous to mu)
00149       
00150       t = -Ginv*(b*e + H);
00151       
00152     }
00153     else { // case 3 - no betas but an alpha
00154 
00155       Vector alpha( betaConstraints->getAlpha() );
00156       if (equals(alpha,e))
00157         throw solution_error(Exception("optimization failed: alpha=e=(1,1,..,1) - undeterminable"));
00158 
00159       // f = eT.Ginv.H
00160       Real f = dot(e, GinvH); 
00161       
00162       // f term: ft = f if null-space solution required, 1+f otherwise
00163       Real ft = nullSpace?0:1 + f;
00164       
00165       // k = alphaT.Ginv.H                          eqn. (2-35)
00166       Real k = dot(alpha, GinvH);
00167       
00168       // l = eT.Ginv.alpha                          eqn. (2-36)
00169       Vector etGinv( e * Ginv );
00170       Real l = dot(etGinv, alpha);
00171       
00172       // s = alphaT.Ginv.alpha                      eqn. (2-37)
00173       Real s = dot(alpha, Ginv*alpha);
00174 
00175       // now calculate eta, the multipliers mu, nu and gi coeffs t
00176       Real l2msa = Math::sqr(l) - s*a;
00177       Real eta = (a*k - l*ft) / l2msa;       // eqn. (2-33) without terms involving betas
00178       Real mu = -(ft + eta*l) / a;           // eqn. (2-32) without terms involving betas
00179 
00180       t = -Ginv*(H + mu*e + eta*alpha);      // eqn. (2-31) without terms involving betas
00181       
00182       // check that NH constraint holds    
00183       Assert(alpha.size()==t.size());  
00184       Real sum=0;
00185       for(Int i=0; i<alpha.size(); i++)
00186         sum+= alpha[i]*t[i];
00187       if (!Math::equals(sum,0,1e-9)) {
00188         throw solution_error(Exception("Solution generated violates NonHolonomic constraint (Sum alphai.ti != 0)"));
00189       }
00190 
00191     }
00192 
00193 
00194   }
00195   else { // cases 2 & 4 - with betas
00196 
00197     // computations common to both cases
00198     
00199     // compute the intermediates a,b,d and A from the papers
00200     //  so that we can evaluate the Largange multipliers mu & nu and
00201     //  finally t 
00202     
00203     Matrix betas(betaConstraints->getBetas()); // each beta is a column 
00204     Int r = betas.size2(); // number of constraints
00205     
00206     // a = eT.Ginv.e  - i.e. the sum of the elements of Ginv
00207     Real a = inner_prod( e, Ginv*e );
00208     
00209     if (Math::equals(a,0))
00210       throw solution_error(Exception("optimization failed: a=0"));
00211     
00212     // b, bi = eT.Ginv.betai
00213     Vector b(r);
00214     Vector etGinv( e * Ginv );
00215     for(Int i=0; i<r; i++) 
00216       b[i] = inner_prod( etGinv, matrixColumn(betas,i) );
00217     // NB: paper 1 also has c, ci = betaiT.Ginv.e, which is actually = bi, hence redundant
00218     
00219     // d, di = 1 + betaiT.Ginv.H
00220     Vector d(r);
00221     Vector GinvH( Ginv * H );
00222     for(Int i=0; i<r; i++) 
00223       d[i] = 1.0 + inner_prod( matrixColumn(betas, i), GinvH );
00224     
00225     // f = eT.Ginv.H
00226     Real f = inner_prod(e, GinvH); 
00227     
00228     // f term: ft = f if null-space solution required, 1+f otherwise
00229     Real ft = nullSpace?0:1 + f;
00230 
00231 
00232     if (!betaConstraints->isAlphaConstraint()) { // case 2 - betas but no alpha
00233       
00234       // A, Aij = bi.bj - a.betaiT.Ginv.betaj    (paper 1)
00235       Matrix A(r,r);
00236       for(Int j=0; j<r; j++) {
00237         Vector Ginvbetaj( Ginv * Vector(matrixColumn(betas,j)) );
00238         for(Int i=0; i<r; i++) 
00239           A(i,j) = b[i]*b[j] - a*inner_prod( matrixColumn(betas,i), Ginvbetaj );
00240       }
00241       Matrix Ainv( Math::inverse(A) );
00242       
00243       
00244       // now calculate the multipliers mu, nu and gi coeffs t
00245       Vector nu( Ainv*(a*d - b*ft) );     // eqn. (1-15/18 : 2-13)
00246       Real mu = -( inner_prod(nu,b) + ft)/a; // eqn. (1-16/19 : 2-14)
00247       
00248       Vector Bnu( betas*nu );
00249       t = -Ginv*(mu*e + Bnu + H); // eqn. (1-17 : 2-15)
00250       
00251     }
00252     else { // case 4 - both betas and an alpha
00253       
00254       Vector alpha( betaConstraints->getAlpha() );
00255       if (equals(alpha,e))
00256         throw solution_error(Exception("optimization failed: alpha=e=(1,1,..,1) - undeterminable"));
00257       
00258       // k = alphaT.Ginv.H                          eqn. (2-35)
00259       Real k = inner_prod(alpha, GinvH);
00260       
00261       // l = eT.Ginv.alpha                          eqn. (2-36)
00262       Real l = inner_prod(etGinv, alpha);
00263       
00264       // s = alphaT.Ginv.alpha                      eqn. (2-37)
00265       Real s = inner_prod(alpha, Ginv*alpha);
00266       
00267       // c, ci = betaiT.Ginv.alpha                  eqn. (2-38)
00268       Vector c(r);
00269       Vector Ginvalpha( Ginv*alpha );
00270       for(Int i=0; i<r; i++)
00271         c[i] = inner_prod( matrixColumn(betas,i), Ginvalpha );
00272       
00273       Real l2msa = Math::sqr(l) - s*a;
00274       
00275       if (Math::equals(l2msa,0))
00276         throw solution_error(Exception("optimization failed: l^2-s.a=0"));
00277       
00278       // A, Aij = bi.(s.bj - l.cj) + ci.(a.cj - l.bj) + (l^2 - s.a).betaiT.Ginv.betaj   eqn. (2-39)
00279       Matrix A(r,r);
00280       for(Int j=0; j<r; j++) {
00281         Real sbjmlcj = s*b[j] - l*c[j];
00282         Real acjmlbj = a*c[j] - l*b[j];
00283         Vector Ginvbetaj( Ginv * Vector(matrixColumn(betas,j)) );
00284         for(Int i=0; i<r; i++) 
00285           A(i,j) = b[i]*sbjmlcj + c[i]*acjmlbj + l2msa*inner_prod( matrixColumn(betas,i), Ginvbetaj );
00286       }
00287       
00288       Matrix Ainv( Math::inverse(A) );
00289       
00290       // now calculate eta, the multipliers mu, nu and gi coeffs t
00291       Vector nu( Ainv*((l*k - s*ft)*b - (a*k - l*ft)*c -  l2msa*d) ); // eqn. (2-34)
00292       Real eta = (a*k - l*ft - inner_prod(nu,l*b-a*c)) / l2msa;       // eqn. (2-33)
00293       Real mu = -(ft + inner_prod(nu,b) + eta*l) / a;                 // eqn. (2-32)
00294       
00295       
00296       Vector Bnu( betas*nu );
00297       t = -Ginv*(H + mu*e + Bnu + eta*alpha);   // eqn. (2-31)
00298 
00299     }
00300     
00301 
00302   }
00303   
00304   return t;
00305   
00306 }
00307 
00308 

Generated on Thu Jul 29 15:56:31 2004 for OpenSim by doxygen 1.3.6