qpOASES.cpp
Go to the documentation of this file.
00001 /*
00002  *      This file is part of qpOASES.
00003  *
00004  *      qpOASES -- An Implementation of the Online Active Set Strategy.
00005  *      Copyright (C) 2007-2011 by Hans Joachim Ferreau, Andreas Potschka,
00006  *      Christian Kirches et al. All rights reserved.
00007  *
00008  *      qpOASES is free software; you can redistribute it and/or
00009  *      modify it under the terms of the GNU Lesser General Public
00010  *      License as published by the Free Software Foundation; either
00011  *      version 2.1 of the License, or (at your option) any later version.
00012  *
00013  *      qpOASES is distributed in the hope that it will be useful,
00014  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
00015  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00016  *      See the GNU Lesser General Public License for more details.
00017  *
00018  *      You should have received a copy of the GNU Lesser General Public
00019  *      License along with qpOASES; if not, write to the Free Software
00020  *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00021  *
00022  */
00023 
00024 
00036 #include <qpOASES/QProblem.hpp>
00037 
00038 
00039 using namespace qpOASES;
00040 
00041 #include "qpOASES_matlab_utils.cpp"
00042 
00043 
00044 
00045 /*
00046  *      q p O A S E S m e x _ c o n s t r a i n t s
00047  */
00048 void qpOASESmex_constraints(    int nV, int nC, int nP,
00049                                                                 SymmetricMatrix *H, real_t* g, Matrix *A,
00050                                                                 real_t* lb, real_t* ub, real_t* lbA, real_t* ubA,
00051                                                                 int nWSRin, real_t* x0, Options* options,
00052                                                                 int nOutputs, mxArray* plhs[]
00053                                                                 )
00054 {
00055         /* 1) Setup initial QP. */
00056         QProblem QP( nV,nC );
00057         QP.setOptions( *options );
00058 
00059         /* 2) Solve initial QP. */
00060         returnValue returnvalue;
00061 
00062         if ( x0 == 0 )
00063                 returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRin,0 );
00064         else
00065                 returnvalue = QP.init( H,g,A,lb,ub,lbA,ubA, nWSRin,0, x0,0,0,0 );
00066 
00067         /* 3) Solve remaining QPs and assign lhs arguments. */
00068         /*    Set up pointers to the current QP vectors */
00069         real_t* g_current   = g;
00070         real_t* lb_current  = lb;
00071         real_t* ub_current  = ub;
00072         real_t* lbA_current = lbA;
00073         real_t* ubA_current = ubA;
00074 
00075         /* Loop through QP sequence. */
00076         for ( int k=0; k<nP; ++k )
00077         {
00078                 if ( k != 0 )
00079                 {
00080                         /* update pointers to the current QP vectors */
00081                         g_current = &(g[k*nV]);
00082                         if ( lb != 0 )
00083                                 lb_current = &(lb[k*nV]);
00084                         if ( ub != 0 )
00085                                 ub_current = &(ub[k*nV]);
00086                         if ( lbA != 0 )
00087                                 lbA_current = &(lbA[k*nC]);
00088                         if ( ubA != 0 )
00089                                 ubA_current = &(ubA[k*nC]);
00090 
00091                         returnvalue = QP.hotstart( g_current,lb_current,ub_current,lbA_current,ubA_current, nWSRin,0 );
00092                 }
00093 
00094                 /* write results into output vectors */
00095                 obtainOutputs(  k,&QP,returnvalue,nWSRin,
00096                                                 nOutputs,plhs,nV,nC );
00097         }
00098 
00099         return;
00100 }
00101 
00102 
00103 /*
00104  *      q p O A S E S m e x _ b o u n d s
00105  */
00106 void qpOASESmex_bounds( int nV, int nP,
00107                                                 SymmetricMatrix *H, real_t* g,
00108                                                 real_t* lb, real_t* ub,
00109                                                 int nWSRin, real_t* x0, Options* options,
00110                                                 int nOutputs, mxArray* plhs[]
00111                                                 )
00112 {
00113         /* 1) Setup initial QP. */
00114         QProblemB QP( nV );
00115         QP.setOptions( *options );
00116 
00117         /* 2) Solve initial QP. */
00118         returnValue returnvalue;
00119 
00120         if ( x0 == 0 )
00121                 returnvalue = QP.init( H,g,lb,ub, nWSRin,0 );
00122         else
00123                 returnvalue = QP.init( H,g,lb,ub, nWSRin,0, x0,0,0 );
00124 
00125         /* 3) Solve remaining QPs and assign lhs arguments. */
00126         /*    Set up pointers to the current QP vectors */
00127         real_t* g_current  = g;
00128         real_t* lb_current = lb;
00129         real_t* ub_current = ub;
00130 
00131         /* Loop through QP sequence. */
00132         for ( int k=0; k<nP; ++k )
00133         {
00134                 if ( k != 0 )
00135                 {
00136                         /* update pointers to the current QP vectors */
00137                         g_current = &(g[k*nV]);
00138                         if ( lb != 0 )
00139                                 lb_current = &(lb[k*nV]);
00140                         if ( ub != 0 )
00141                                 ub_current = &(ub[k*nV]);
00142 
00143                         returnvalue = QP.hotstart( g_current,lb_current,ub_current, nWSRin,0 );
00144                 }
00145 
00146                 /* write results into output vectors */
00147                 obtainOutputs(  k,&QP,returnvalue,nWSRin,
00148                                                 nOutputs,plhs,nV );
00149         }
00150 
00151         return;
00152 }
00153 
00154 
00155 
00156 /*
00157  *      m e x F u n c t i o n
00158  */
00159 void mexFunction( int nlhs, mxArray* plhs[], int nrhs, const mxArray* prhs[] )
00160 {
00161         /* inputs */
00162         SymmetricMatrix *H=0;
00163         Matrix *A=0;
00164         real_t *g=0, *A_for=0, *A_mem=0, *lb=0, *ub=0, *lbA=0, *ubA=0, *x0=0;
00165         int H_idx, g_idx, A_idx, lb_idx, ub_idx, lbA_idx, ubA_idx, x0_idx=-1, options_idx=-1;
00166 
00167         Options options;
00168         options.printLevel = PL_LOW;
00169         #ifdef __DEBUG__
00170         options.printLevel = PL_HIGH;
00171         #endif
00172         #ifdef __SUPPRESSANYOUTPUT__
00173         options.printLevel = PL_NONE;
00174         #endif
00175 
00176         /* dimensions */
00177         unsigned int nV=0, nC=0, nP=0;
00178 
00179         /* sparse matrix indices */
00180         long *Hdiag = 0;
00181 
00182         /* I) CONSISTENCY CHECKS: */
00183         /* 1) Ensure that qpOASES is called with a feasible number of input arguments. */
00184         if ( ( nrhs < 4 ) || ( nrhs > 9 ) )
00185                 mexErrMsgTxt( "ERROR (qpOASES): Invalid number of input arguments!\n    Type 'help qpOASES' for further information." );
00186 
00187         /* 2) Check for proper number of output arguments. */
00188         if ( nlhs > 5 )
00189                 mexErrMsgTxt( "ERROR (qpOASES): At most five output arguments are allowed: \n    [obj,x,y,status,nWSRout]!" );
00190         if ( nlhs < 1 )
00191                 mexErrMsgTxt( "ERROR (qpOASES): At least one output argument is required: [obj,...]!" );
00192 
00193 
00194         /* II) PREPARE RESPECTIVE QPOASES FUNCTION CALL: */
00195         /*     Choose between QProblem and QProblemB object and assign the corresponding
00196          *     indices of the input pointer array in to order to access QP data correctly. */
00197         H_idx = 0;
00198         g_idx = 1;
00199         nV = mxGetM( prhs[ H_idx ] ); /* row number of Hessian matrix */
00200         nP = mxGetN( prhs[ g_idx ] ); /* number of columns of the gradient matrix (vectors series have to be stored columnwise!) */
00201 
00202         /* 0) Check whether options are specified .*/
00203         if ( ( !mxIsEmpty( prhs[nrhs-1] ) ) && ( mxIsStruct( prhs[nrhs-1] ) ) )
00204                 options_idx = nrhs-1;
00205 
00206         /* 1) Simply bounded QP. */
00207         if ( ( ( nrhs >= 4 ) && ( nrhs <= 5 ) ) ||
00208                  ( ( options_idx > 0 ) && ( nrhs == 6 ) ) )
00209         {
00210                 lb_idx   = 2;
00211                 ub_idx   = 3;
00212 
00213                 if ( nrhs >= 5 ) /* x0 specified */
00214                         x0_idx = 4;
00215                 else
00216                         x0_idx = -1;
00217         }
00218         else
00219         {
00220                 A_idx = 2;
00221 
00222                 /* If constraint matrix is empty, use a QProblemB object! */
00223                 if ( mxIsEmpty( prhs[ A_idx ] ) )
00224                 {
00225                         lb_idx   = 3;
00226                         ub_idx   = 4;
00227 
00228                         if ( nrhs >= 8 ) /* x0 specified */
00229                                 x0_idx = 7;
00230                         else
00231                                 x0_idx = -1;
00232                 }
00233                 else
00234                 {
00235                         lb_idx   = 3;
00236                         ub_idx   = 4;
00237                         lbA_idx  = 5;
00238                         ubA_idx  = 6;
00239 
00240                         if ( nrhs >= 8 ) /* x0 specified */
00241                                 x0_idx = 7;
00242                         else
00243                                 x0_idx = -1;
00244 
00245                         nC = mxGetM( prhs[ A_idx ] ); /* row number of constraint matrix */
00246                 }
00247         }
00248 
00249 
00250         /* III) ACTUALLY PERFORM QPOASES FUNCTION CALL: */
00251         int nWSRin = 5*(nV+nC);
00252         if ( options_idx > 0 )
00253                 setupOptions( &options,prhs[options_idx],nWSRin );
00254 
00255         /* ensure that data is given in real_t precision */
00256         if ( ( mxIsDouble( prhs[ H_idx ] ) == 0 ) ||
00257                  ( mxIsDouble( prhs[ g_idx ] ) == 0 ) )
00258                 mexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in double precision!" );
00259 
00260         /* Check inputs dimensions and assign pointers to inputs. */
00261         if ( mxGetN( prhs[ H_idx ] ) != nV )
00262         {
00263                 char msg[200]; 
00264                 snprintf(msg, 199, "ERROR (qpOASES): Hessian matrix input dimension mismatch (%ld != %d)!", 
00265                                 (long int)mxGetN(prhs[H_idx]), nV);
00266                 fprintf(stderr, "%s\n", msg);
00267                 mexErrMsgTxt(msg);
00268         }
00269 
00270         /* check for sparsity */
00271         if ( mxIsSparse( prhs[ H_idx ] ) != 0 )
00272         {
00273                 long *ir = (long *)mxGetIr(prhs[H_idx]);
00274                 long *jc = (long *)mxGetJc(prhs[H_idx]);
00275                 real_t *v = (real_t*)mxGetPr(prhs[H_idx]);
00276                 /*
00277                 for (long col = 0; col < nV; col++)
00278                         for (long idx = jc[col]; idx < jc[col+1]; idx++)
00279                                 mexPrintf("   (%ld,%ld) %12.4f\n", ir[idx]+1, col+1, v[idx]);
00280                                 */
00281                 //mexPrintf( "%ld\n", ir[0] );
00282                 SymSparseMat *sH;
00283                 H = sH = new SymSparseMat(nV, nV, ir, jc, v);
00284                 Hdiag = sH->createDiagInfo();
00285         }
00286         else
00287         {
00288                 H = new SymDenseMat(nV, nV, nV, (real_t*) mxGetPr(prhs[H_idx]));
00289         }
00290 
00291         if ( smartDimensionCheck( &g,nV,nP, BT_FALSE,prhs,g_idx ) != SUCCESSFUL_RETURN )
00292                 return;
00293 
00294         if ( smartDimensionCheck( &lb,nV,nP, BT_TRUE,prhs,lb_idx ) != SUCCESSFUL_RETURN )
00295                 return;
00296 
00297         if ( smartDimensionCheck( &ub,nV,nP, BT_TRUE,prhs,ub_idx ) != SUCCESSFUL_RETURN )
00298                 return;
00299 
00300         if ( smartDimensionCheck( &x0,nV,1, BT_TRUE,prhs,x0_idx ) != SUCCESSFUL_RETURN )
00301                 return;
00302 
00303         if ( nC > 0 )
00304         {
00305                 /* ensure that data is given in real_t precision */
00306                 if ( mxIsDouble( prhs[ A_idx ] ) == 0 )
00307                         mexErrMsgTxt( "ERROR (qpOASES): All data has to be provided in real_t precision!" );
00308 
00309                 /* Check inputs dimensions and assign pointers to inputs. */
00310                 if ( mxGetN( prhs[ A_idx ] ) != nV )
00311                 {
00312                         char msg[200]; 
00313                         snprintf(msg, 199, "ERROR (qpOASES): Constraint matrix input dimension mismatch (%ld != %d)!", 
00314                                         (long int)mxGetN(prhs[A_idx]), nV);
00315                         fprintf(stderr, "%s\n", msg);
00316                         mexErrMsgTxt(msg);
00317                 }
00318 
00319                 A_for = (real_t*) mxGetPr( prhs[ A_idx ] );
00320 
00321                 if ( smartDimensionCheck( &lbA,nC,nP, BT_TRUE,prhs,lbA_idx ) != SUCCESSFUL_RETURN )
00322                         return;
00323 
00324                 if ( smartDimensionCheck( &ubA,nC,nP, BT_TRUE,prhs,ubA_idx ) != SUCCESSFUL_RETURN )
00325                         return;
00326 
00327                 /* Check for sparsity. */
00328                 if ( mxIsSparse( prhs[ A_idx ] ) != 0 )
00329                 {
00330                         long *ir = (long *)mxGetIr(prhs[A_idx]);
00331                         long *jc = (long *)mxGetJc(prhs[A_idx]);
00332                         real_t *v = (real_t*)mxGetPr(prhs[A_idx]);
00333                         A = new SparseMatrix(nC, nV, ir, jc, v);
00334                 }
00335                 else
00336                 {
00337                         /* Convert constraint matrix A from FORTRAN to C style
00338                          * (not necessary for H as it should be symmetric!). */
00339                         A_mem = new real_t[nC*nV];
00340                         convertFortranToC( A_for,nV,nC, A_mem );
00341                         A = new DenseMatrix(nC, nV, nV, A_mem );
00342             A->doFreeMemory();
00343                 }
00344         }
00345 
00346         allocateOutputs( nlhs,plhs,nV,nC,nP );
00347 
00348         if ( nC == 0 )
00349         {
00350                 /* call qpOASES */
00351                 qpOASESmex_bounds(      nV,nP,
00352                                                         H,g,
00353                                                         lb,ub,
00354                                                         nWSRin,x0,&options,
00355                                                         nlhs,plhs
00356                                                         );
00357 
00358         delete H;
00359                 if (Hdiag) delete[] Hdiag;
00360                 return;
00361                 /* 2) Call usual version including constraints (using QProblem class) */
00362         }
00363         else
00364         {
00365                 /* Call qpOASES. */
00366                 qpOASESmex_constraints( nV,nC,nP,
00367                                                                 H,g,A,
00368                                                                 lb,ub,lbA,ubA,
00369                                                                 nWSRin,x0,&options,
00370                                                                 nlhs,plhs
00371                                                                 );
00372 
00373                 delete H; delete A;
00374                 if (Hdiag) delete[] Hdiag;
00375                 return;
00376         }
00377 }
00378 
00379 /*
00380  *      end of file
00381  */


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Thu Aug 27 2015 11:59:50