qpOASES-3.2.0/interfaces/simulink/qpOASES_QProblem.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of qpOASES.
3  *
4  * qpOASES -- An Implementation of the Online Active Set Strategy.
5  * Copyright (C) 2007-2015 by Hans Joachim Ferreau, Andreas Potschka,
6  * Christian Kirches et al. All rights reserved.
7  *
8  * qpOASES is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * qpOASES is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  * See the GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with qpOASES; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 
24 
37 #include <stdlib.h>
38 
39 #include <qpOASES.hpp>
41 
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 
47 
48 #define S_FUNCTION_NAME qpOASES_QProblem
49 #define S_FUNCTION_LEVEL 2
51 #define MDL_START
53 #include "simstruc.h"
54 
55 
56 /* SETTINGS: */
57 #define SAMPLINGTIME -1
58 #define NCONTROLINPUTS 2
59 #define MAXITER 100
60 #define HESSIANTYPE HST_UNKNOWN
63 static void mdlInitializeSizes (SimStruct *S) /* Init sizes array */
64 {
65  int nU = NCONTROLINPUTS;
66 
67  /* Specify the number of continuous and discrete states */
68  ssSetNumContStates(S, 0);
69  ssSetNumDiscStates(S, 0);
70 
71  /* Specify the number of parameters */
72  ssSetNumSFcnParams(S, 2); /* H, A */
73  if ( ssGetNumSFcnParams(S) != ssGetSFcnParamsCount(S) )
74  return;
75 
76  /* Specify the number of intput ports */
77  if ( !ssSetNumInputPorts(S, 5) )
78  return;
79 
80  /* Specify the number of output ports */
81  if ( !ssSetNumOutputPorts(S, 4) )
82  return;
83 
84  /* Specify dimension information for the input ports */
85  ssSetInputPortVectorDimension(S, 0, DYNAMICALLY_SIZED); /* g */
86  ssSetInputPortVectorDimension(S, 1, DYNAMICALLY_SIZED); /* lb */
87  ssSetInputPortVectorDimension(S, 2, DYNAMICALLY_SIZED); /* ub */
88  ssSetInputPortVectorDimension(S, 3, DYNAMICALLY_SIZED); /* lbA */
89  ssSetInputPortVectorDimension(S, 4, DYNAMICALLY_SIZED); /* ubA */
90 
91  /* Specify dimension information for the output ports */
92  ssSetOutputPortVectorDimension(S, 0, nU ); /* uOpt */
93  ssSetOutputPortVectorDimension(S, 1, 1 ); /* fval */
94  ssSetOutputPortVectorDimension(S, 2, 1 ); /* exitflag */
95  ssSetOutputPortVectorDimension(S, 3, 1 ); /* iter */
96 
97  /* Specify the direct feedthrough status */
98  ssSetInputPortDirectFeedThrough(S, 0, 1);
99  ssSetInputPortDirectFeedThrough(S, 1, 1);
100  ssSetInputPortDirectFeedThrough(S, 2, 1);
101  ssSetInputPortDirectFeedThrough(S, 3, 1);
102  ssSetInputPortDirectFeedThrough(S, 4, 1);
103 
104  /* One sample time */
105  ssSetNumSampleTimes(S, 1);
106 
107  /* global variables:
108  * 0: problem
109  * 1: H
110  * 2: g
111  * 3: A
112  * 4: lb
113  * 5: ub
114  * 6: lbA
115  * 7: ubA
116  */
117 
118  /* Specify the size of the block's pointer work vector */
119  ssSetNumPWork(S, 8);
120 }
121 
122 
123 #if defined(MATLAB_MEX_FILE)
124 
125 #define MDL_SET_INPUT_PORT_DIMENSION_INFO
126 #define MDL_SET_OUTPUT_PORT_DIMENSION_INFO
127 
128 static void mdlSetInputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
129 {
130  if ( !ssSetInputPortDimensionInfo(S, port, dimsInfo) )
131  return;
132 }
133 
134 static void mdlSetOutputPortDimensionInfo(SimStruct *S, int_T port, const DimsInfo_T *dimsInfo)
135 {
136  if ( !ssSetOutputPortDimensionInfo(S, port, dimsInfo) )
137  return;
138 }
139 
140 #endif
141 
142 
143 static void mdlInitializeSampleTimes(SimStruct *S)
144 {
145  ssSetSampleTime(S, 0, SAMPLINGTIME);
146  ssSetOffsetTime(S, 0, 0.0);
147 }
148 
149 
150 static void mdlStart(SimStruct *S)
151 {
153 
154  int nU = NCONTROLINPUTS;
155  int size_g, size_lb, size_ub, size_lbA, size_ubA;
156  int size_H, nRows_H, nCols_H, size_A, nRows_A, nCols_A;
157  int nV, nC;
158 
159  QProblem* problem;
160 
161 
162  /* get block inputs dimensions */
163  const mxArray* in_H = ssGetSFcnParam(S, 0);
164  const mxArray* in_A = ssGetSFcnParam(S, 1);
165 
166  if ( mxIsEmpty(in_H) == 1 )
167  {
168  if ( ( HESSIANTYPE != HST_ZERO ) && ( HESSIANTYPE != HST_IDENTITY ) )
169  {
170  #ifndef __SUPPRESSANYOUTPUT__
171  mexErrMsgTxt( "ERROR (qpOASES): Hessian can only be empty if type is set to HST_ZERO or HST_IDENTITY!" );
172  #endif
173  return;
174  }
175 
176  nRows_H = 0;
177  nCols_H = 0;
178  size_H = 0;
179  }
180  else
181  {
182  nRows_H = (int)mxGetM(in_H);
183  nCols_H = (int)mxGetN(in_H);
184  size_H = nRows_H * nCols_H;
185  }
186 
187  if ( mxIsEmpty(in_A) == 1 )
188  {
189  nRows_A = 0;
190  nCols_A = 0;
191  size_A = 0;
192  }
193  else
194  {
195  nRows_A = (int)mxGetM(in_A);
196  nCols_A = (int)mxGetN(in_A);
197  size_A = nRows_A * nCols_A;
198  }
199 
200  size_g = ssGetInputPortWidth(S, 0);
201  size_lb = ssGetInputPortWidth(S, 1);
202  size_ub = ssGetInputPortWidth(S, 2);
203  size_lbA = ssGetInputPortWidth(S, 3);
204  size_ubA = ssGetInputPortWidth(S, 4);
205 
206 
207  /* dimension checks */
208  nV = size_g;
209  nC = nRows_A;
210 
211 
212  if ( MAXITER < 0 )
213  {
214  #ifndef __SUPPRESSANYOUTPUT__
215  mexErrMsgTxt( "ERROR (qpOASES): Maximum number of iterations must not be negative!" );
216  #endif
217  return;
218  }
219 
220  if ( nV <= 0 )
221  {
222  #ifndef __SUPPRESSANYOUTPUT__
223  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch!" );
224  #endif
225  return;
226  }
227 
228  if ( ( size_H != nV*nV ) && ( size_H != 0 ) )
229  {
230  #ifndef __SUPPRESSANYOUTPUT__
231  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in H!" );
232  #endif
233  return;
234  }
235 
236  if ( nRows_H != nCols_H )
237  {
238  #ifndef __SUPPRESSANYOUTPUT__
239  mexErrMsgTxt( "ERROR (qpOASES): Hessian matrix must be square matrix!" );
240  #endif
241  return;
242  }
243 
244  if ( ( nU < 1 ) || ( nU > nV ) )
245  {
246  #ifndef __SUPPRESSANYOUTPUT__
247  mexErrMsgTxt( "ERROR (qpOASES): Invalid number of control inputs!" );
248  #endif
249  return;
250  }
251 
252  if ( ( size_lb != nV ) && ( size_lb != 0 ) )
253  {
254  #ifndef __SUPPRESSANYOUTPUT__
255  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in lb!" );
256  #endif
257  return;
258  }
259 
260  if ( ( size_ub != nV ) && ( size_lb != 0 ) )
261  {
262  #ifndef __SUPPRESSANYOUTPUT__
263  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in ub!" );
264  #endif
265  return;
266  }
267 
268  if ( ( size_lbA != nC ) && ( size_lbA != 0 ) )
269  {
270  #ifndef __SUPPRESSANYOUTPUT__
271  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in lbA!" );
272  #endif
273  return;
274  }
275 
276  if ( ( size_ubA != nC ) && ( size_ubA != 0 ) )
277  {
278  #ifndef __SUPPRESSANYOUTPUT__
279  mexErrMsgTxt( "ERROR (qpOASES): Dimension mismatch in ubA!" );
280  #endif
281  return;
282  }
283 
284 
285  /* allocate QProblem object */
286  problem = new QProblem( nV,nC,HESSIANTYPE );
287  if ( problem == 0 )
288  {
289  #ifndef __SUPPRESSANYOUTPUT__
290  mexErrMsgTxt( "ERROR (qpOASES): Unable to create QProblem object!" );
291  #endif
292  return;
293  }
294 
295  Options problemOptions;
296  problemOptions.setToMPC();
297  problem->setOptions( problemOptions );
298 
299  #ifndef __DEBUG__
300  problem->setPrintLevel( PL_LOW );
301  #endif
302  #ifdef __SUPPRESSANYOUTPUT__
303  problem->setPrintLevel( PL_NONE );
304  #endif
305 
306  ssGetPWork(S)[0] = (void *) problem;
307 
308  /* allocate memory for QP data ... */
309  if ( size_H > 0 )
310  ssGetPWork(S)[1] = (void *) calloc( size_H, sizeof(real_t) ); /* H */
311  else
312  ssGetPWork(S)[1] = 0;
313 
314  ssGetPWork(S)[2] = (void *) calloc( size_g, sizeof(real_t) ); /* g */
315  ssGetPWork(S)[3] = (void *) calloc( size_A, sizeof(real_t) ); /* A */
316 
317  if ( size_lb > 0 )
318  ssGetPWork(S)[4] = (void *) calloc( size_lb, sizeof(real_t) ); /* lb */
319  else
320  ssGetPWork(S)[4] = 0;
321 
322  if ( size_ub > 0 )
323  ssGetPWork(S)[5] = (void *) calloc( size_ub, sizeof(real_t) ); /* ub */
324  else
325  ssGetPWork(S)[5] = 0;
326 
327  if ( size_lbA > 0 )
328  ssGetPWork(S)[6] = (void *) calloc( size_lbA, sizeof(real_t) ); /* lbA */
329  else
330  ssGetPWork(S)[6] = 0;
331 
332  if ( size_ubA > 0 )
333  ssGetPWork(S)[7] = (void *) calloc( size_ubA, sizeof(real_t) ); /* ubA */
334  else
335  ssGetPWork(S)[7] = 0;
336 }
337 
338 
339 static void mdlOutputs(SimStruct *S, int_T tid)
340 {
342 
343  int i;
344  int nV, nC;
345  returnValue status;
346 
347  int_t nWSR = MAXITER;
348  int nU = NCONTROLINPUTS;
349 
350  InputRealPtrsType in_g, in_lb, in_ub, in_lbA, in_ubA;
351 
352  QProblem* problem;
353  real_t *H, *g, *A, *lb, *ub, *lbA, *ubA;
354 
355  real_t *xOpt;
356 
357  real_T *out_uOpt, *out_objVal, *out_status, *out_nWSR;
358 
359 
360  /* get pointers to block inputs ... */
361  const mxArray* in_H = ssGetSFcnParam(S, 0);
362  const mxArray* in_A = ssGetSFcnParam(S, 1);
363  in_g = ssGetInputPortRealSignalPtrs(S, 0);
364  in_lb = ssGetInputPortRealSignalPtrs(S, 1);
365  in_ub = ssGetInputPortRealSignalPtrs(S, 2);
366  in_lbA = ssGetInputPortRealSignalPtrs(S, 3);
367  in_ubA = ssGetInputPortRealSignalPtrs(S, 4);
368 
369 
370  /* ... and to the QP data */
371  problem = (QProblem*)(ssGetPWork(S)[0]);
372 
373  H = (real_t *) ssGetPWork(S)[1];
374  g = (real_t *) ssGetPWork(S)[2];
375  A = (real_t *) ssGetPWork(S)[3];
376  lb = (real_t *) ssGetPWork(S)[4];
377  ub = (real_t *) ssGetPWork(S)[5];
378  lbA = (real_t *) ssGetPWork(S)[6];
379  ubA = (real_t *) ssGetPWork(S)[7];
380 
381 
382  /* setup QP data */
383  nV = ssGetInputPortWidth(S, 0); /* nV = size_g */
384  nC = (int)mxGetM(in_A); /* nC = nRows_A*/
385 
386  if ( H != 0 )
387  {
388  /* no conversion from FORTRAN to C as Hessian is symmetric! */
389  for ( i=0; i<nV*nV; ++i )
390  H[i] = (mxGetPr(in_H))[i];
391  }
392 
393  convertFortranToC( mxGetPr(in_A),nV,nC, A );
394 
395  for ( i=0; i<nV; ++i )
396  g[i] = (*in_g)[i];
397 
398  if ( lb != 0 )
399  {
400  for ( i=0; i<nV; ++i )
401  lb[i] = (*in_lb)[i];
402  }
403 
404  if ( ub != 0 )
405  {
406  for ( i=0; i<nV; ++i )
407  ub[i] = (*in_ub)[i];
408  }
409 
410  if ( lbA != 0 )
411  {
412  for ( i=0; i<nC; ++i )
413  lbA[i] = (*in_lbA)[i];
414  }
415 
416  if ( ubA != 0 )
417  {
418  for ( i=0; i<nC; ++i )
419  ubA[i] = (*in_ubA)[i];
420  }
421 
422  xOpt = new real_t[nV];
423 
424  if ( problem->getCount() == 0 )
425  {
426  /* initialise and solve first QP */
427  status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR,0 );
428  problem->getPrimalSolution( xOpt );
429  }
430  else
431  {
432  /* solve neighbouring QP using hotstart technique */
433  status = problem->hotstart( g,lb,ub,lbA,ubA, nWSR,0 );
434  if ( ( status != SUCCESSFUL_RETURN ) && ( status != RET_MAX_NWSR_REACHED ) )
435  {
436  /* if an error occurs, reset problem data structures ... */
437  problem->reset( );
438 
439  /* ... and initialise/solve again with remaining number of iterations. */
440  int_t nWSR_retry = MAXITER - nWSR;
441  status = problem->init( H,g,A,lb,ub,lbA,ubA, nWSR_retry,0 );
442  nWSR += nWSR_retry;
443 
444  }
445 
446  /* obtain optimal solution */
447  problem->getPrimalSolution( xOpt );
448  }
449 
450  /* generate block output: status information ... */
451  out_uOpt = ssGetOutputPortRealSignal(S, 0);
452  out_objVal = ssGetOutputPortRealSignal(S, 1);
453  out_status = ssGetOutputPortRealSignal(S, 2);
454  out_nWSR = ssGetOutputPortRealSignal(S, 3);
455 
456  for ( i=0; i<nU; ++i )
457  out_uOpt[i] = (real_T)(xOpt[i]);
458 
459  out_objVal[0] = (real_T)(problem->getObjVal());
460  out_status[0] = (real_t)(getSimpleStatus( status ));
461  out_nWSR[0] = (real_T)(nWSR);
462 
463  removeNaNs( out_uOpt,nU );
464  removeInfs( out_uOpt,nU );
465  removeNaNs( out_objVal,1 );
466  removeInfs( out_objVal,1 );
467 
468  delete[] xOpt;
469 }
470 
471 
472 static void mdlTerminate(SimStruct *S)
473 {
475 
476  int i;
477 
478  /* reset global message handler */
480 
481  if ( ssGetPWork(S)[0] != 0 )
482  delete ((QProblem*)(ssGetPWork(S)[0]));
483 
484  for ( i=1; i<8; ++i )
485  {
486  if ( ssGetPWork(S)[i] != 0 )
487  free( ssGetPWork(S)[i] );
488  }
489 }
490 
491 
492 #ifdef MATLAB_MEX_FILE
493 #include "simulink.c"
494 #else
495 #include "cg_sfun.h"
496 #endif
497 
498 
499 #ifdef __cplusplus
500 }
501 #endif
502 
503 
504 /*
505  * end of file
506  */
returnValue init(const real_t *const _H, const real_t *const _g, const real_t *const _A, const real_t *const _lb, const real_t *const _ub, const real_t *const _lbA, const real_t *const _ubA, int &nWSR, const real_t *const yOpt=0, real_t *const cputime=0)
Allows to pass back messages to the calling function.
returnValue hotstart(const real_t *const g_new, const real_t *const lb_new, const real_t *const ub_new, const real_t *const lbA_new, const real_t *const ubA_new, int &nWSR, real_t *const cputime)
returnValue convertFortranToC(const real_t *const A_for, int nV, int nC, real_t *const A)
#define HST_IDENTITY
#define PL_NONE
returnValue setOptions(const Options &_options)
Provides a generic way to set and pass user-specified options.
Definition: options.hpp:65
uint_t getCount() const
#define PL_LOW
#define HST_ZERO
returnValue setToMPC()
double real_t
Definition: AD_test.c:10
int_t getSimpleStatus(returnValue returnvalue, BooleanType doPrintStatus=BT_FALSE)
Implements the online active set strategy for QPs with general constraints.


acado
Author(s): Milan Vukov, Rien Quirynen
autogenerated on Mon Jun 10 2019 12:35:01