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

robot/control/kinematics/AnalyticLagrangianNullSpaceBetaOptimizer.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: AnalyticLagrangianNullSpaceBetaOptimizer.cpp 1036 2004-02-11 20:48:55Z jungd $
00019   $Revision: 1.1 $
00020   $Date: 2004-02-11 15:48:55 -0500 (Wed, 11 Feb 2004) $
00021   $Author: jungd $
00022 
00023 ****************************************************************************/
00024 
00025 #include <robot/control/kinematics/AnalyticLagrangianNullSpaceBetaOptimizer>
00026 #include <robot/control/kinematics/ReferenceOpVectorFormObjective>
00027 #include <robot/control/kinematics/solution_error>
00028 
00029 using base::transpose;
00030 using robot::control::kinematics::AnalyticLagrangianNullSpaceBetaOptimizer;
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 AnalyticLagrangianNullSpaceBetaOptimizer::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) );
00098   Assert(t.size() == span);
00099 
00100   // finally, we can calculate dq
00101   Vector dq( gs.size1() );
00102   dq = zeroVector( gs.size1() );
00103   for(Int i=0; i<span; i++)
00104     dq += t[i]*matrixColumn(gs,i);
00105 
00106   return dq;
00107 }
00108 
00109 
00110 
00111 base::Vector AnalyticLagrangianNullSpaceBetaOptimizer::calct(const Matrix& Ginv, const Vector& H, ref<const BetaFormConstraints> betaConstraints) const
00112 {
00113   //
00114   // 4 cases:
00115   //  1)   no betas &   no alpha (alpha is the non-holonomic constraint) 
00116   //  2)      betas but no alpha
00117   //  3)   no betas but an alpha
00118   //  4) both betas and an alpha
00119   //
00120 
00121   const Int span = Ginv.size1();
00122   Vector t(span);  // solution coeffs
00123 
00124   
00125   if (betaConstraints->numBetaConstraints() == 0) { // cases 1&3 - no betas
00126     
00127     // trivial.  Since we're after a null-space solution and there are no
00128     //  contraints to drive the system, the solution is 0
00129     t = zeroVector(span);      
00130       
00131   }
00132   else { // cases 2 & 4 - with betas
00133 
00134     // computations common to both cases
00135     
00136     // compute the intermediates a,b,d and A from the papers
00137     //  so that we can evaluate the Largange multipliers mu & nu and
00138     //  finally t 
00139     
00140     Matrix betas(betaConstraints->getBetas()); // each beta is a column 
00141     Int r = betas.size2(); // number of constraints
00142     
00143     // d, di = -(1 + betaiT.Ginv.H)
00144     Vector d(r);
00145     Vector GinvH( Ginv * H );
00146     for(Int i=0; i<r; i++) 
00147       d[i] = -(1.0 + inner_prod( matrixColumn(betas, i), GinvH ));
00148     
00149 
00150     if (!betaConstraints->isAlphaConstraint()) { // case 2 - betas but no alpha
00151       
00152       // A, Aij = betaiT.Ginv.betaj    
00153       Matrix A(r,r);
00154       for(Int j=0; j<r; j++) {
00155         Vector Ginvbetaj( Ginv * Vector(matrixColumn(betas,j)) );
00156         for(Int i=0; i<r; i++) 
00157           A(i,j) = inner_prod( matrixColumn(betas,i), Ginvbetaj );
00158       }
00159       Matrix Ainv( Math::inverse(A) );
00160       
00161       
00162       // now calculate the multipliers nu and gi coeffs t
00163       Vector nu( Ainv*d );     // A*nu = d
00164       
00165       Vector Bnu( betas*nu );
00166       t = -Ginv*(Bnu + H); 
00167       
00168     }
00169     else { // case 4 - both betas and an alpha
00170       
00171       throw solution_error(Exception("Null-space solution with non-holonomic constraint not implemented."));
00172 
00173     }
00174     
00175 
00176   }
00177   
00178   return t;
00179   
00180 }
00181 
00182 

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